Generate valid C# for templates with external specializations only

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
This commit is contained in:
Dimitar Dobrev 2021-12-28 22:11:55 +02:00
Родитель 27c52ecf54
Коммит f1915b3066
5 изменённых файлов: 16 добавлений и 47 удалений

Просмотреть файл

@ -247,25 +247,17 @@ namespace CppSharp.AST
return null;
}
public static bool HasDependentValueFieldInLayout(this Class @class)
{
if (@class.Fields.Any(f => IsValueDependent(f.Type)))
return true;
if (@class.Bases.Where(b => b.IsClass).Select(
b => b.Class).Any(HasDependentValueFieldInLayout))
return true;
public static bool HasDependentValueFieldInLayout(this Class @class,
IEnumerable<ClassTemplateSpecialization> specializations = null) =>
@class.Fields.Any(f => IsValueDependent(f.Type)) ||
@class.Bases.Where(b => b.IsClass).Select(
b => b.Class).Any(c => c.HasDependentValueFieldInLayout()) ||
// HACK: Clang can't always resolve complex templates such as the base of std::atomic in msvc
if (@class.IsTemplate && @class.Specializations.Any(
s => s.Layout.Fields.Any(
f => f.QualifiedType.Type.TryGetDeclaration(
out ClassTemplateSpecialization specialization) &&
specialization.TemplatedDecl.TemplatedClass.HasDependentValueFieldInLayout())))
return true;
return false;
}
(@class.IsTemplate && (specializations ?? @class.Specializations).Any(
s => s.Layout.Fields.Any(
f => f.QualifiedType.Type.TryGetDeclaration(
out ClassTemplateSpecialization specialization) &&
specialization.TemplatedDecl.TemplatedClass.HasDependentValueFieldInLayout())));
public static IEnumerable<Property> GetConstCharFieldProperties(this Class @class) =>
@class.Properties.Where(p => p.HasGetter && p.HasSetter &&

Просмотреть файл

@ -3067,7 +3067,9 @@ void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
Scope Scope(nullptr, Scope::ScopeFlags::ClassScope, c->getSema().getDiagnostics());
c->getSema().TUScope = &Scope;
InstantiateSpecialization(CTS);
if (!CTS->isCompleteDefinition())
c->getSema().InstantiateClassTemplateSpecialization(CTS->getBeginLoc(),
CTS, clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
c->getSema().getDiagnostics().setClient(existingClient, false);
c->getSema().TUScope = nullptr;
@ -3083,32 +3085,6 @@ 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, clang::TemplateSpecializationKind::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()),
clang::TemplateSpecializationKind::TSK_ImplicitInstantiation, false);
}
}
}
}
Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
const clang::SourceLocation& ParamStartLoc)
{

Просмотреть файл

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

Просмотреть файл

@ -330,7 +330,7 @@ namespace CppSharp.Generators.CSharp
GenerateClassTemplateSpecializationsInternals(
nestedTemplate, nestedTemplate.Specializations);
if (template.HasDependentValueFieldInLayout() ||
if (template.HasDependentValueFieldInLayout(specializations) ||
template.Specializations.Intersect(specializations).Count() == specializations.Count)
foreach (var specialization in generated)
GenerateClassInternals(specialization);

Просмотреть файл

@ -2,6 +2,7 @@
#include "../NamespacesBase/NamespacesBase.h"
#include "Independent.h"
#include <string>
#include <unordered_map>
#include <vector>
// Namespace clashes with NamespacesBase.OverlappingNamespace
@ -71,6 +72,7 @@ private:
IndependentFields<int> independentSpecialization;
IndependentFields<Derived> independentExternalSpecialization;
IndependentFields<Derived>::Nested nestedInExternalSpecialization;
std::unordered_map<int, Derived> externalSpecializationOnly;
};
class DLL_API HasVirtualInDependency : public HasVirtualInCore