Browse Source

Added support for handling non-virtual methods inherited from MI bases.

pull/406/merge
triton 11 years ago
parent
commit
1e0db93c5e
  1. 3
      src/AST/Function.cs
  2. 3
      src/AST/Method.cs
  3. 5
      src/Generator/Generators/CSharp/CSharpTextTemplate.cs
  4. 74
      src/Generator/Passes/MultipleInheritancePass.cs
  5. 2
      src/Generator/Passes/RenamePass.cs
  6. 12
      tests/CSharpTemp/CSharpTemp.Tests.cs
  7. 35
      tests/CSharpTemp/CSharpTemp.h

3
src/AST/Function.cs

@ -94,7 +94,8 @@ namespace CppSharp.AST @@ -94,7 +94,8 @@ namespace CppSharp.AST
ComplementOperator,
AbstractImplCall,
DefaultValueOverload,
InterfaceInstance
InterfaceInstance,
AdjustedMethod
}
public class Function : Declaration, ITypedDecl, IMangledDecl

3
src/AST/Method.cs

@ -95,6 +95,7 @@ namespace CppSharp.AST @@ -95,6 +95,7 @@ namespace CppSharp.AST
IsMoveConstructor = method.IsMoveConstructor;
Conversion = method.Conversion;
SynthKind = method.SynthKind;
AdjustedOffset = method.AdjustedOffset;
}
public Method(Function function)
@ -148,6 +149,8 @@ namespace CppSharp.AST @@ -148,6 +149,8 @@ namespace CppSharp.AST
public Class ExplicitInterfaceImpl { get; set; }
public int AdjustedOffset { get; set; }
public override T Visit<T>(IDeclVisitor<T> visitor)
{
return visitor.VisitMethodDecl(this);

5
src/Generator/Generators/CSharp/CSharpTextTemplate.cs

@ -496,7 +496,8 @@ namespace CppSharp.Generators.CSharp @@ -496,7 +496,8 @@ namespace CppSharp.Generators.CSharp
Action<Method> tryAddOverload = method =>
{
if (method.IsSynthetized)
if (method.IsSynthetized &&
method.SynthKind != FunctionSynthKind.AdjustedMethod)
return;
if (method.IsProxy)
@ -2298,6 +2299,8 @@ namespace CppSharp.Generators.CSharp @@ -2298,6 +2299,8 @@ namespace CppSharp.Generators.CSharp
else
{
names.Insert(instanceIndex, Helpers.InstanceIdentifier);
if (method.SynthKind == FunctionSynthKind.AdjustedMethod)
names[instanceIndex] += " + " + method.AdjustedOffset.ToString();
}
}
}

74
src/Generator/Passes/MultipleInheritancePass.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using System.Linq;
using CppSharp.AST;
using CppSharp.Generators.CSharp;
@ -24,10 +25,79 @@ namespace CppSharp.Passes @@ -24,10 +25,79 @@ namespace CppSharp.Passes
return result;
}
public static bool ComputeClassPath(Class current, Class target,
List<BaseClassSpecifier> path)
{
if (target == current)
return true;
foreach (var @base in current.Bases)
{
path.Add(@base);
if (ComputeClassPath(@base.Class, target, path))
return false;
}
path.RemoveAt(path.Count-1);
return false;
}
public static List<BaseClassSpecifier> ComputeClassPath(Class from, Class to)
{
var path = new List<BaseClassSpecifier>();
ComputeClassPath(from, to, path);
return path;
}
int ComputeNonVirtualBaseClassOffset(Class from, Class to)
{
var bases = ComputeClassPath(from, to);
return bases.Sum(@base => @base.Offset);
}
public void CheckNonVirtualInheritedFunctions(Class @class, Class originalClass = null)
{
if (originalClass == null)
originalClass = @class;
foreach (BaseClassSpecifier baseSpecifier in @class.Bases)
{
var @base = baseSpecifier.Class;
if (@base.IsInterface) continue;
var nonVirtualOffset = ComputeNonVirtualBaseClassOffset(originalClass, @base);
if (nonVirtualOffset == 0)
continue;
foreach (var method in @base.Methods.Where(method =>
!method.IsVirtual && (method.Kind == CXXMethodKind.Normal)))
{
Console.WriteLine(method);
var adjustedMethod = new Method(method)
{
SynthKind = FunctionSynthKind.AdjustedMethod,
AdjustedOffset = nonVirtualOffset,
};
originalClass.Methods.Add(adjustedMethod);
}
CheckNonVirtualInheritedFunctions(@base, originalClass);
}
}
public override bool VisitClassDecl(Class @class)
{
if (AlreadyVisited(@class))
return false;
CheckNonVirtualInheritedFunctions(@class);
// skip the first base because we can inherit from one class
for (int i = 1; i < @class.Bases.Count; i++)
for (var i = 1; i < @class.Bases.Count; i++)
{
var @base = @class.Bases[i].Class;
if (@base.IsInterface) continue;

2
src/Generator/Passes/RenamePass.cs

@ -105,7 +105,7 @@ namespace CppSharp.Passes @@ -105,7 +105,7 @@ namespace CppSharp.Passes
declarations.AddRange(decl.Namespace.Enums);
declarations.AddRange(decl.Namespace.Events);
var function = decl as Function;
if (function != null)
if (function != null && function.SynthKind != FunctionSynthKind.AdjustedMethod)
{
// account for overloads
declarations.AddRange(GetFunctionsWithTheSameParams(function));

12
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -188,4 +188,16 @@ public class CSharpTempTests : GeneratorTestFixture @@ -188,4 +188,16 @@ public class CSharpTempTests : GeneratorTestFixture
{
Assert.AreEqual(5, Foo.Rename);
}
[Test, Ignore]
public void TestPrimarySecondaryBase()
{
var a = new MI_A0();
var resa = a.Get();
Assert.That(resa, Is.EqualTo(50));
var c = new MI_C();
var res = c.Get();
Assert.That(res, Is.EqualTo(50));
}
}

35
tests/CSharpTemp/CSharpTemp.h

@ -312,6 +312,41 @@ private: @@ -312,6 +312,41 @@ private:
IgnoredType<int> _ignoredType;
};
// --- Multiple inheritance
struct DLL_API MI_A0
{
MI_A0();
int get();
int F;
};
MI_A0::MI_A0() : F(50) {}
int MI_A0::get() { return F; };
struct DLL_API MI_A
{
MI_A();
virtual void v(int i = 5);
};
MI_A::MI_A() {}
void MI_A::v(int i) {}
struct DLL_API MI_B : public MI_A
{
MI_B();
};
MI_B::MI_B() {}
struct DLL_API MI_C : public MI_A0, public MI_B
{
MI_C();
};
MI_C::MI_C() {}
class DLL_API StructWithPrivateFields
{
public:

Loading…
Cancel
Save