From 05a44565bdee6c0866d0939aca9703247b60a623 Mon Sep 17 00:00:00 2001
From: Dimitar Dobrev <dpldobrev@yahoo.com>
Date: Tue, 3 Nov 2015 19:22:11 +0200
Subject: [PATCH] Ensured a virtual dtor is called even if the base dtor is not
 virtual.

Signed-off-by: Dimitar Dobrev <dpldobrev@yahoo.com>
---
 src/Generator/Generators/CSharp/CSharpTextTemplate.cs |  7 +++++--
 tests/CSharp/CSharp.Tests.cs                          |  9 +++++++++
 tests/CSharp/CSharp.cpp                               | 11 +++++++++++
 tests/CSharp/CSharp.h                                 |  8 ++++++++
 tests/Common/Common.cpp                               |  5 +++++
 tests/Common/Common.h                                 |  4 ++--
 6 files changed, 40 insertions(+), 4 deletions(-)

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 <typename T>