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
ComplementOperator, ComplementOperator,
AbstractImplCall, AbstractImplCall,
DefaultValueOverload, DefaultValueOverload,
InterfaceInstance InterfaceInstance,
AdjustedMethod
} }
public class Function : Declaration, ITypedDecl, IMangledDecl public class Function : Declaration, ITypedDecl, IMangledDecl

3
src/AST/Method.cs

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

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

@ -496,7 +496,8 @@ namespace CppSharp.Generators.CSharp
Action<Method> tryAddOverload = method => Action<Method> tryAddOverload = method =>
{ {
if (method.IsSynthetized) if (method.IsSynthetized &&
method.SynthKind != FunctionSynthKind.AdjustedMethod)
return; return;
if (method.IsProxy) if (method.IsProxy)
@ -2298,6 +2299,8 @@ namespace CppSharp.Generators.CSharp
else else
{ {
names.Insert(instanceIndex, Helpers.InstanceIdentifier); 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 @@
using System.Collections.Generic; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using CppSharp.AST; using CppSharp.AST;
using CppSharp.Generators.CSharp; using CppSharp.Generators.CSharp;
@ -24,10 +25,79 @@ namespace CppSharp.Passes
return result; 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) public override bool VisitClassDecl(Class @class)
{ {
if (AlreadyVisited(@class))
return false;
CheckNonVirtualInheritedFunctions(@class);
// skip the first base because we can inherit from one 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; var @base = @class.Bases[i].Class;
if (@base.IsInterface) continue; if (@base.IsInterface) continue;

2
src/Generator/Passes/RenamePass.cs

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

12
tests/CSharpTemp/CSharpTemp.Tests.cs

@ -188,4 +188,16 @@ public class CSharpTempTests : GeneratorTestFixture
{ {
Assert.AreEqual(5, Foo.Rename); 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:
IgnoredType<int> _ignoredType; 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 class DLL_API StructWithPrivateFields
{ {
public: public:

Loading…
Cancel
Save