Skip to content

Commit 7115ed0

Browse files
authored
[Clang] Unify interface for accessing template arguments as written for class/variable template specializations (llvm#81642)
Our current method of storing the template arguments as written for `(Class/Var)Template(Partial)SpecializationDecl` suffers from a number of flaws: - We use `TypeSourceInfo` to store `TemplateArgumentLocs` for class template/variable template partial/explicit specializations. For variable template specializations, this is a rather unintuitive hack (as we store a non-type specialization as a type). Moreover, we don't ever *need* the type as written -- in almost all cases, we only want the template arguments (e.g. in tooling use-cases). - The template arguments as written are stored in a number of redundant data members. For example, `(Class/Var)TemplatePartialSpecialization` have their own `ArgsAsWritten` member that stores an `ASTTemplateArgumentListInfo` (the template arguments). `VarTemplateSpecializationDecl` has yet _another_ redundant member "`TemplateArgsInfo`" that also stores an `ASTTemplateArgumentListInfo`. This patch eliminates all `(Class/Var)Template(Partial)SpecializationDecl` members which store the template arguments as written, and turns the `ExplicitInfo` member into a `llvm::PointerUnion<const ASTTemplateArgumentListInfo*, ExplicitInstantiationInfo*>` (to avoid unnecessary allocations when the declaration isn't an explicit instantiation). The template arguments as written are now accessed via `getTemplateArgsWritten` in all cases. The "most breaking" change is to AST Matchers, insofar that `hasTypeLoc` will no longer match class template specializations (since they no longer store the type as written).
1 parent 1a2a1fb commit 7115ed0

26 files changed

+846
-729
lines changed

clang-tools-extra/clangd/AST.cpp

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,11 @@ getTemplateSpecializationArgLocs(const NamedDecl &ND) {
5050
if (const ASTTemplateArgumentListInfo *Args =
5151
Func->getTemplateSpecializationArgsAsWritten())
5252
return Args->arguments();
53-
} else if (auto *Cls =
54-
llvm::dyn_cast<ClassTemplatePartialSpecializationDecl>(&ND)) {
53+
} else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
5554
if (auto *Args = Cls->getTemplateArgsAsWritten())
5655
return Args->arguments();
57-
} else if (auto *Var =
58-
llvm::dyn_cast<VarTemplatePartialSpecializationDecl>(&ND)) {
59-
if (auto *Args = Var->getTemplateArgsAsWritten())
60-
return Args->arguments();
6156
} else if (auto *Var = llvm::dyn_cast<VarTemplateSpecializationDecl>(&ND)) {
62-
if (auto *Args = Var->getTemplateArgsInfo())
57+
if (auto *Args = Var->getTemplateArgsAsWritten())
6358
return Args->arguments();
6459
}
6560
// We return std::nullopt for ClassTemplateSpecializationDecls because it does
@@ -270,22 +265,10 @@ std::string printTemplateSpecializationArgs(const NamedDecl &ND) {
270265
getTemplateSpecializationArgLocs(ND)) {
271266
printTemplateArgumentList(OS, *Args, Policy);
272267
} else if (auto *Cls = llvm::dyn_cast<ClassTemplateSpecializationDecl>(&ND)) {
273-
if (const TypeSourceInfo *TSI = Cls->getTypeAsWritten()) {
274-
// ClassTemplateSpecializationDecls do not contain
275-
// TemplateArgumentTypeLocs, they only have TemplateArgumentTypes. So we
276-
// create a new argument location list from TypeSourceInfo.
277-
auto STL = TSI->getTypeLoc().getAs<TemplateSpecializationTypeLoc>();
278-
llvm::SmallVector<TemplateArgumentLoc> ArgLocs;
279-
ArgLocs.reserve(STL.getNumArgs());
280-
for (unsigned I = 0; I < STL.getNumArgs(); ++I)
281-
ArgLocs.push_back(STL.getArgLoc(I));
282-
printTemplateArgumentList(OS, ArgLocs, Policy);
283-
} else {
284-
// FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
285-
// e.g. friend decls. Currently we fallback to Template Arguments without
286-
// location information.
287-
printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
288-
}
268+
// FIXME: Fix cases when getTypeAsWritten returns null inside clang AST,
269+
// e.g. friend decls. Currently we fallback to Template Arguments without
270+
// location information.
271+
printTemplateArgumentList(OS, Cls->getTemplateArgs().asArray(), Policy);
289272
}
290273
OS.flush();
291274
return TemplateArgs;
@@ -453,10 +436,12 @@ bool hasReservedScope(const DeclContext &DC) {
453436
}
454437

455438
QualType declaredType(const TypeDecl *D) {
439+
ASTContext &Context = D->getASTContext();
456440
if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(D))
457-
if (const auto *TSI = CTSD->getTypeAsWritten())
458-
return TSI->getType();
459-
return D->getASTContext().getTypeDeclType(D);
441+
if (const auto *Args = CTSD->getTemplateArgsAsWritten())
442+
return Context.getTemplateSpecializationType(
443+
TemplateName(CTSD->getSpecializedTemplate()), Args->arguments());
444+
return Context.getTypeDeclType(D);
460445
}
461446

462447
namespace {

clang-tools-extra/clangd/SemanticHighlighting.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -693,17 +693,22 @@ class CollectExtraHighlightings
693693
return true;
694694
}
695695

696+
bool
697+
VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *D) {
698+
if (auto *Args = D->getTemplateArgsAsWritten())
699+
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
700+
return true;
701+
}
702+
696703
bool VisitClassTemplatePartialSpecializationDecl(
697704
ClassTemplatePartialSpecializationDecl *D) {
698705
if (auto *TPL = D->getTemplateParameters())
699706
H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
700-
if (auto *Args = D->getTemplateArgsAsWritten())
701-
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
702707
return true;
703708
}
704709

705710
bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D) {
706-
if (auto *Args = D->getTemplateArgsInfo())
711+
if (auto *Args = D->getTemplateArgsAsWritten())
707712
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
708713
return true;
709714
}
@@ -712,8 +717,6 @@ class CollectExtraHighlightings
712717
VarTemplatePartialSpecializationDecl *D) {
713718
if (auto *TPL = D->getTemplateParameters())
714719
H.addAngleBracketTokens(TPL->getLAngleLoc(), TPL->getRAngleLoc());
715-
if (auto *Args = D->getTemplateArgsAsWritten())
716-
H.addAngleBracketTokens(Args->getLAngleLoc(), Args->getRAngleLoc());
717720
return true;
718721
}
719722

clang-tools-extra/include-cleaner/lib/WalkAST.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -267,18 +267,21 @@ class ASTWalker : public RecursiveASTVisitor<ASTWalker> {
267267
return true;
268268
}
269269

270-
// Report a reference from explicit specializations to the specialized
271-
// template. Implicit ones are filtered out by RAV and explicit instantiations
272-
// are already traversed through typelocs.
270+
// Report a reference from explicit specializations/instantiations to the
271+
// specialized template. Implicit ones are filtered out by RAV.
273272
bool
274273
VisitClassTemplateSpecializationDecl(ClassTemplateSpecializationDecl *CTSD) {
275-
if (CTSD->isExplicitSpecialization())
274+
// if (CTSD->isExplicitSpecialization())
275+
if (clang::isTemplateExplicitInstantiationOrSpecialization(
276+
CTSD->getTemplateSpecializationKind()))
276277
report(CTSD->getLocation(),
277278
CTSD->getSpecializedTemplate()->getTemplatedDecl());
278279
return true;
279280
}
280281
bool VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *VTSD) {
281-
if (VTSD->isExplicitSpecialization())
282+
// if (VTSD->isExplicitSpecialization())
283+
if (clang::isTemplateExplicitInstantiationOrSpecialization(
284+
VTSD->getTemplateSpecializationKind()))
282285
report(VTSD->getLocation(),
283286
VTSD->getSpecializedTemplate()->getTemplatedDecl());
284287
return true;

0 commit comments

Comments
 (0)