|
|
|
@ -10,20 +10,24 @@ namespace CppSharp.Passes
@@ -10,20 +10,24 @@ namespace CppSharp.Passes
|
|
|
|
|
{ |
|
|
|
|
/// <summary>
|
|
|
|
|
/// This pass generates internal classes that implement abstract classes.
|
|
|
|
|
/// When the return type of a function is abstract, these internal classes provide -
|
|
|
|
|
/// since the real type cannot be resolved while binding - an allocatable class that supports proper polymorphism.
|
|
|
|
|
/// When the return type of a function is abstract, these internal
|
|
|
|
|
/// classes provide since the real type cannot be resolved while binding
|
|
|
|
|
/// an allocatable class that supports proper polymorphism.
|
|
|
|
|
/// </summary>
|
|
|
|
|
public class GenerateAbstractImplementationsPass : TranslationUnitPass |
|
|
|
|
{ |
|
|
|
|
/// <summary>
|
|
|
|
|
/// Collects all internal implementations in a unit to be added at the end because the unit cannot be changed while it's being iterated though.
|
|
|
|
|
/// Collects all internal implementations in a unit to be added at
|
|
|
|
|
/// the end because the unit cannot be changed while it's being
|
|
|
|
|
/// iterated though.
|
|
|
|
|
/// </summary>
|
|
|
|
|
private readonly List<Class> internalImpls = new List<Class>(); |
|
|
|
|
|
|
|
|
|
public override bool VisitTranslationUnit(TranslationUnit unit) |
|
|
|
|
{ |
|
|
|
|
bool result = base.VisitTranslationUnit(unit); |
|
|
|
|
var result = base.VisitTranslationUnit(unit); |
|
|
|
|
unit.Classes.AddRange(internalImpls); |
|
|
|
|
|
|
|
|
|
internalImpls.Clear(); |
|
|
|
|
return result; |
|
|
|
|
} |
|
|
|
@ -44,6 +48,7 @@ namespace CppSharp.Passes
@@ -44,6 +48,7 @@ namespace CppSharp.Passes
|
|
|
|
|
ctor.Access = AccessSpecifier.Protected; |
|
|
|
|
internalImpls.Add(AddInternalImplementation(@class)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return base.VisitClassDecl(@class); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -57,6 +62,7 @@ namespace CppSharp.Passes
@@ -57,6 +62,7 @@ namespace CppSharp.Passes
|
|
|
|
|
{ |
|
|
|
|
var method = new Method(abstractMethod) { Namespace = internalImpl }; |
|
|
|
|
internalImpl.Methods.Add(method); |
|
|
|
|
|
|
|
|
|
var @delegate = new TypedefDecl |
|
|
|
|
{ |
|
|
|
|
Name = ASTHelpers.GetDelegateName(abstractMethod), |
|
|
|
@ -77,6 +83,7 @@ namespace CppSharp.Passes
@@ -77,6 +83,7 @@ namespace CppSharp.Passes
|
|
|
|
|
method.IsOverride = true; |
|
|
|
|
method.IsSynthetized = true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return internalImpl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -88,8 +95,10 @@ namespace CppSharp.Passes
@@ -88,8 +95,10 @@ namespace CppSharp.Passes
|
|
|
|
|
Access = @class.Access, |
|
|
|
|
Namespace = @class.Namespace |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
var @base = new BaseClassSpecifier { Type = new TagType(@class) }; |
|
|
|
|
internalImpl.Bases.Add(@base); |
|
|
|
|
|
|
|
|
|
return internalImpl; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -98,7 +107,8 @@ namespace CppSharp.Passes
@@ -98,7 +107,8 @@ namespace CppSharp.Passes
|
|
|
|
|
var abstractMethods = GetAbstractMethods(@class); |
|
|
|
|
var overriddenMethods = GetOverriddenMethods(@class); |
|
|
|
|
var paramTypeCmp = new ParameterTypeComparer(); |
|
|
|
|
for (int i = abstractMethods.Count - 1; i >= 0; i--) |
|
|
|
|
|
|
|
|
|
for (var i = abstractMethods.Count - 1; i >= 0; i--) |
|
|
|
|
{ |
|
|
|
|
var @abstract = abstractMethods[i]; |
|
|
|
|
if (overriddenMethods.Find(m => m.Name == @abstract.Name && |
|
|
|
@ -109,6 +119,7 @@ namespace CppSharp.Passes
@@ -109,6 +119,7 @@ namespace CppSharp.Passes
|
|
|
|
|
abstractMethods.RemoveAt(i); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return abstractMethods; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -117,6 +128,7 @@ namespace CppSharp.Passes
@@ -117,6 +128,7 @@ namespace CppSharp.Passes
|
|
|
|
|
var abstractMethods = @class.Methods.Where(m => m.IsPure).ToList(); |
|
|
|
|
foreach (var @base in @class.Bases) |
|
|
|
|
abstractMethods.AddRange(GetAbstractMethods(@base.Class)); |
|
|
|
|
|
|
|
|
|
return abstractMethods; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -125,6 +137,7 @@ namespace CppSharp.Passes
@@ -125,6 +137,7 @@ namespace CppSharp.Passes
|
|
|
|
|
var abstractMethods = @class.Methods.Where(m => m.IsOverride).ToList(); |
|
|
|
|
foreach (var @base in @class.Bases) |
|
|
|
|
abstractMethods.AddRange(GetOverriddenMethods(@base.Class)); |
|
|
|
|
|
|
|
|
|
return abstractMethods; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -144,57 +157,63 @@ namespace CppSharp.Passes
@@ -144,57 +157,63 @@ namespace CppSharp.Passes
|
|
|
|
|
private static void CreateVTableMS(Class @class, |
|
|
|
|
IList<Method> abstractMethods, Class internalImplementation) |
|
|
|
|
{ |
|
|
|
|
var vTables = GetVTables(@class); |
|
|
|
|
var vtables = GetVTables(@class); |
|
|
|
|
for (int i = 0; i < abstractMethods.Count; i++) |
|
|
|
|
{ |
|
|
|
|
for (int j = 0; j < vTables.Count; j++) |
|
|
|
|
for (int j = 0; j < vtables.Count; j++) |
|
|
|
|
{ |
|
|
|
|
var vTable = vTables[j]; |
|
|
|
|
var vTable = vtables[j]; |
|
|
|
|
var k = vTable.Layout.Components.FindIndex(v => v.Method == abstractMethods[i]); |
|
|
|
|
if (k >= 0) |
|
|
|
|
{ |
|
|
|
|
var vTableComponent = vTable.Layout.Components[k]; |
|
|
|
|
vTableComponent.Declaration = internalImplementation.Methods[i]; |
|
|
|
|
vTable.Layout.Components[k] = vTableComponent; |
|
|
|
|
vTables[j] = vTable; |
|
|
|
|
vtables[j] = vTable; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internalImplementation.Layout.VFTables.Clear(); |
|
|
|
|
internalImplementation.Layout.VFTables.AddRange(vTables); |
|
|
|
|
internalImplementation.Layout.VFTables.AddRange(vtables); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static void CreateVTableItanium(Class @class, |
|
|
|
|
IList<Method> abstractMethods, Class internalImplementation) |
|
|
|
|
{ |
|
|
|
|
var vTableComponents = GetVTableComponents(@class); |
|
|
|
|
for (int i = 0; i < abstractMethods.Count; i++) |
|
|
|
|
var vtableComponents = GetVTableComponents(@class); |
|
|
|
|
for (var i = 0; i < abstractMethods.Count; i++) |
|
|
|
|
{ |
|
|
|
|
var j = vTableComponents.FindIndex(v => v.Method == abstractMethods[i]); |
|
|
|
|
var vTableComponent = vTableComponents[j]; |
|
|
|
|
vTableComponent.Declaration = internalImplementation.Methods[i]; |
|
|
|
|
vTableComponents[j] = vTableComponent; |
|
|
|
|
var j = vtableComponents.FindIndex(v => v.Method == abstractMethods[i]); |
|
|
|
|
var vtableComponent = vtableComponents[j]; |
|
|
|
|
vtableComponent.Declaration = internalImplementation.Methods[i]; |
|
|
|
|
vtableComponents[j] = vtableComponents[j]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
internalImplementation.Layout.Layout.Components.Clear(); |
|
|
|
|
internalImplementation.Layout.Layout.Components.AddRange(vTableComponents); |
|
|
|
|
internalImplementation.Layout.Layout.Components.AddRange(vtableComponents); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static List<VTableComponent> GetVTableComponents(Class @class) |
|
|
|
|
{ |
|
|
|
|
var vTableComponents = new List<VTableComponent>( |
|
|
|
|
var vtableComponents = new List<VTableComponent>( |
|
|
|
|
@class.Layout.Layout.Components); |
|
|
|
|
|
|
|
|
|
foreach (var @base in @class.Bases) |
|
|
|
|
vTableComponents.AddRange(GetVTableComponents(@base.Class)); |
|
|
|
|
return vTableComponents; |
|
|
|
|
vtableComponents.AddRange(GetVTableComponents(@base.Class)); |
|
|
|
|
|
|
|
|
|
return vtableComponents; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static List<VFTableInfo> GetVTables(Class @class) |
|
|
|
|
{ |
|
|
|
|
var vTables = new List<VFTableInfo>( |
|
|
|
|
var vtables = new List<VFTableInfo>( |
|
|
|
|
@class.Layout.VFTables); |
|
|
|
|
|
|
|
|
|
foreach (var @base in @class.Bases) |
|
|
|
|
vTables.AddRange(GetVTables(@base.Class)); |
|
|
|
|
return vTables; |
|
|
|
|
vtables.AddRange(GetVTables(@base.Class)); |
|
|
|
|
|
|
|
|
|
return vtables; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|