Browse Source

Instantiate specialized classes nested in templates

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/1636/head
Dimitar Dobrev 4 years ago
parent
commit
2da9e49fe8
  1. 14
      src/AST/ClassExtensions.cs
  2. 33
      src/CppParser/Parser.cpp
  3. 1
      src/CppParser/Parser.h
  4. 8
      src/Generator/Generators/CSharp/CSharpSources.cs
  5. 16
      src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs
  6. 8
      tests/CSharp/CSharpTemplates.cpp

14
src/AST/ClassExtensions.cs

@ -233,6 +233,20 @@ namespace CppSharp.AST
return @interface; return @interface;
} }
public static ClassTemplateSpecialization GetParentSpecialization(this Class @class)
{
Class currentClass = @class;
do
{
if (currentClass is ClassTemplateSpecialization specialization)
{
return specialization;
}
currentClass = currentClass.Namespace as Class;
} while (currentClass != null);
return null;
}
public static bool HasDependentValueFieldInLayout(this Class @class) public static bool HasDependentValueFieldInLayout(this Class @class)
{ {
if (@class.Fields.Any(f => IsValueDependent(f.Type))) if (@class.Fields.Any(f => IsValueDependent(f.Type)))

33
src/CppParser/Parser.cpp

@ -42,6 +42,7 @@
#include <clang/Parse/ParseAST.h> #include <clang/Parse/ParseAST.h>
#include <clang/Sema/Sema.h> #include <clang/Sema/Sema.h>
#include <clang/Sema/SemaConsumer.h> #include <clang/Sema/SemaConsumer.h>
#include <clang/Sema/Template.h>
#include <clang/Frontend/Utils.h> #include <clang/Frontend/Utils.h>
#include <clang/Driver/Driver.h> #include <clang/Driver/Driver.h>
#include <clang/Driver/ToolChain.h> #include <clang/Driver/ToolChain.h>
@ -3053,8 +3054,7 @@ void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
RD = const_cast<CXXRecordDecl*>(Type->getPointeeCXXRecordDecl()); RD = const_cast<CXXRecordDecl*>(Type->getPointeeCXXRecordDecl());
ClassTemplateSpecializationDecl* CTS; ClassTemplateSpecializationDecl* CTS;
if (!RD || if (!RD ||
!(CTS = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) || !(CTS = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)))
CTS->isCompleteDefinition())
return; return;
auto existingClient = c->getSema().getDiagnostics().getClient(); auto existingClient = c->getSema().getDiagnostics().getClient();
@ -3065,8 +3065,7 @@ void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
Scope Scope(nullptr, Scope::ScopeFlags::ClassScope, c->getSema().getDiagnostics()); Scope Scope(nullptr, Scope::ScopeFlags::ClassScope, c->getSema().getDiagnostics());
c->getSema().TUScope = &Scope; c->getSema().TUScope = &Scope;
c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(), InstantiateSpecialization(CTS);
CTS, TSK_ImplicitInstantiation, false);
c->getSema().getDiagnostics().setClient(existingClient, false); c->getSema().getDiagnostics().setClient(existingClient, false);
c->getSema().TUScope = nullptr; c->getSema().TUScope = nullptr;
@ -3082,6 +3081,32 @@ void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
} }
} }
void Parser::InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* CTS)
{
using namespace clang;
if (!CTS->isCompleteDefinition())
{
c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(),
CTS, TSK_ImplicitInstantiation, false);
}
for (auto Decl : CTS->decls())
{
if (Decl->getKind() == Decl::Kind::CXXRecord)
{
CXXRecordDecl* Nested = cast<CXXRecordDecl>(Decl);
CXXRecordDecl* Template = Nested->getInstantiatedFromMemberClass();
if (Template && !Nested->isCompleteDefinition() && !Nested->hasDefinition())
{
c->getSema().InstantiateClass(Nested->getBeginLoc(), Nested, Template,
MultiLevelTemplateArgumentList(CTS->getTemplateArgs()),
TSK_ImplicitInstantiation, false);
}
}
}
}
Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD, Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc) const clang::SourceLocation& ParamStartLoc)
{ {

1
src/CppParser/Parser.h

@ -137,6 +137,7 @@ private:
std::string GetTypeName(const clang::Type* Type); std::string GetTypeName(const clang::Type* Type);
bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty); bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty);
void CompleteIfSpecializationType(const clang::QualType& QualType); void CompleteIfSpecializationType(const clang::QualType& QualType);
void InstantiateSpecialization(clang::ClassTemplateSpecializationDecl* CTS);
Parameter* WalkParameter(const clang::ParmVarDecl* PVD, Parameter* WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc); const clang::SourceLocation& ParamStartLoc);
void SetBody(const clang::FunctionDecl* FD, Function* F); void SetBody(const clang::FunctionDecl* FD, Function* F);

8
src/Generator/Generators/CSharp/CSharpSources.cs

@ -361,13 +361,11 @@ namespace CppSharp.Generators.CSharp
private IEnumerable<Class> GetGeneratedClasses( private IEnumerable<Class> GetGeneratedClasses(
Class dependentClass, IEnumerable<Class> specializedClasses) Class dependentClass, IEnumerable<Class> specializedClasses)
{ {
var specialization = specializedClasses.FirstOrDefault(s => s.IsGenerated) ??
specializedClasses.First();
if (dependentClass.HasDependentValueFieldInLayout()) if (dependentClass.HasDependentValueFieldInLayout())
return specializedClasses; return specializedClasses.KeepSingleAllPointersSpecialization();
return new[] { specialization }; return new[] { specializedClasses.FirstOrDefault(s => s.IsGenerated) ??
specializedClasses.First()};
} }
public override void GenerateDeclarationCommon(Declaration decl) public override void GenerateDeclarationCommon(Declaration decl)

16
src/Generator/Generators/CSharp/CSharpSourcesExtensions.cs

@ -24,11 +24,9 @@ namespace CppSharp.Generators.CSharp
var printedClass = @class.Visit(gen.TypePrinter); var printedClass = @class.Visit(gen.TypePrinter);
if (@class.IsDependent) if (@class.IsDependent)
{ {
IEnumerable<Class> specializations = foreach (var specialization in (from s in @class.GetSpecializedClassesToGenerate()
@class.GetSpecializedClassesToGenerate().Where(s => s.IsGenerated); where s.IsGenerated
if (@class.IsTemplate) select s).KeepSingleAllPointersSpecialization())
specializations = specializations.KeepSingleAllPointersSpecialization();
foreach (var specialization in specializations)
gen.GenerateNativeConstructorByValue(specialization, printedClass); gen.GenerateNativeConstructorByValue(specialization, printedClass);
} }
else else
@ -40,10 +38,10 @@ namespace CppSharp.Generators.CSharp
public static IEnumerable<Class> KeepSingleAllPointersSpecialization( public static IEnumerable<Class> KeepSingleAllPointersSpecialization(
this IEnumerable<Class> specializations) this IEnumerable<Class> specializations)
{ {
Func<TemplateArgument, bool> allPointers = (TemplateArgument a) => static bool allPointers(TemplateArgument a) => a.Type.Type?.Desugar().IsAddress() == true;
a.Type.Type?.Desugar().IsAddress() == true; var groups = (from @class in specializations
var groups = (from ClassTemplateSpecialization spec in specializations let spec = @class.GetParentSpecialization()
group spec by spec.Arguments.All(allPointers) group @class by spec.Arguments.All(allPointers)
into @group into @group
select @group).ToList(); select @group).ToList();
foreach (var group in groups) foreach (var group in groups)

8
tests/CSharp/CSharpTemplates.cpp

@ -109,8 +109,12 @@ void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool>
VirtualTemplate<int> _6, VirtualTemplate<bool> _7, VirtualTemplate<int> _6, VirtualTemplate<bool> _7,
HasDefaultTemplateArgument<int, int> _8, DerivedChangesTypeName<T1> _9, HasDefaultTemplateArgument<int, int> _8, DerivedChangesTypeName<T1> _9,
TemplateWithIndexer<int> _10, TemplateWithIndexer<T1> _11, TemplateWithIndexer<int> _10, TemplateWithIndexer<T1> _11,
TemplateWithIndexer<T2*> _12, TemplateDerivedFromRegularDynamic<RegularDynamic> _13, TemplateWithIndexer<void*> _12, TemplateWithIndexer<UsedInTemplatedIndexer> _13,
IndependentFields<OnlySpecialisedInTypeArg<double> > _14, std::string s) TemplateDerivedFromRegularDynamic<RegularDynamic> _14,
IndependentFields<OnlySpecialisedInTypeArg<double>> _15,
DependentPointerFields<float> _16, IndependentFields<const T1&> _17,
TemplateWithIndexer<T2*> _18, IndependentFields<int(*)(int)> _19,
TemplateWithIndexer<const char*> _20, std::string s)
{ {
} }

Loading…
Cancel
Save