From cd5b57a786c0dba5d48ad7275bc54a453ff65a6c Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Sat, 30 Sep 2017 21:56:08 +0300 Subject: [PATCH] Ensured all non-system template specialisations are complete. Signed-off-by: Dimitar Dobrev --- src/CppParser/Parser.cpp | 18 ++++++------- src/Generator.Tests/AST/TestAST.cs | 2 +- src/Generator/AST/Utils.cs | 1 - .../Generators/CSharp/CSharpMarshal.cs | 25 +++++++++++++------ .../Passes/ResolveIncompleteDeclsPass.cs | 2 +- tests/CSharp/CSharp.Tests.cs | 17 ++++++------- tests/CSharp/CSharpTemplates.h | 12 ++++----- 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/src/CppParser/Parser.cpp b/src/CppParser/Parser.cpp index 30e12eba..8104f63c 100644 --- a/src/CppParser/Parser.cpp +++ b/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) { - // 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(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) 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, diff --git a/src/Generator.Tests/AST/TestAST.cs b/src/Generator.Tests/AST/TestAST.cs index b8c3c58a..3bed5441 100644 --- a/src/Generator.Tests/AST/TestAST.cs +++ b/src/Generator.Tests/AST/TestAST.cs @@ -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; diff --git a/src/Generator/AST/Utils.cs b/src/Generator/AST/Utils.cs index bce8b389..9d48ff04 100644 --- a/src/Generator/AST/Utils.cs +++ b/src/Generator/AST/Utils.cs @@ -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; } diff --git a/src/Generator/Generators/CSharp/CSharpMarshal.cs b/src/Generator/Generators/CSharp/CSharpMarshal.cs index 6b205f87..4f172309 100644 --- a/src/Generator/Generators/CSharp/CSharpMarshal.cs +++ b/src/Generator/Generators/CSharp/CSharpMarshal.cs @@ -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 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 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); diff --git a/src/Generator/Passes/ResolveIncompleteDeclsPass.cs b/src/Generator/Passes/ResolveIncompleteDeclsPass.cs index 1203672b..1155fec5 100644 --- a/src/Generator/Passes/ResolveIncompleteDeclsPass.cs +++ b/src/Generator/Passes/ResolveIncompleteDeclsPass.cs @@ -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) diff --git a/tests/CSharp/CSharp.Tests.cs b/tests/CSharp/CSharp.Tests.cs index a5a6adce..855966c1 100644 --- a/tests/CSharp/CSharp.Tests.cs +++ b/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")); } - [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)); diff --git a/tests/CSharp/CSharpTemplates.h b/tests/CSharp/CSharpTemplates.h index a2e7abad..636cb99e 100644 --- a/tests/CSharp/CSharpTemplates.h +++ b/tests/CSharp/CSharpTemplates.h @@ -385,6 +385,12 @@ public: { }; IndependentFields getIndependentFields(); + void completeSpecializationInParameter(DependentValueFields p1, + DependentValueFields p2, + DependentValueFields p3); + void completeSpecializationInParameter(TwoTemplateArgs p1, + TwoTemplateArgs p2, + TwoTemplateArgs p3); private: IndependentFields independentFields; DependentValueFields dependentValueFields; @@ -399,12 +405,6 @@ private: DependentValueFields> nestedDependentPointer1; DependentValueFields> nestedDependentPointer2; DependentValueFieldForArray dependentFieldArray; - void completeSpecializationInParameter(DependentValueFields p1, - DependentValueFields p2, - DependentValueFields p3); - void completeSpecializationInParameter(TwoTemplateArgs p1, - TwoTemplateArgs p2, - TwoTemplateArgs p3); }; template