Skip to content

Commit feb2df8

Browse files
committed
Completed just class template specialisations used in functions.
Signed-off-by: Dimitar Dobrev <[email protected]>
1 parent b7faf33 commit feb2df8

File tree

3 files changed

+79
-80
lines changed

3 files changed

+79
-80
lines changed

src/CppParser/Parser.cpp

Lines changed: 77 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,45 @@ WalkTemplateSpecializationKind(clang::TemplateSpecializationKind Kind)
11111111
llvm_unreachable("Unknown template specialization kind");
11121112
}
11131113

1114+
//-----------------------------------//
1115+
1116+
struct Diagnostic
1117+
{
1118+
clang::SourceLocation Location;
1119+
llvm::SmallString<100> Message;
1120+
clang::DiagnosticsEngine::Level Level;
1121+
};
1122+
1123+
struct DiagnosticConsumer : public clang::DiagnosticConsumer
1124+
{
1125+
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level,
1126+
const clang::Diagnostic& Info) override {
1127+
// Update the base type NumWarnings and NumErrors variables.
1128+
if (Level == clang::DiagnosticsEngine::Warning)
1129+
NumWarnings++;
1130+
1131+
if (Level == clang::DiagnosticsEngine::Error ||
1132+
Level == clang::DiagnosticsEngine::Fatal)
1133+
{
1134+
NumErrors++;
1135+
if (Decl)
1136+
{
1137+
Decl->setInvalidDecl();
1138+
Decl = 0;
1139+
}
1140+
}
1141+
1142+
auto Diag = Diagnostic();
1143+
Diag.Location = Info.getLocation();
1144+
Diag.Level = Level;
1145+
Info.FormatDiagnostic(Diag.Message);
1146+
Diagnostics.push_back(Diag);
1147+
}
1148+
1149+
std::vector<Diagnostic> Diagnostics;
1150+
clang::Decl* Decl;
1151+
};
1152+
11141153
ClassTemplateSpecialization*
11151154
Parser::WalkClassTemplateSpecialization(const clang::ClassTemplateSpecializationDecl* CTS)
11161155
{
@@ -2110,39 +2149,6 @@ static const clang::Type* GetFinalType(const clang::Type* Ty)
21102149
}
21112150
}
21122151

2113-
bool Parser::ShouldCompleteType(const clang::QualType& QualType, bool LocValid)
2114-
{
2115-
auto FinalType = GetFinalType(QualType.getTypePtr());
2116-
if (auto Tag = FinalType->getAsTagDecl())
2117-
{
2118-
if (auto CTS = llvm::dyn_cast<clang::ClassTemplateSpecializationDecl>(Tag))
2119-
{
2120-
// we cannot get a location in some cases of template arguments
2121-
if (!LocValid || CTS->isCompleteDefinition())
2122-
return false;
2123-
2124-
auto TAL = &CTS->getTemplateArgs();
2125-
for (size_t i = 0; i < TAL->size(); i++)
2126-
{
2127-
auto TA = TAL->get(i);
2128-
if (TA.getKind() == clang::TemplateArgument::ArgKind::Type)
2129-
{
2130-
auto Type = TA.getAsType();
2131-
if (Type->isVoidType())
2132-
return false;
2133-
}
2134-
}
2135-
auto Unit = GetTranslationUnit(Tag);
2136-
// HACK: completing all system types overflows the managed stack
2137-
// while running the AST converter since the latter is a giant indirect recursion
2138-
// this solution is a hack because we might need to complete system template specialisations
2139-
// such as std:string or std::vector in order to represent them in the target language
2140-
return !Unit->isSystemHeader;
2141-
}
2142-
}
2143-
return false;
2144-
}
2145-
21462152
Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
21472153
bool DesugarType)
21482154
{
@@ -2153,11 +2159,6 @@ Type* Parser::WalkType(clang::QualType QualType, const clang::TypeLoc* TL,
21532159

21542160
auto LocValid = TL && !TL->isNull();
21552161

2156-
auto CompleteType = ShouldCompleteType(QualType, LocValid);
2157-
if (CompleteType)
2158-
c->getSema().RequireCompleteType(
2159-
LocValid ? TL->getLocStart() : clang::SourceLocation(), QualType, 1);
2160-
21612162
const clang::Type* Type = QualType.getTypePtr();
21622163

21632164
if (DesugarType)
@@ -2857,8 +2858,8 @@ bool Parser::CanCheckCodeGenInfo(clang::Sema& S, const clang::Type* Ty)
28572858
{
28582859
auto FinalType = GetFinalType(Ty);
28592860

2860-
if (Ty->isDependentType() || FinalType->isDependentType() ||
2861-
FinalType->isInstantiationDependentType())
2861+
if (FinalType->isDependentType() ||
2862+
FinalType->isInstantiationDependentType() || FinalType->isUndeducedType())
28622863
return false;
28632864

28642865
if (auto RT = FinalType->getAs<clang::RecordType>())
@@ -2899,6 +2900,27 @@ static clang::TypeLoc DesugarTypeLoc(const clang::TypeLoc& Loc)
28992900
return Loc;
29002901
}
29012902

2903+
void Parser::CompleteIfSpecializationType(const clang::QualType& QualType)
2904+
{
2905+
using namespace clang;
2906+
2907+
auto Type = QualType->getUnqualifiedDesugaredType();
2908+
auto RD = Type->getAsCXXRecordDecl();
2909+
if (!RD)
2910+
RD = const_cast<CXXRecordDecl*>(Type->getPointeeCXXRecordDecl());
2911+
ClassTemplateSpecializationDecl* CTS;
2912+
if (!RD ||
2913+
!(CTS = llvm::dyn_cast<ClassTemplateSpecializationDecl>(RD)) ||
2914+
CTS->isCompleteDefinition())
2915+
return;
2916+
2917+
auto Diagnostics = c->getSema().getDiagnostics().getClient();
2918+
auto SemaDiagnostics = static_cast<::DiagnosticConsumer*>(Diagnostics);
2919+
SemaDiagnostics->Decl = CTS;
2920+
c->getSema().InstantiateClassTemplateSpecialization(CTS->getLocStart(),
2921+
CTS, TSK_ImplicitInstantiation, false);
2922+
}
2923+
29022924
Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
29032925
const clang::SourceLocation& ParamStartLoc)
29042926
{
@@ -2913,14 +2935,18 @@ Parameter* Parser::WalkParameter(const clang::ParmVarDecl* PVD,
29132935

29142936
TypeLoc PTL;
29152937
if (auto TSI = PVD->getTypeSourceInfo())
2916-
PTL = PVD->getTypeSourceInfo()->getTypeLoc();
2938+
PTL = TSI->getTypeLoc();
29172939

29182940
auto paramRange = PVD->getSourceRange();
29192941
paramRange.setBegin(ParamStartLoc);
29202942

29212943
HandlePreprocessedEntities(P, paramRange, MacroLocation::FunctionParameters);
29222944

2923-
P->qualifiedType = GetQualifiedType(PVD->getOriginalType(), &PTL);
2945+
const auto& Type = PVD->getOriginalType();
2946+
auto Function = PVD->getParentFunctionOrMethod();
2947+
if (Function && cast<NamedDecl>(Function)->isExternallyVisible())
2948+
CompleteIfSpecializationType(Type);
2949+
P->qualifiedType = GetQualifiedType(Type, &PTL);
29242950
P->hasDefaultValue = PVD->hasDefaultArg();
29252951
P->index = PVD->getFunctionScopeIndex();
29262952
if (PVD->hasDefaultArg() && !PVD->hasUnparsedDefaultArg())
@@ -3008,8 +3034,11 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
30083034
}
30093035
else
30103036
F->qualifiedType = GetQualifiedType(FD->getType());
3011-
3012-
F->returnType = GetQualifiedType(FD->getReturnType(), &RTL);
3037+
3038+
auto ReturnType = FD->getReturnType();
3039+
if (FD->isExternallyVisible())
3040+
CompleteIfSpecializationType(ReturnType);
3041+
F->returnType = GetQualifiedType(ReturnType, &RTL);
30133042

30143043
const auto& Mangled = GetDeclMangledName(FD);
30153044
F->mangled = Mangled;
@@ -3047,7 +3076,7 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
30473076
if (GetDeclText(Range, Sig))
30483077
F->signature = Sig;
30493078

3050-
for (const auto& VD : FD->parameters())
3079+
for (auto VD : FD->parameters())
30513080
{
30523081
auto P = WalkParameter(VD, ParamStartLoc);
30533082
F->Parameters.push_back(P);
@@ -3069,6 +3098,9 @@ void Parser::WalkFunction(const clang::FunctionDecl* FD, Function* F,
30693098
if (auto FTSI = FD->getTemplateSpecializationInfo())
30703099
F->specializationInfo = WalkFunctionTemplateSpec(FTSI, F);
30713100

3101+
if (F->isDependent)
3102+
return;
3103+
30723104
const CXXMethodDecl* MD;
30733105
if ((MD = dyn_cast<CXXMethodDecl>(FD)) && !MD->isStatic() &&
30743106
!HasLayout(cast<CXXRecordDecl>(MD->getDeclContext())))
@@ -3874,39 +3906,6 @@ Declaration* Parser::WalkDeclaration(const clang::Decl* D)
38743906
return Decl;
38753907
}
38763908

3877-
//-----------------------------------//
3878-
3879-
struct Diagnostic
3880-
{
3881-
clang::SourceLocation Location;
3882-
llvm::SmallString<100> Message;
3883-
clang::DiagnosticsEngine::Level Level;
3884-
};
3885-
3886-
struct DiagnosticConsumer : public clang::DiagnosticConsumer
3887-
{
3888-
virtual ~DiagnosticConsumer() { }
3889-
3890-
virtual void HandleDiagnostic(clang::DiagnosticsEngine::Level Level,
3891-
const clang::Diagnostic& Info) override {
3892-
// Update the base type NumWarnings and NumErrors variables.
3893-
if (Level == clang::DiagnosticsEngine::Warning)
3894-
NumWarnings++;
3895-
3896-
if (Level == clang::DiagnosticsEngine::Error ||
3897-
Level == clang::DiagnosticsEngine::Fatal)
3898-
NumErrors++;
3899-
3900-
auto Diag = Diagnostic();
3901-
Diag.Location = Info.getLocation();
3902-
Diag.Level = Level;
3903-
Info.FormatDiagnostic(Diag.Message);
3904-
Diagnostics.push_back(Diag);
3905-
}
3906-
3907-
std::vector<Diagnostic> Diagnostics;
3908-
};
3909-
39103909
void Parser::HandleDiagnostics(ParserResult* res)
39113910
{
39123911
auto DiagClient = (DiagnosticConsumer&) c->getDiagnosticClient();

src/CppParser/Parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ class Parser
8787
void WalkVariable(const clang::VarDecl* VD, Variable* Var);
8888
Friend* WalkFriend(const clang::FriendDecl* FD);
8989
RawComment* WalkRawComment(const clang::RawComment* RC);
90-
bool ShouldCompleteType(const clang::QualType& QualType, bool LocValid);
9190
Type* WalkType(clang::QualType QualType, const clang::TypeLoc* TL = 0,
9291
bool DesugarType = false);
9392
TemplateArgument WalkTemplateArgument(const clang::TemplateArgument& TA, clang::TemplateArgumentLoc* ArgLoc);
@@ -124,6 +123,7 @@ class Parser
124123
std::string GetDeclMangledName(const clang::Decl* D);
125124
std::string GetTypeName(const clang::Type* Type);
126125
bool CanCheckCodeGenInfo(clang::Sema & S, const clang::Type * Ty);
126+
void CompleteIfSpecializationType(const clang::QualType& QualType);
127127
Parameter* WalkParameter(const clang::ParmVarDecl* PVD,
128128
const clang::SourceLocation& ParamStartLoc);
129129
void SetBody(const clang::FunctionDecl* FD, Function* F);

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.ImplicitInstantiation, template.Specializations[4].SpecializationKind);
285+
Assert.AreEqual(TemplateSpecializationKind.Undeclared, 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;

0 commit comments

Comments
 (0)