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) @@ -2020,15 +2020,13 @@ static const clang::Type* GetFinalType(const clang::Type* Ty)
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());
if (auto Tag = FinalType->getAsTagDecl())
{
if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag))
{
// we cannot get a location in some cases of template arguments
if (!LocValid)
if (!LocValid || CTS->isCompleteDefinition())
return false;
auto TAL = &CTS->getTemplateArgs();
@ -2042,15 +2040,15 @@ bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid) @@ -2042,15 +2040,15 @@ bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
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,

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

@ -282,7 +282,7 @@ namespace CppSharp.Generator.Tests.AST @@ -282,7 +282,7 @@ namespace CppSharp.Generator.Tests.AST
Assert.AreEqual(5, template.Specializations.Count);
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].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();
Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef.");
var integerInst = typeDef.Type as TemplateSpecializationType;

1
src/Generator/AST/Utils.cs

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

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

@ -351,7 +351,9 @@ namespace CppSharp.Generators.CSharp @@ -351,7 +351,9 @@ namespace CppSharp.Generators.CSharp
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);
}
@ -545,19 +547,28 @@ namespace CppSharp.Generators.CSharp @@ -545,19 +547,28 @@ namespace CppSharp.Generators.CSharp
if (!VisitType(pointer, quals))
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();
if (Context.Function != null && pointer.IsPrimitiveTypeConvertibleToRef() &&
if (Context.Function != null && realPointer.IsPrimitiveTypeConvertibleToRef() &&
Context.MarshalKind != MarshalKind.VTableReturnValue &&
Context.Function.OperatorKind != CXXOperatorKind.Subscript)
{
var refParamPtr = string.Format("__refParamPtr{0}", Context.ParameterIndex);
var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType;
if (templateSubstitution != null)
{
var castParam = $"__{Context.Parameter.Name}{Context.ParameterIndex}";
Context.Before.WriteLine(
$"var {castParam} = ({templateSubstitution}) (object) {Context.Parameter.Name};");
Context.Before.WriteLine($"{pointer} {refParamPtr} = &{castParam};");
Context.Before.Write($"var {castParam} = ({templateSubstitution}) ");
if (realPointer != pointer)
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);
}
else
@ -569,7 +580,7 @@ namespace CppSharp.Generators.CSharp @@ -569,7 +580,7 @@ namespace CppSharp.Generators.CSharp
else
{
Context.Before.WriteLine(
$"fixed ({pointer} {refParamPtr} = &{Context.Parameter.Name})");
$"fixed ({realPointer} {refParamPtr} = &{Context.Parameter.Name})");
Context.HasCodeBlock = true;
Context.Before.WriteStartBraceIndent();
Context.Return.Write(refParamPtr);

2
src/Generator/Passes/ResolveIncompleteDeclsPass.cs

@ -33,7 +33,7 @@ namespace CppSharp.Passes @@ -33,7 +33,7 @@ namespace CppSharp.Passes
template.TemplatedDecl = template.TemplatedDecl.CompleteDeclaration ?? template.TemplatedDecl;
// store all specializations in the real template class because ClassTemplateDecl only forwards
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);
if (template.TemplatedClass.TemplateParameters.Count == 0 || complete)

17
tests/CSharp/CSharp.Tests.cs

@ -555,32 +555,31 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -555,32 +555,31 @@ public unsafe class CSharpTests : GeneratorTestFixture
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()
{
foreach (var internalType in new[]
{
typeof(CSharp.IndependentFields.__Internal),
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.DependentValueFields.Internal_Ptr),
typeof(CSharp.DependentValueFields.__Internal_Ptr),
typeof(CSharp.HasDefaultTemplateArgument.__Internalc__S_HasDefaultTemplateArgument__I___S_IndependentFields__I)
})
{
var independentFields = internalType.GetFields();
Assert.That(independentFields.Length, Is.EqualTo(1));
var independentFields = internalType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
var fieldOffset = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
Assert.That(fieldOffset.Value, Is.EqualTo(0));
}
foreach (var internalType in new Type[]
{
//typeof(CSharp.TwoTemplateArgs.Internal_Ptr),
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_int),
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_float)
typeof(CSharp.TwoTemplateArgs.__Internal_Ptr),
typeof(CSharp.TwoTemplateArgs.__Internalc__S_TwoTemplateArgs___I_I),
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));
var fieldOffsetKey = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
Assert.That(fieldOffsetKey.Value, Is.EqualTo(0));

12
tests/CSharp/CSharpTemplates.h

@ -385,6 +385,12 @@ public: @@ -385,6 +385,12 @@ public:
{
};
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:
IndependentFields<int> independentFields;
DependentValueFields<bool> dependentValueFields;
@ -399,12 +405,6 @@ private: @@ -399,12 +405,6 @@ private:
DependentValueFields<DependentValueFields<int*>> nestedDependentPointer1;
DependentValueFields<DependentValueFields<char*>> nestedDependentPointer2;
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>

Loading…
Cancel
Save