Browse Source

Delete the C++ copy when returning by value

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
llvm-debug
Dimitar Dobrev 4 years ago
parent
commit
60a994bc8b
  1. 43
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 9
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 1
      tests/CSharp/CSharpTemplates.h
  4. 9
      tests/Common/Common.Tests.cs
  5. 13
      tests/Common/Common.cpp
  6. 18
      tests/Common/Common.h

43
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -282,7 +282,48 @@ namespace CppSharp.Generators.CSharp @@ -282,7 +282,48 @@ namespace CppSharp.Generators.CSharp
if (returnType.IsAddress())
Context.Return.Write(HandleReturnedPointer(@class, qualifiedClass));
else
Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
{
if (Context.MarshalKind == MarshalKind.NativeField ||
Context.MarshalKind == MarshalKind.Variable ||
!originalClass.HasNonTrivialDestructor)
{
Context.Return.Write($"{qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName})");
}
else
{
Context.Before.WriteLine($@"var __{Context.ReturnVarName} = {
qualifiedClass}.{Helpers.CreateInstanceIdentifier}({Context.ReturnVarName});");
Method dtor = originalClass.Destructors.First();
if (dtor.IsVirtual)
{
var i = VTables.GetVTableIndex(dtor);
int vtableIndex = 0;
if (Context.Context.ParserOptions.IsMicrosoftAbi)
vtableIndex = @class.Layout.VFTables.IndexOf(@class.Layout.VFTables.First(
v => v.Layout.Components.Any(c => c.Method == dtor)));
Context.Before.WriteLine($@"var __vtables = new IntPtr[] {{ {
string.Join(", ", originalClass.Layout.VTablePointers.Select(
x => $" * (IntPtr*) ({ Helpers.InstanceIdentifier} + {x.Offset})"))} }};");
Context.Before.WriteLine($"var __slot = *(IntPtr*) (__vtables[{vtableIndex}] + {i} * sizeof(IntPtr));");
Context.Before.Write($"Marshal.GetDelegateForFunctionPointer<{dtor.FunctionType}>(__slot)({Helpers.InstanceIdentifier}");
if (dtor.GatherInternalParams(Context.Context.ParserOptions.IsItaniumLikeAbi).Count > 1)
{
Context.Before.WriteLine(", 0");
}
Context.Before.WriteLine(");");
}
else
{
string suffix = string.Empty;
var specialization = @class as ClassTemplateSpecialization;
if (specialization != null)
suffix = Helpers.GetSuffixFor(specialization);
Context.Before.WriteLine($@"{typePrinter.PrintNative(originalClass)}.dtor{
suffix}(new {typePrinter.IntPtrType}(&{Context.ReturnVarName}));");
}
Context.Return.Write($"__{Context.ReturnVarName}");
}
}
return true;
}

9
src/Generator/Generators/CSharp/CSharpSources.cs

@ -2180,10 +2180,8 @@ namespace CppSharp.Generators.CSharp @@ -2180,10 +2180,8 @@ namespace CppSharp.Generators.CSharp
// ensure any virtual dtor in the chain is called
var dtor = @class.Destructors.FirstOrDefault(d => d.Access != AccessSpecifier.Private);
var baseDtor = @class.BaseClass == null ? null :
@class.BaseClass.Destructors.FirstOrDefault(d => !d.IsVirtual);
if (ShouldGenerateClassNativeField(@class) ||
((dtor != null && (dtor.IsVirtual || @class.HasNonTrivialDestructor)) && baseDtor != null) ||
(dtor != null && (dtor.IsVirtual || @class.HasNonTrivialDestructor)) ||
// virtual destructors in abstract classes may lack a pointer in the v-table
// so they have to be called by symbol; thus we need an explicit Dispose override
@class.IsAbstract)
@ -3464,11 +3462,6 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty @@ -3464,11 +3462,6 @@ internal static{(@new ? " new" : string.Empty)} {printedClass} __GetInstance({Ty
if (function.IsPure)
return;
if (function.OriginalName == "system_do_it")
{
System.Diagnostics.Debugger.Break();
}
PushBlock(BlockKind.InternalsClassMethod);
var callConv = function.CallingConvention.ToInteropCallConv();

1
tests/CSharp/CSharpTemplates.h

@ -794,6 +794,7 @@ template class DLL_API Base<int>; @@ -794,6 +794,7 @@ template class DLL_API Base<int>;
template class DLL_API DependentValueFields<int>;
template class DLL_API DependentValueFields<int*>;
template class DLL_API DependentValueFields<float>;
template class DLL_API DependentValueFields<double>;
template class DLL_API DependentPointerFields<float>;
template class DLL_API VirtualTemplate<int>;
template class DLL_API VirtualTemplate<bool>;

9
tests/Common/Common.Tests.cs

@ -1127,6 +1127,15 @@ This is a very long string. This is a very long string. This is a very long stri @@ -1127,6 +1127,15 @@ This is a very long string. This is a very long string. This is a very long stri
}
}
[Test]
public void TestReturnByValueWithReturnParam()
{
using (var returnByValueWithReturnParam = ReturnByValueWithReturnParamFactory.Generate())
{
Assert.That(returnByValueWithReturnParam.UseCount, Is.EqualTo(1));
}
}
[Test, Ignore("This was exposed by another bug and doesn't work yet.")]
public void TestFreeFunctionReturnByValue()
{

13
tests/Common/Common.cpp

@ -1336,6 +1336,19 @@ HasPropertyNamedAsParent::~HasPropertyNamedAsParent() @@ -1336,6 +1336,19 @@ HasPropertyNamedAsParent::~HasPropertyNamedAsParent()
{
}
ReturnByValueWithReturnParam::ReturnByValueWithReturnParam() {}
ReturnByValueWithReturnParam::ReturnByValueWithReturnParam(const ReturnByValueWithReturnParam& other) : _ptr(other._ptr) {}
ReturnByValueWithReturnParam::~ReturnByValueWithReturnParam() {}
int ReturnByValueWithReturnParam::getUseCount() { return _ptr.use_count(); }
ReturnByValueWithReturnParam ReturnByValueWithReturnParamFactory::generate()
{
return ReturnByValueWithReturnParam();
}
void integerOverload(int i)
{
}

18
tests/Common/Common.h

@ -1355,6 +1355,24 @@ public: @@ -1355,6 +1355,24 @@ public:
int hasPropertyNamedAsParent;
};
class DLL_API ReturnByValueWithReturnParam
{
public:
ReturnByValueWithReturnParam();
ReturnByValueWithReturnParam(const ReturnByValueWithReturnParam& other);
~ReturnByValueWithReturnParam();
int getUseCount();
private:
std::shared_ptr<int> _ptr = std::shared_ptr<int>(new int[1]);
};
class DLL_API ReturnByValueWithReturnParamFactory
{
public:
static ReturnByValueWithReturnParam generate();
};
template<typename T> void TemplatedFunction(T type)
{

Loading…
Cancel
Save