From c7203ad8e7f096a6b50fdf23209cffcd19276e32 Mon Sep 17 00:00:00 2001 From: Dimitar Dobrev Date: Tue, 14 Feb 2017 22:47:37 +0200 Subject: [PATCH] Collected template parameters of class templates. Signed-off-by: Dimitar Dobrev --- src/AST/Class.cs | 20 +++++++++++++ src/AST/ITypePrinter.cs | 9 +++++- .../Generators/CSharp/CSharpTypePrinter.cs | 3 +- src/Generator/Passes/RenamePass.cs | 6 +++- .../Passes/ResolveIncompleteDeclsPass.cs | 3 ++ src/Generator/Types/Std/Stdlib.cs | 30 +++++++++---------- 6 files changed, 53 insertions(+), 18 deletions(-) diff --git a/src/AST/Class.cs b/src/AST/Class.cs index 9493fd3f..18c025ef 100644 --- a/src/AST/Class.cs +++ b/src/AST/Class.cs @@ -127,6 +127,7 @@ namespace CppSharp.AST IsPOD = false; Type = ClassType.RefType; Layout = new ClassLayout(); + templateParameters = new List(); specializations = new List(); } @@ -218,6 +219,24 @@ namespace CppSharp.AST } } + /// + /// If this class is a template, this list contains all of its template parameters. + /// + /// cannot be relied upon to contain all of them because + /// ClassTemplateDecl in Clang is not a complete declaration, it only serves to forward template classes. + /// + /// + public List TemplateParameters + { + get + { + if (!IsDependent) + throw new InvalidOperationException( + "Only dependent classes have template parameters."); + return templateParameters; + } + } + /// /// If this class is a template, this list contains all of its specializations. /// cannot be relied upon to contain all of them because @@ -274,6 +293,7 @@ namespace CppSharp.AST return visitor.VisitClassDecl(this); } + private List templateParameters; private List specializations; } } diff --git a/src/AST/ITypePrinter.cs b/src/AST/ITypePrinter.cs index e4f3223e..b2f97349 100644 --- a/src/AST/ITypePrinter.cs +++ b/src/AST/ITypePrinter.cs @@ -38,7 +38,14 @@ namespace CppSharp.AST if (templateSpecializationType != null) templateArgs = templateSpecializationType.Arguments; else - templateArgs = ((ClassTemplateSpecialization) ((TagType) type).Declaration).Arguments; + { + var declaration = ((TagType) type).Declaration; + var specialization = declaration as ClassTemplateSpecialization; + if (specialization == null) + return string.Join(", ", + ((Class) declaration).TemplateParameters.Select(t => t.Name)); + templateArgs = ((ClassTemplateSpecialization) declaration).Arguments; + } var paramsList = new List(); foreach (var arg in templateArgs.Where(a => a.Kind == TemplateArgument.ArgumentKind.Type)) diff --git a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs index 03b1b306..8a9f1ede 100644 --- a/src/Generator/Generators/CSharp/CSharpTypePrinter.cs +++ b/src/Generator/Generators/CSharp/CSharpTypePrinter.cs @@ -579,7 +579,8 @@ namespace CppSharp.Generators.CSharp if (ContextKind == TypePrinterContextKind.Native) return $"{GetName(@class.OriginalClass ?? @class)}.{Helpers.InternalStruct}"; - return GetName(@class); + return $@"{GetName(@class)}{(@class.IsDependent ? $@"<{ + string.Join(", ", @class.TemplateParameters.Select(p => p.Name))}>" : string.Empty)}"; } public override TypePrinterResult VisitClassTemplateSpecializationDecl( diff --git a/src/Generator/Passes/RenamePass.cs b/src/Generator/Passes/RenamePass.cs index 7f88f237..94c8d554 100644 --- a/src/Generator/Passes/RenamePass.cs +++ b/src/Generator/Passes/RenamePass.cs @@ -146,12 +146,16 @@ namespace CppSharp.Passes if (specialization != null) declarations.RemoveAll(d => specialization.TemplatedDecl.TemplatedDecl == d); + var @class = decl.Namespace as Class; + if (@class != null && @class.IsDependent) + declarations.AddRange(@class.TemplateParameters); + var result = declarations.Any(d => d != decl && d.Name == newName); if (result) return true; if (decl is Method && decl.IsGenerated) - return ((Class) decl.Namespace).GetPropertyByName(newName) != null; + return @class.GetPropertyByName(newName) != null; var property = decl as Property; if (property != null && property.Field != null) diff --git a/src/Generator/Passes/ResolveIncompleteDeclsPass.cs b/src/Generator/Passes/ResolveIncompleteDeclsPass.cs index 6235aef6..61b50c3f 100644 --- a/src/Generator/Passes/ResolveIncompleteDeclsPass.cs +++ b/src/Generator/Passes/ResolveIncompleteDeclsPass.cs @@ -28,6 +28,9 @@ namespace CppSharp.Passes s => !s.IsIncomplete && !template.TemplatedClass.Specializations.Contains(s))) template.TemplatedClass.Specializations.Add(specialization); + if (template.TemplatedClass.TemplateParameters.Count == 0) + template.TemplatedClass.TemplateParameters.AddRange(template.Parameters); + return true; } diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index 9e5981fc..d968f6cc 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -64,29 +64,29 @@ namespace CppSharp.Types.Std var typePrinter = new CSharpTypePrinter(ctx.Context); typePrinter.PushContext(TypePrinterContextKind.Native); if (!ctx.Parameter.Type.Desugar().IsAddress()) - ctx.Return.Write("*({0}*) ", basicString.Visit(typePrinter)); + ctx.Return.Write($"*({basicString.Visit(typePrinter)}*) "); typePrinter.PopContext(); var allocator = ctx.Context.ASTContext.FindClass("allocator", false, true).First( a => a.IsDependent && a.TranslationUnit.IsSystemHeader); + var allocatorChar = allocator.Specializations.First(s => !s.Ignore); if (type.IsPointer() || (type.IsReference() && ctx.Declaration is Field)) { - ctx.Return.Write("new {0}({1}, new {2}()).{3}", - basicString.Visit(typePrinter), ctx.Parameter.Name, - allocator.Visit(typePrinter), Helpers.InstanceIdentifier); + ctx.Return.Write($@"new {basicString.Visit(typePrinter)}({ + ctx.Parameter.Name}, new {allocatorChar.Visit(typePrinter)}()).{ + Helpers.InstanceIdentifier}"); } else { - string varAllocator = "__allocator" + ctx.ParameterIndex; - string varBasicString = "__basicString" + ctx.ParameterIndex; - ctx.SupportBefore.WriteLine("var {0} = new {1}();", - varAllocator, allocator.Visit(typePrinter)); - ctx.SupportBefore.WriteLine("var {0} = new {1}({2}, {3});", - varBasicString, basicString.Visit(typePrinter), - ctx.Parameter.Name, varAllocator); - ctx.Return.Write("{0}.{1}", varBasicString, Helpers.InstanceIdentifier); - ctx.Cleanup.WriteLine("{0}.Dispose({1});", varBasicString, - type.IsPointer() ? "true" : "false"); - ctx.Cleanup.WriteLine("{0}.Dispose();", varAllocator); + var varAllocator = $"__allocator{ctx.ParameterIndex}"; + var varBasicString = $"__basicString{ctx.ParameterIndex}"; + ctx.SupportBefore.WriteLine($@"var {varAllocator} = new { + allocatorChar.Visit(typePrinter)}();"); + ctx.SupportBefore.WriteLine($@"var {varBasicString} = new { + basicString.Visit(typePrinter)}({ctx.Parameter.Name}, {varAllocator});"); + ctx.Return.Write($"{varBasicString}.{Helpers.InstanceIdentifier}"); + ctx.Cleanup.WriteLine($@"{varBasicString}.Dispose({ + (type.IsPointer() ? "true" : "false")});"); + ctx.Cleanup.WriteLine($"{varAllocator}.Dispose();"); } }