Skip to content

Commit cd5b57a

Browse files
committed
Ensured all non-system template specialisations are complete.
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent 5eb077b commit cd5b57a

File tree

7 files changed

+42
-35
lines changed

7 files changed

+42
-35
lines changed

src/CppParser/Parser.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,15 +2020,13 @@ static const clang::Type* GetFinalType(const clang::Type* Ty)
20202020

20212021
bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
20222022
{
2023-
// 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
2024-
return false;
20252023
auto FinalType = GetFinalType(QualType.getTypePtr());
20262024
if (auto Tag = FinalType->getAsTagDecl())
20272025
{
20282026
if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag))
20292027
{
20302028
// we cannot get a location in some cases of template arguments
2031-
if (!LocValid)
2029+
if (!LocValid || CTS->isCompleteDefinition())
20322030
return false;
20332031

20342032
auto TAL = &CTS->getTemplateArgs();
@@ -2042,15 +2040,15 @@ bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
20422040
return false;
20432041
}
20442042
}
2043+
auto Unit = GetTranslationUnit(Tag);
2044+
// HACK: completing all system types overflows the managed stack
2045+
// while running the AST converter since the latter is a giant indirect recursion
2046+
// this solution is a hack because we might need to complete system template specialisations
2047+
// such as std:string or std::vector in order to represent them in the target language
2048+
return !Unit->isSystemHeader;
20452049
}
2046-
auto Unit = GetTranslationUnit(Tag);
2047-
// HACK: completing all system types overflows the managed stack
2048-
// while running the AST converter since the latter is a giant indirect recursion
2049-
// this solution is a hack because we might need to complete system template specialisations
2050-
// such as std:string or std::vector in order to represent them in the target language
2051-
return !Unit->isSystemHeader;
20522050
}
2053-
return true;
2051+
return false;
20542052
}
20552053

20562054
Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,

src/Generator.Tests/AST/TestAST.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ public void TestASTClassTemplates()
282282
Assert.AreEqual(5, template.Specializations.Count);
283283
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[0].SpecializationKind);
284284
Assert.AreEqual(TemplateSpecializationKind.ExplicitInstantiationDefinition, template.Specializations[3].SpecializationKind);
285-
Assert.AreEqual(TemplateSpecializationKind.Undeclared, template.Specializations[4].SpecializationKind);
285+
Assert.AreEqual(TemplateSpecializationKind.ImplicitInstantiation, template.Specializations[4].SpecializationKind);
286286
var typeDef = AstContext.FindTypedef("TestTemplateClassInt").FirstOrDefault();
287287
Assert.IsNotNull(typeDef, "Couldn't find TestTemplateClassInt typedef.");
288288
var integerInst = typeDef.Type as TemplateSpecializationType;

src/Generator/AST/Utils.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,6 @@ private static bool IsSpecializationNeeded(Declaration container,
163163
specialization.Arguments.Any(a => UnsupportedTemplateArgument(
164164
specialization, a, typeMaps)) ||
165165
container.Namespace == specialization)) ||
166-
specialization.IsIncomplete ||
167166
(!internalOnly && specialization.TemplatedDecl.TemplatedClass.IsIncomplete) ||
168167
specialization is ClassTemplatePartialSpecialization;
169168
}

src/Generator/Generators/CSharp/CSharpMarshal.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,9 @@ public override bool VisitParameterDecl(Parameter parameter)
351351

352352
public override bool VisitTemplateParameterSubstitutionType(TemplateParameterSubstitutionType param, TypeQualifiers quals)
353353
{
354-
Context.Return.Write("({0}) (object) ", param.ReplacedParameter.Parameter.Name);
354+
Context.Return.Write($"({param.ReplacedParameter.Parameter.Name}) (object) ");
355+
if (param.Replacement.Type.Desugar().IsPointerToPrimitiveType())
356+
Context.Return.Write($"({CSharpTypePrinter.IntPtrType}) ");
355357
return base.VisitTemplateParameterSubstitutionType(param, quals);
356358
}
357359

@@ -545,19 +547,28 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
545547
if (!VisitType(pointer, quals))
546548
return false;
547549

550+
var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType;
551+
PointerType realPointer = null;
552+
if (templateSubstitution != null)
553+
realPointer = templateSubstitution.Replacement.Type.Desugar() as PointerType;
554+
realPointer = realPointer ?? pointer;
548555
var pointee = pointer.Pointee.Desugar();
549-
if (Context.Function != null && pointer.IsPrimitiveTypeConvertibleToRef() &&
556+
if (Context.Function != null && realPointer.IsPrimitiveTypeConvertibleToRef() &&
550557
Context.MarshalKind != MarshalKind.VTableReturnValue &&
551558
Context.Function.OperatorKind != CXXOperatorKind.Subscript)
552559
{
553560
var refParamPtr = string.Format("__refParamPtr{0}", Context.ParameterIndex);
554-
var templateSubstitution = pointer.Pointee as TemplateParameterSubstitutionType;
555561
if (templateSubstitution != null)
556562
{
557563
var castParam = $"__{Context.Parameter.Name}{Context.ParameterIndex}";
558-
Context.Before.WriteLine(
559-
$"var {castParam} = ({templateSubstitution}) (object) {Context.Parameter.Name};");
560-
Context.Before.WriteLine($"{pointer} {refParamPtr} = &{castParam};");
564+
Context.Before.Write($"var {castParam} = ({templateSubstitution}) ");
565+
if (realPointer != pointer)
566+
Context.Before.Write($"({CSharpTypePrinter.IntPtrType}) ");
567+
Context.Before.WriteLine($"(object) {Context.Parameter.Name};");
568+
Context.Before.Write($"var {refParamPtr} = ");
569+
if (realPointer == pointer)
570+
Context.Before.Write("&");
571+
Context.Before.WriteLine($"{castParam};");
561572
Context.Return.Write(refParamPtr);
562573
}
563574
else
@@ -569,7 +580,7 @@ public override bool VisitPointerType(PointerType pointer, TypeQualifiers quals)
569580
else
570581
{
571582
Context.Before.WriteLine(
572-
$"fixed ({pointer} {refParamPtr} = &{Context.Parameter.Name})");
583+
$"fixed ({realPointer} {refParamPtr} = &{Context.Parameter.Name})");
573584
Context.HasCodeBlock = true;
574585
Context.Before.WriteStartBraceIndent();
575586
Context.Return.Write(refParamPtr);

src/Generator/Passes/ResolveIncompleteDeclsPass.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public override bool VisitClassTemplateDecl(ClassTemplate template)
3333
template.TemplatedDecl = template.TemplatedDecl.CompleteDeclaration ?? template.TemplatedDecl;
3434
// store all specializations in the real template class because ClassTemplateDecl only forwards
3535
foreach (var specialization in template.Specializations.Where(
36-
s => !s.IsIncomplete && !template.TemplatedClass.Specializations.Contains(s)))
36+
s => !template.TemplatedClass.Specializations.Contains(s)))
3737
template.TemplatedClass.Specializations.Add(specialization);
3838

3939
if (template.TemplatedClass.TemplateParameters.Count == 0 || complete)

tests/CSharp/CSharp.Tests.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -555,32 +555,31 @@ public void TestStdStringConstant()
555555
Assert.That(CSharp.HasFreeConstant.AnotherUnit.STD_STRING_CONSTANT, Is.EqualTo("test"));
556556
}
557557

558-
[Test, Ignore("The completion of types is temporarily suspended because of problems with QtWidgets.")]
558+
[Test]
559559
public void TestTemplateInternals()
560560
{
561561
foreach (var internalType in new[]
562562
{
563563
typeof(CSharp.IndependentFields.__Internal),
564564
typeof(CSharp.DependentValueFields.__Internalc__S_DependentValueFields__b),
565-
//typeof(CSharp.DependentValueFields.Internal_float),
565+
typeof(CSharp.DependentValueFields.__Internalc__S_DependentValueFields__f),
566566
typeof(CSharp.DependentPointerFields.__Internal),
567-
//typeof(CSharp.DependentValueFields.Internal_Ptr),
567+
typeof(CSharp.DependentValueFields.__Internal_Ptr),
568568
typeof(CSharp.HasDefaultTemplateArgument.__Internalc__S_HasDefaultTemplateArgument__I___S_IndependentFields__I)
569569
})
570570
{
571-
var independentFields = internalType.GetFields();
572-
Assert.That(independentFields.Length, Is.EqualTo(1));
571+
var independentFields = internalType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
573572
var fieldOffset = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
574573
Assert.That(fieldOffset.Value, Is.EqualTo(0));
575574
}
576575
foreach (var internalType in new Type[]
577576
{
578-
//typeof(CSharp.TwoTemplateArgs.Internal_Ptr),
579-
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_int),
580-
//typeof(CSharp.TwoTemplateArgs.Internal_intPtr_float)
577+
typeof(CSharp.TwoTemplateArgs.__Internal_Ptr),
578+
typeof(CSharp.TwoTemplateArgs.__Internalc__S_TwoTemplateArgs___I_I),
579+
typeof(CSharp.TwoTemplateArgs.__Internalc__S_TwoTemplateArgs___I_f)
581580
})
582581
{
583-
var independentFields = internalType.GetFields();
582+
var independentFields = internalType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
584583
Assert.That(independentFields.Length, Is.EqualTo(2));
585584
var fieldOffsetKey = (FieldOffsetAttribute) independentFields[0].GetCustomAttribute(typeof(FieldOffsetAttribute));
586585
Assert.That(fieldOffsetKey.Value, Is.EqualTo(0));

tests/CSharp/CSharpTemplates.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,12 @@ class DLL_API TemplateSpecializer
385385
{
386386
};
387387
IndependentFields<bool> getIndependentFields();
388+
void completeSpecializationInParameter(DependentValueFields<float> p1,
389+
DependentValueFields<int*> p2,
390+
DependentValueFields<float*> p3);
391+
void completeSpecializationInParameter(TwoTemplateArgs<int*, int*> p1,
392+
TwoTemplateArgs<int*, int> p2,
393+
TwoTemplateArgs<int*, float> p3);
388394
private:
389395
IndependentFields<int> independentFields;
390396
DependentValueFields<bool> dependentValueFields;
@@ -399,12 +405,6 @@ class DLL_API TemplateSpecializer
399405
DependentValueFields<DependentValueFields<int*>> nestedDependentPointer1;
400406
DependentValueFields<DependentValueFields<char*>> nestedDependentPointer2;
401407
DependentValueFieldForArray<char[3]> dependentFieldArray;
402-
void completeSpecializationInParameter(DependentValueFields<float> p1,
403-
DependentValueFields<int*> p2,
404-
DependentValueFields<float*> p3);
405-
void completeSpecializationInParameter(TwoTemplateArgs<int*, int*> p1,
406-
TwoTemplateArgs<int*, int> p2,
407-
TwoTemplateArgs<int*, float> p3);
408408
};
409409

410410
template <typename Key, typename T>

0 commit comments

Comments
 (0)