From d769a81ade7000f118e4a8a8aac660c008fce74a Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Thu, 10 Sep 2015 17:52:54 +0300 Subject: [PATCH] Called virtual destructors through the virtual table. Signed-off-by: Dimitar Dobrev --- src/AST/ClassExtensions.cs | 8 ++--- .../Generators/CSharp/CSharpTextTemplate.cs | 31 ++++++++++++------- tests/CSharp/CSharp.Tests.cs | 9 ++++++ tests/CSharp/CSharp.cpp | 16 ++++++++++ tests/CSharp/CSharp.h | 9 ++++++ 5 files changed, 57 insertions(+), 16 deletions(-) diff --git a/src/AST/ClassExtensions.cs b/src/AST/ClassExtensions.cs index 4b282041..89013e66 100644 --- a/src/AST/ClassExtensions.cs +++ b/src/AST/ClassExtensions.cs @@ -61,10 +61,10 @@ namespace CppSharp.AST let baseMethod = ( from method in @base.Class.Methods where - method.OriginalName == @override.OriginalName && - method.ReturnType == @override.ReturnType && - method.Parameters.SequenceEqual(@override.Parameters, - new ParameterTypeComparer()) + (method.OriginalName == @override.OriginalName && + method.ReturnType == @override.ReturnType && + method.Parameters.SequenceEqual(@override.Parameters, new ParameterTypeComparer())) || + (@override.IsDestructor && method.IsDestructor && method.IsVirtual) select method).FirstOrDefault() let rootBaseMethod = @base.Class.GetRootBaseMethod(@override, onlyFirstBase) ?? baseMethod where rootBaseMethod != null || onlyFirstBase diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index 180482fe..f5c24312 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1889,12 +1889,16 @@ namespace CppSharp.Generators.CSharp { WriteLine("if ({0} || force)", Helpers.OwnsNativeInstanceIdentifier); - var implicitArg = string.Empty; - if (dtor.Parameters.Any(parameter => - parameter.Kind == ParameterKind.ImplicitDestructorParameter)) - implicitArg = ", 0"; // Do not delete instance in MS ABI. - WriteLineIndent("Internal.{0}({1}{2});", GetFunctionNativeIdentifier(dtor), - Helpers.InstanceIdentifier, implicitArg); + if (dtor.IsVirtual) + { + WriteStartBraceIndent(); + GenerateVirtualFunctionCall(dtor, @class); + WriteCloseBraceIndent(); + } + else + { + GenerateInternalFunctionCall(dtor); + } } } @@ -1908,10 +1912,11 @@ namespace CppSharp.Generators.CSharp private void GenerateNativeConstructor(Class @class) { - if (@class.IsRefType) + var shouldGenerateClassNativeField = ShouldGenerateClassNativeField(@class); + if (@class.IsRefType && shouldGenerateClassNativeField) { PushBlock(CSharpBlockKind.Field); - WriteLine("private bool {0};", Helpers.OwnsNativeInstanceIdentifier); + WriteLine("protected bool {0};", Helpers.OwnsNativeInstanceIdentifier); PopBlock(NewLineKind.BeforeNextBlock); } @@ -1950,7 +1955,7 @@ namespace CppSharp.Generators.CSharp if (@class.IsRefType) { - if (ShouldGenerateClassNativeField(@class)) + if (shouldGenerateClassNativeField) { WriteLine("{0} = new global::System.IntPtr(native);", Helpers.InstanceIdentifier); var dtor = @class.Destructors.FirstOrDefault(); @@ -2689,11 +2694,13 @@ namespace CppSharp.Generators.CSharp Function function = null) { PrimitiveType primitive; + // Do not delete instance in MS ABI. + var name = param.Kind == ParameterKind.ImplicitDestructorParameter ? "0" : param.Name; // returned structs must be blittable and bool and char aren't if (param.Type.IsPrimitiveType(out primitive) && primitive != PrimitiveType.Char && primitive != PrimitiveType.Bool) { - return new ParamMarshal { Name = param.Name, Param = param }; + return new ParamMarshal { Name = name, Param = param }; } var argName = "arg" + paramIndex.ToString(CultureInfo.InvariantCulture); @@ -2708,7 +2715,7 @@ namespace CppSharp.Generators.CSharp { var qualifiedIdentifier = CSharpMarshalNativeToManagedPrinter.QualifiedIdentifier( @class.OriginalClass ?? @class); - WriteLine("{0} = new {1}();", param.Name, qualifiedIdentifier); + WriteLine("{0} = new {1}();", name, qualifiedIdentifier); } } @@ -2724,7 +2731,7 @@ namespace CppSharp.Generators.CSharp if (param.Type.IsPrimitiveTypeConvertibleToRef()) { - WriteLine("fixed ({0} {1} = &{2})", param.Type.CSharpType(TypePrinter), argName, param.Name); + WriteLine("fixed ({0} {1} = &{2})", param.Type.CSharpType(TypePrinter), argName, name); paramMarshal.HasFixedBlock = true; WriteStartBraceIndent(); } diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index 45158bda..d7d361fd 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -319,6 +319,15 @@ public class CSharpTests : GeneratorTestFixture } } + [Test] + public void TestCallingVirtualDtor() + { + var callDtorVirtually = new CallDtorVirtually(); + var hasVirtualDtor1 = CallDtorVirtually.GetHasVirtualDtor1(callDtorVirtually); + hasVirtualDtor1.Dispose(); + Assert.That(CallDtorVirtually.Destroyed, Is.True); + } + [Test] public void TestParamTypeToInterfacePass() { diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index 931917db..6fd703dc 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -578,6 +578,22 @@ void TestNativeToManagedMap::setPropertyWithNoVirtualDtor(Bar* bar) this->bar = bar; } +CallDtorVirtually::CallDtorVirtually() +{ +} + +CallDtorVirtually::~CallDtorVirtually() +{ + Destroyed = true; +} + +bool CallDtorVirtually::Destroyed = false; + +HasVirtualDtor1* CallDtorVirtually::getHasVirtualDtor1(HasVirtualDtor1* returned) +{ + return returned; +} + void SecondaryBase::VirtualMember() { } diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index a7def1d1..64187bf8 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -549,6 +549,15 @@ private: Bar* bar; }; +class DLL_API CallDtorVirtually : public HasVirtualDtor1 +{ +public: + CallDtorVirtually(); + ~CallDtorVirtually(); + static bool Destroyed; + static HasVirtualDtor1* getHasVirtualDtor1(HasVirtualDtor1* returned); +}; + class HasProtectedNestedAnonymousType { protected: