diff --git a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs index d2807852..075e22e8 100644 --- a/src/Generator/Generators/CSharp/CSharpTextTemplate.cs +++ b/src/Generator/Generators/CSharp/CSharpTextTemplate.cs @@ -1694,8 +1694,11 @@ namespace CppSharp.Generators.CSharp { GenerateClassFinalizer(@class); - // Only root bases need a Dispose - if (ShouldGenerateClassNativeField(@class)) + // ensure any virtual dtor in the chain is called + var dtor = @class.Destructors.FirstOrDefault(d => d.Access != AccessSpecifier.Private && d.IsVirtual); + var baseDtor = @class.BaseClass == null ? null : + @class.BaseClass.Destructors.FirstOrDefault(d => !d.IsVirtual); + if (ShouldGenerateClassNativeField(@class) || (dtor != null && baseDtor != null)) GenerateDisposeMethods(@class); } } diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index d81230dd..3b13416a 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/tests/CSharp/CSharp.Tests.cs @@ -495,4 +495,13 @@ public class CSharpTests : GeneratorTestFixture Assert.That(multipleInheritanceFieldOffsets.Own, Is.EqualTo(3)); } } + + [Test] + public void TestVirtualDtorAddedInDerived() + { + using (new VirtualDtorAddedInDerived()) + { + } + Assert.IsTrue(VirtualDtorAddedInDerived.DtorCalled); + } } diff --git a/tests/CSharp/CSharp.cpp b/tests/CSharp/CSharp.cpp index 7bc02705..09e11389 100644 --- a/tests/CSharp/CSharp.cpp +++ b/tests/CSharp/CSharp.cpp @@ -906,3 +906,14 @@ MultipleInheritanceFieldOffsetsPrimaryBase::MultipleInheritanceFieldOffsetsPrima MultipleInheritanceFieldOffsets::MultipleInheritanceFieldOffsets() : own(3) { } + +VirtualDtorAddedInDerived::VirtualDtorAddedInDerived() +{ +} + +VirtualDtorAddedInDerived::~VirtualDtorAddedInDerived() +{ + dtorCalled = true; +} + +bool VirtualDtorAddedInDerived::dtorCalled = false; diff --git a/tests/CSharp/CSharp.h b/tests/CSharp/CSharp.h index d73e6654..c8500bfd 100644 --- a/tests/CSharp/CSharp.h +++ b/tests/CSharp/CSharp.h @@ -828,3 +828,11 @@ public: MultipleInheritanceFieldOffsets(); int own; }; + +class DLL_API VirtualDtorAddedInDerived : public Foo +{ +public: + VirtualDtorAddedInDerived(); + virtual ~VirtualDtorAddedInDerived(); + static bool dtorCalled; +}; diff --git a/tests/Common/Common.cpp b/tests/Common/Common.cpp index b946ae01..2b44ba6a 100644 --- a/tests/Common/Common.cpp +++ b/tests/Common/Common.cpp @@ -319,6 +319,11 @@ const AbstractFoo& ReturnsAbstractFoo::getFoo() return i; } +Ex2* DerivedException::clone() +{ + return 0; +} + void DefaultParameters::Foo(int a, int b) { } diff --git a/tests/Common/Common.h b/tests/Common/Common.h index cb548e2b..af74f48f 100644 --- a/tests/Common/Common.h +++ b/tests/Common/Common.h @@ -231,7 +231,7 @@ struct DLL_API Exception struct DLL_API DerivedException : public Exception { - virtual Ex2* clone() override { return 0; } + virtual Ex2* clone() override; }; // Tests for ambiguous call to native functions with default parameters @@ -920,7 +920,7 @@ class AbstractTemplate { public: AbstractTemplate(); - void abstractFunction() = 0; + virtual void abstractFunction() = 0; }; template