Browse Source

Ensured all non-system template specialisations are complete.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/974/merge
Dimitar Dobrev 8 years ago
parent
commit
cd5b57a786
  1. 18
      src/CppParser/Parser.cpp
  2. 2
      src/Generator.Tests/AST/TestAST.cs
  3. 1
      src/Generator/AST/Utils.cs
  4. 25
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  5. 2
      src/Generator/Passes/ResolveIncompleteDeclsPass.cs
  6. 17
      tests/CSharp/CSharp.Tests.cs
  7. 12
      tests/CSharp/CSharpTemplates.h

18
src/CppParser/Parser.cpp

@ -2020,15 +2020,13 @@ static const clang::Type* GetFinalType(const clang::Type* Ty)
bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid) bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
{ {
// HACK: the completion of types is temporarily suspended because of problems with QtWidgets; will restore when it's time to wrap functions in template types
return false;
auto FinalType = GetFinalType(QualType.getTypePtr()); auto FinalType = GetFinalType(QualType.getTypePtr());
if (auto Tag = FinalType->getAsTagDecl()) if (auto Tag = FinalType->getAsTagDecl())
{ {
if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag)) if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag))
{ {
// we cannot get a location in some cases of template arguments // we cannot get a location in some cases of template arguments
if (!LocValid) if (!LocValid || CTS->isCompleteDefinition())
return false; return false;
auto TAL = &CTS->getTemplateArgs(); auto TAL = &CTS->getTemplateArgs();
@ -2042,15 +2040,15 @@ bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
return false; return false;
} }
} }
auto Unit = GetTranslationUnit(Tag);
// HACK: completing all system types overflows the managed stack
// while running the AST converter since the latter is a giant indirect recursion
// this solution is a hack because we might need to complete system template specialisations
// such as std:string or std::vector in order to represent them in the target language
return !Unit->isSystemHeader;
} }
auto Unit = GetTranslationUnit(Tag);
// HACK: completing all system types overflows the managed stack
// while running the AST converter since the latter is a giant indirect recursion
// this solution is a hack because we might need to complete system template specialisations
// such as std:string or std::vector in order to represent them in the target language
return !Unit->isSystemHeader;
} }
return true; return false;
} }
Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL, Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,

2
src/Generator.Tests/AST/TestAST.cs

@ -282,7 +282,7 @@ namespace CppSharp.Generator.Tests.AST
Assert.AreEqual(5, template.Specializations.Count); Assert.AreEqual(5, template.Specializations.Count);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].SpecializationKind); Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[3].SpecializationKind); Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[3].SpecializationKind);
Assert.AreEqual(TemplateSpecializationKind.Undeclared, template.Specializations[4].SpecializationKind); Assert.AreEqual(TemplateSpecializationKind.ImplicitInstantiation, template.Specializations[4].SpecializationKind);
var typeDef = AstContext.FindTypedef("TestTemplateClassInt").FirstOrDefault(); var typeDef = AstContext.FindTypedef("TestTemplateClassInt").FirstOrDefault();
Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef."); Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef.");
var integerInst = typeDef.Type as TemplateSpecializationType; var integerInst = typeDef.Type as TemplateSpecializationType;

1
src/Generator/AST/Utils.cs

@ -163,7 +163,6 @@ namespace CppSharp.AST
specialization.Arguments.Any(a => UnsupportedTemplateArgument( specialization.Arguments.Any(a => UnsupportedTemplateArgument(
specialization, a, typeMaps)) || specialization, a, typeMaps)) ||
container.Namespace == specialization)) || container.Namespace == specialization)) ||
specialization.IsIncomplete ||
(!internalOnly && specialization.TemplatedDecl.TemplatedClass.IsIncomplete) || (!internalOnly && specialization.TemplatedDecl.TemplatedClass.IsIncomplete) ||
specialization is ClassTemplatePartialSpecialization; specialization is ClassTemplatePartialSpecialization;
} }

25
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -351,7 +351,9 @@ namespace CppSharp.Generators.CSharp
public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals) public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals)
{ {
Context.Return.Write("({0}) (object) ", param.ReplacedParameter.Parameter.Name); Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) ");
if (param.Replacement.Type.Desugar().IsPointerToPrimitiveType())
Context.Return.Write($"({CSharpTypePrinter.IntPtrType}) ");
return base.VisitTemplateParameterSubstitutionType(param, quals); return base.VisitTemplateParameterSubstitutionType(param, quals);
} }
@ -545,19 +547,28 @@ namespace CppSharp.Generators.CSharp
if (!VisitType(pointer, quals)) if (!VisitType(pointer, quals))
return false; return false;
var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType;
PointerType realPointer = null;
if (templateSubstitution != null)
realPointer = templateSubstitution.Replacement.Type.Desugar() as PointerType;
realPointer = realPointer ?? pointer;
var pointee = pointer.Pointee.Desugar(); var pointee = pointer.Pointee.Desugar();
if (Context.Function != null && pointer.IsPrimitiveTypeConvertibleToRef() && if (Context.Function != null && realPointer.IsPrimitiveTypeConvertibleToRef() &&
Context.MarshalKind != MarshalKind.VTableReturnValue && Context.MarshalKind != MarshalKind.VTableReturnValue &&
Context.Function.OperatorKind != CXXOperatorKind.Subscript) Context.Function.OperatorKind != CXXOperatorKind.Subscript)
{ {
var refParamPtr = string.Format("__refParamPtr{0}", Context.ParameterIndex); var refParamPtr = string.Format("__refParamPtr{0}", Context.ParameterIndex);
var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType;
if (templateSubstitution != null) if (templateSubstitution != null)
{ {
var castParam = $"__{Context.Parameter.Name}{Context.ParameterIndex}"; var castParam = $"__{Context.Parameter.Name}{Context.ParameterIndex}";
Context.Before.WriteLine( Context.Before.Write($"var {castParam} = ({templateSubstitution}) ");
$"var {castParam} = ({templateSubstitution}) (object) {Context.Parameter.Name};"); if (realPointer != pointer)
Context.Before.WriteLine($"{pointer} {refParamPtr} = &{castParam};"); Context.Before.Write($"({CSharpTypePrinter.IntPtrType}) ");
Context.Before.WriteLine($"(object) {Context.Parameter.Name};");
Context.Before.Write($"var {refParamPtr} = ");
if (realPointer == pointer)
Context.Before.Write("&");
Context.Before.WriteLine($"{castParam};");
Context.Return.Write(refParamPtr); Context.Return.Write(refParamPtr);
} }
else else
@ -569,7 +580,7 @@ namespace CppSharp.Generators.CSharp
else else
{ {
Context.Before.WriteLine( Context.Before.WriteLine(
$"fixed ({pointer} {refParamPtr} = &{Context.Parameter.Name})"); $"fixed ({realPointer} {refParamPtr} = &{Context.Parameter.Name})");
Context.HasCodeBlock = true; Context.HasCodeBlock = true;
Context.Before.WriteStartBraceIndent(); Context.Before.WriteStartBraceIndent();
Context.Return.Write(refParamPtr); Context.Return.Write(refParamPtr);

2
src/Generator/Passes/ResolveIncompleteDeclsPass.cs

@ -33,7 +33,7 @@ namespace CppSharp.Passes
template.TemplatedDecl = template.TemplatedDecl.CompleteDeclaration ?? template.TemplatedDecl; template.TemplatedDecl = template.TemplatedDecl.CompleteDeclaration ?? template.TemplatedDecl;
// store all specializations in the real template class because ClassTemplateDecl only forwards // store all specializations in the real template class because ClassTemplateDecl only forwards
foreach (var specialization in template.Specializations.Where( foreach (var specialization in template.Specializations.Where(
s => !s.IsIncomplete && !template.TemplatedClass.Specializations.Contains(s))) s => !template.TemplatedClass.Specializations.Contains(s)))
template.TemplatedClass.Specializations.Add(specialization); template.TemplatedClass.Specializations.Add(specialization);
if (template.TemplatedClass.TemplateParameters.Count == 0 || complete) if (template.TemplatedClass.TemplateParameters.Count == 0 || complete)

17
tests/CSharp/CSharp.Tests.cs

@ -555,32 +555,31 @@ public unsafe class CSharpTests : GeneratorTestFixture
Assert.That(CSharp.HasFreeConstant.AnotherUnit.STD_STRING_CONSTANT, Is.EqualTo("test")); Assert.That(CSharp.HasFreeConstant.AnotherUnit.STD_STRING_CONSTANT, Is.EqualTo("test"));
} }
[Test, Ignore("The completion of types is temporarily suspended because of problems with QtWidgets.")] [Test]
public void TestTemplateInternals() public void TestTemplateInternals()
{ {
foreach (var internalType in new[] foreach (var internalType in new[]
{ {
typeof(CSharp.IndependentFields.__Internal), typeof(CSharp.IndependentFields.__Internal),
typeof(CSharp.DependentValueFields.__Internalc__S_DependentValueFields__b), typeof(CSharp.DependentValueFields.__Internalc__S_DependentValueFields__b),
//typeof(CSharp.DependentValueFields.Internal_float), typeof(CSharp.DependentValueFields.__Internalc__S_DependentValueFields__f),
typeof(CSharp.DependentPointerFields.__Internal), typeof(CSharp.DependentPointerFields.__Internal),
//typeof(CSharp.DependentValueFields.Internal_Ptr), typeof(CSharp.DependentValueFields.__Internal_Ptr),
typeof(CSharp.HasDefaultTemplateArgument.__Internalc__S_HasDefaultTemplateArgument__I___S_IndependentFields__I) typeof(CSharp.HasDefaultTemplateArgument.__Internalc__S_HasDefaultTemplateArgument__I___S_IndependentFields__I)
}) })
{ {
var independentFields = internalType.GetFields(); var independentFields = internalType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
Assert.That(independentFields.Length, Is.EqualTo(1));
var fieldOffset = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute)); var fieldOffset = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
Assert.That(fieldOffset.Value, Is.EqualTo(0)); Assert.That(fieldOffset.Value, Is.EqualTo(0));
} }
foreach (var internalType in new Type[] foreach (var internalType in new Type[]
{ {
//typeof(CSharp.TwoTemplateArgs.Internal_Ptr), typeof(CSharp.TwoTemplateArgs.__Internal_Ptr),
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_int), typeof(CSharp.TwoTemplateArgs.__Internalc__S_TwoTemplateArgs___I_I),
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_float) typeof(CSharp.TwoTemplateArgs.__Internalc__S_TwoTemplateArgs___I_f)
}) })
{ {
var independentFields = internalType.GetFields(); var independentFields = internalType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
Assert.That(independentFields.Length, Is.EqualTo(2)); Assert.That(independentFields.Length, Is.EqualTo(2));
var fieldOffsetKey = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute)); var fieldOffsetKey = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
Assert.That(fieldOffsetKey.Value, Is.EqualTo(0)); Assert.That(fieldOffsetKey.Value, Is.EqualTo(0));

12
tests/CSharp/CSharpTemplates.h

@ -385,6 +385,12 @@ public:
{ {
}; };
IndependentFields<bool> getIndependentFields(); IndependentFields<bool> getIndependentFields();
void completeSpecializationInParameter(DependentValueFields<float> p1,
DependentValueFields<int*> p2,
DependentValueFields<float*> p3);
void completeSpecializationInParameter(TwoTemplateArgs<int*, int*> p1,
TwoTemplateArgs<int*, int> p2,
TwoTemplateArgs<int*, float> p3);
private: private:
IndependentFields<int> independentFields; IndependentFields<int> independentFields;
DependentValueFields<bool> dependentValueFields; DependentValueFields<bool> dependentValueFields;
@ -399,12 +405,6 @@ private:
DependentValueFields<DependentValueFields<int*>> nestedDependentPointer1; DependentValueFields<DependentValueFields<int*>> nestedDependentPointer1;
DependentValueFields<DependentValueFields<char*>> nestedDependentPointer2; DependentValueFields<DependentValueFields<char*>> nestedDependentPointer2;
DependentValueFieldForArray<char[3]> dependentFieldArray; DependentValueFieldForArray<char[3]> dependentFieldArray;
void completeSpecializationInParameter(DependentValueFields<float> p1,
DependentValueFields<int*> p2,
DependentValueFields<float*> p3);
void completeSpecializationInParameter(TwoTemplateArgs<int*, int*> p1,
TwoTemplateArgs<int*, int> p2,
TwoTemplateArgs<int*, float> p3);
}; };
template <typename Key, typename T> template <typename Key, typename T>

Loading…
Cancel
Save