Skip to content

Commit 89ce871

Browse files
authored
[clang] fix TemplateName Subst* nodes transform (llvm#155342)
This makes sure NestedNameSpecifierLocs don't apply to the replacement TemplateName of SubstTemplate* nodes. Also removes improper name qualification over these Subst Nodes, causing some canonical TemplateNames to not be fully qualified when printed. Since this is a regression introduced in llvm#147835, which was never released, there are no release notes. Fixes llvm#155281
1 parent 86bca29 commit 89ce871

File tree

12 files changed

+152
-141
lines changed

12 files changed

+152
-141
lines changed

clang/include/clang/AST/TemplateName.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -335,17 +335,17 @@ class TemplateName {
335335
/// structure, if any.
336336
QualifiedTemplateName *getAsQualifiedTemplateName() const;
337337

338-
/// Retrieve the underlying qualified template name,
339-
/// looking through underlying nodes.
340-
QualifiedTemplateName *getAsAdjustedQualifiedTemplateName() const;
341-
342338
/// Retrieve the underlying dependent template name
343339
/// structure, if any.
344340
DependentTemplateName *getAsDependentTemplateName() const;
345341

346-
// Retrieve the qualifier stored in either a underlying DependentTemplateName
347-
// or QualifiedTemplateName.
348-
NestedNameSpecifier getQualifier() const;
342+
// Retrieve the qualifier and template keyword stored in either a underlying
343+
// DependentTemplateName or QualifiedTemplateName.
344+
std::tuple<NestedNameSpecifier, bool> getQualifierAndTemplateKeyword() const;
345+
346+
NestedNameSpecifier getQualifier() const {
347+
return std::get<0>(getQualifierAndTemplateKeyword());
348+
}
349349

350350
/// Retrieve the using shadow declaration through which the underlying
351351
/// template declaration is introduced, if any.

clang/include/clang/AST/TypeLoc.h

Lines changed: 8 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,11 +1872,10 @@ class TemplateSpecializationTypeLoc :
18721872
if (!getLocalData()->QualifierData)
18731873
return NestedNameSpecifierLoc();
18741874

1875-
auto *QTN =
1876-
getTypePtr()->getTemplateName().getAsAdjustedQualifiedTemplateName();
1877-
assert(QTN && "missing qualification");
1878-
return NestedNameSpecifierLoc(QTN->getQualifier(),
1879-
getLocalData()->QualifierData);
1875+
NestedNameSpecifier Qualifier =
1876+
getTypePtr()->getTemplateName().getQualifier();
1877+
assert(Qualifier && "missing qualification");
1878+
return NestedNameSpecifierLoc(Qualifier, getLocalData()->QualifierData);
18801879
}
18811880

18821881
SourceLocation getTemplateKeywordLoc() const {
@@ -2503,10 +2502,9 @@ class DeducedTemplateSpecializationTypeLoc
25032502
void *Data = getLocalData()->QualifierData;
25042503
if (!Data)
25052504
return NestedNameSpecifierLoc();
2506-
NestedNameSpecifier Qualifier = getTypePtr()
2507-
->getTemplateName()
2508-
.getAsAdjustedQualifiedTemplateName()
2509-
->getQualifier();
2505+
NestedNameSpecifier Qualifier =
2506+
getTypePtr()->getTemplateName().getQualifier();
2507+
assert(Qualifier && "missing qualification");
25102508
return NestedNameSpecifierLoc(Qualifier, Data);
25112509
}
25122510

@@ -2521,10 +2519,7 @@ class DeducedTemplateSpecializationTypeLoc
25212519
}
25222520

25232521
assert(QualifierLoc.getNestedNameSpecifier() ==
2524-
getTypePtr()
2525-
->getTemplateName()
2526-
.getAsAdjustedQualifiedTemplateName()
2527-
->getQualifier() &&
2522+
getTypePtr()->getTemplateName().getQualifier() &&
25282523
"Inconsistent nested-name-specifier pointer");
25292524
getLocalData()->QualifierData = QualifierLoc.getOpaqueData();
25302525
}

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10447,6 +10447,12 @@ TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier Qualifier,
1044710447
assert(Template.getKind() == TemplateName::Template ||
1044810448
Template.getKind() == TemplateName::UsingTemplate);
1044910449

10450+
if (Template.getAsTemplateDecl()->getKind() == Decl::TemplateTemplateParm) {
10451+
assert(!Qualifier && "unexpected qualified template template parameter");
10452+
assert(TemplateKeyword == false);
10453+
return Template;
10454+
}
10455+
1045010456
// FIXME: Canonicalization?
1045110457
llvm::FoldingSetNodeID ID;
1045210458
QualifiedTemplateName::Profile(ID, Qualifier, TemplateKeyword, Template);

clang/lib/AST/TemplateName.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -289,28 +289,23 @@ QualifiedTemplateName *TemplateName::getAsQualifiedTemplateName() const {
289289
return dyn_cast_if_present<QualifiedTemplateName *>(Storage);
290290
}
291291

292-
QualifiedTemplateName *
293-
TemplateName::getAsAdjustedQualifiedTemplateName() const {
294-
for (std::optional<TemplateName> Cur = *this; Cur;
295-
Cur = Cur->desugar(/*IgnoreDeduced=*/true))
296-
if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
297-
return N;
298-
return nullptr;
299-
}
300-
301292
DependentTemplateName *TemplateName::getAsDependentTemplateName() const {
302293
return Storage.dyn_cast<DependentTemplateName *>();
303294
}
304295

305-
NestedNameSpecifier TemplateName::getQualifier() const {
296+
std::tuple<NestedNameSpecifier, bool>
297+
TemplateName::getQualifierAndTemplateKeyword() const {
306298
for (std::optional<TemplateName> Cur = *this; Cur;
307299
Cur = Cur->desugar(/*IgnoreDeduced=*/true)) {
308300
if (DependentTemplateName *N = Cur->getAsDependentTemplateName())
309-
return N->getQualifier();
301+
return {N->getQualifier(), N->hasTemplateKeyword()};
310302
if (QualifiedTemplateName *N = Cur->getAsQualifiedTemplateName())
311-
return N->getQualifier();
303+
return {N->getQualifier(), N->hasTemplateKeyword()};
304+
if (Cur->getAsSubstTemplateTemplateParm() ||
305+
Cur->getAsSubstTemplateTemplateParmPack())
306+
break;
312307
}
313-
return std::nullopt;
308+
return {std::nullopt, false};
314309
}
315310

316311
UsingShadowDecl *TemplateName::getAsUsingShadowDecl() const {
@@ -448,8 +443,14 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
448443
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
449444
if (handleAnonymousTTP(Template, OS))
450445
return;
451-
if (Qual == Qualified::None || Policy.SuppressScope) {
452-
OS << *Template;
446+
if (Qual == Qualified::None || isa<TemplateTemplateParmDecl>(Template) ||
447+
Policy.SuppressScope) {
448+
if (IdentifierInfo *II = Template->getIdentifier();
449+
Policy.CleanUglifiedParameters && II &&
450+
isa<TemplateTemplateParmDecl>(Template))
451+
OS << II->deuglifiedName();
452+
else
453+
OS << *Template;
453454
} else {
454455
PrintingPolicy NestedNamePolicy = Policy;
455456
NestedNamePolicy.SuppressUnwrittenScope = true;
@@ -474,12 +475,7 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
474475
if (handleAnonymousTTP(UTD, OS))
475476
return;
476477

477-
if (IdentifierInfo *II = UTD->getIdentifier();
478-
Policy.CleanUglifiedParameters && II &&
479-
isa<TemplateTemplateParmDecl>(UTD))
480-
OS << II->deuglifiedName();
481-
else
482-
OS << *UTD;
478+
OS << *UTD;
483479
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
484480
DTN->print(OS, Policy);
485481
} else if (SubstTemplateTemplateParmStorage *subst =

clang/lib/AST/Type.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1961,12 +1961,10 @@ NestedNameSpecifier Type::getPrefix() const {
19611961
switch (getTypeClass()) {
19621962
case Type::DependentName:
19631963
return cast<DependentNameType>(this)->getQualifier();
1964-
case Type::TemplateSpecialization: {
1965-
QualifiedTemplateName *S = cast<TemplateSpecializationType>(this)
1966-
->getTemplateName()
1967-
.getAsAdjustedQualifiedTemplateName();
1968-
return S ? S->getQualifier() : std::nullopt;
1969-
}
1964+
case Type::TemplateSpecialization:
1965+
return cast<TemplateSpecializationType>(this)
1966+
->getTemplateName()
1967+
.getQualifier();
19701968
case Type::DependentTemplateSpecialization:
19711969
return cast<DependentTemplateSpecializationType>(this)
19721970
->getDependentTemplateName()

clang/lib/AST/TypeLoc.cpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -750,27 +750,25 @@ void TemplateSpecializationTypeLoc::set(SourceLocation ElaboratedKeywordLoc,
750750

751751
void TemplateSpecializationTypeLoc::initializeLocal(ASTContext &Context,
752752
SourceLocation Loc) {
753-
QualifiedTemplateName *Name =
754-
getTypePtr()->getTemplateName().getAsAdjustedQualifiedTemplateName();
753+
754+
auto [Qualifier, HasTemplateKeyword] =
755+
getTypePtr()->getTemplateName().getQualifierAndTemplateKeyword();
755756

756757
SourceLocation ElaboratedKeywordLoc =
757758
getTypePtr()->getKeyword() != ElaboratedTypeKeyword::None
758759
? Loc
759760
: SourceLocation();
760761

761762
NestedNameSpecifierLoc QualifierLoc;
762-
if (NestedNameSpecifier Qualifier =
763-
Name ? Name->getQualifier() : std::nullopt) {
763+
if (Qualifier) {
764764
NestedNameSpecifierLocBuilder Builder;
765765
Builder.MakeTrivial(Context, Qualifier, Loc);
766766
QualifierLoc = Builder.getWithLocInContext(Context);
767767
}
768768

769769
TemplateArgumentListInfo TAL(Loc, Loc);
770770
set(ElaboratedKeywordLoc, QualifierLoc,
771-
/*TemplateKeywordLoc=*/Name && Name->hasTemplateKeyword()
772-
? Loc
773-
: SourceLocation(),
771+
/*TemplateKeywordLoc=*/HasTemplateKeyword ? Loc : SourceLocation(),
774772
/*NameLoc=*/Loc, /*LAngleLoc=*/Loc, /*RAngleLoc=*/Loc);
775773
initializeArgLocs(Context, getTypePtr()->template_arguments(), getArgInfos(),
776774
Loc);

clang/lib/Sema/SemaLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4578,7 +4578,7 @@ static void getNestedNameSpecifierIdentifiers(
45784578
TemplateName Name =
45794579
cast<TemplateSpecializationType>(T)->getTemplateName();
45804580
if (const QualifiedTemplateName *QTN =
4581-
Name.getAsAdjustedQualifiedTemplateName()) {
4581+
Name.getAsQualifiedTemplateName()) {
45824582
getNestedNameSpecifierIdentifiers(QTN->getQualifier(), Identifiers);
45834583
Name = QTN->getUnderlyingTemplate();
45844584
}

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,9 +2124,11 @@ TemplateName TemplateInstantiator::TransformTemplateName(
21242124
NestedNameSpecifierLoc &QualifierLoc, SourceLocation TemplateKWLoc,
21252125
TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
21262126
NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
2127-
if (TemplateTemplateParmDecl *TTP
2128-
= dyn_cast_or_null<TemplateTemplateParmDecl>(Name.getAsTemplateDecl())) {
2129-
if (TTP->getDepth() < TemplateArgs.getNumLevels()) {
2127+
if (Name.getKind() == TemplateName::Template) {
2128+
assert(!QualifierLoc && "Unexpected qualifier");
2129+
if (auto *TTP =
2130+
dyn_cast<TemplateTemplateParmDecl>(Name.getAsTemplateDecl());
2131+
TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
21302132
// If the corresponding template argument is NULL or non-existent, it's
21312133
// because we are performing instantiation from explicitly-specified
21322134
// template arguments in a function template, but there were some
@@ -2169,13 +2171,6 @@ TemplateName TemplateInstantiator::TransformTemplateName(
21692171

21702172
TemplateName Template = Arg.getAsTemplate();
21712173
assert(!Template.isNull() && "Null template template argument");
2172-
2173-
if (NestedNameSpecifier Qualifier = Template.getQualifier()) {
2174-
NestedNameSpecifierLocBuilder Builder;
2175-
Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
2176-
QualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
2177-
}
2178-
21792174
return getSema().Context.getSubstTemplateTemplateParm(
21802175
Template, AssociatedDecl, TTP->getIndex(), PackIndex, Final);
21812176
}

clang/lib/Sema/TreeTransform.h

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -744,11 +744,6 @@ class TreeTransform {
744744

745745
StmtResult TransformSEHHandler(Stmt *Handler);
746746

747-
QualType TransformTemplateSpecializationType(TypeLocBuilder &TLB,
748-
TemplateSpecializationTypeLoc TL,
749-
TemplateName Template,
750-
CXXScopeSpec &SS);
751-
752747
QualType TransformDependentTemplateSpecializationType(
753748
TypeLocBuilder &TLB, DependentTemplateSpecializationTypeLoc TL,
754749
QualType ObjectType, NamedDecl *UnqualLookup,
@@ -1315,9 +1310,8 @@ class TreeTransform {
13151310
///
13161311
/// By default, builds the new template name directly. Subclasses may override
13171312
/// this routine to provide different behavior.
1318-
TemplateName RebuildTemplateName(CXXScopeSpec &SS,
1319-
bool TemplateKW,
1320-
TemplateDecl *Template);
1313+
TemplateName RebuildTemplateName(CXXScopeSpec &SS, bool TemplateKW,
1314+
TemplateName Name);
13211315

13221316
/// Build a new template name given a nested name specifier and the
13231317
/// name that is referred to as a template.
@@ -4822,9 +4816,7 @@ TemplateName TreeTransform<Derived>::TransformTemplateName(
48224816
TemplateName Name, SourceLocation NameLoc, QualType ObjectType,
48234817
NamedDecl *FirstQualifierInScope, bool AllowInjectedClassName) {
48244818
if (QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName()) {
4825-
// FIXME: Preserve UsingTemplateName.
4826-
TemplateDecl *Template = QTN->getUnderlyingTemplate().getAsTemplateDecl();
4827-
assert(Template && "qualified template name must refer to a template");
4819+
TemplateName UnderlyingName = QTN->getUnderlyingTemplate();
48284820

48294821
if (QualifierLoc) {
48304822
QualifierLoc = getDerived().TransformNestedNameSpecifierLoc(
@@ -4833,20 +4825,22 @@ TemplateName TreeTransform<Derived>::TransformTemplateName(
48334825
return TemplateName();
48344826
}
48354827

4836-
TemplateDecl *TransTemplate
4837-
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
4838-
Template));
4839-
if (!TransTemplate)
4828+
NestedNameSpecifierLoc UnderlyingQualifier;
4829+
TemplateName NewUnderlyingName = getDerived().TransformTemplateName(
4830+
UnderlyingQualifier, TemplateKWLoc, UnderlyingName, NameLoc, ObjectType,
4831+
FirstQualifierInScope, AllowInjectedClassName);
4832+
if (NewUnderlyingName.isNull())
48404833
return TemplateName();
4834+
assert(!UnderlyingQualifier && "unexpected qualifier");
48414835

48424836
if (!getDerived().AlwaysRebuild() &&
48434837
QualifierLoc.getNestedNameSpecifier() == QTN->getQualifier() &&
4844-
TransTemplate == Template)
4838+
NewUnderlyingName == UnderlyingName)
48454839
return Name;
48464840
CXXScopeSpec SS;
48474841
SS.Adopt(QualifierLoc);
48484842
return getDerived().RebuildTemplateName(SS, QTN->hasTemplateKeyword(),
4849-
TransTemplate);
4843+
NewUnderlyingName);
48504844
}
48514845

48524846
if (DependentTemplateName *DTN = Name.getAsDependentTemplateName()) {
@@ -4874,9 +4868,19 @@ TemplateName TreeTransform<Derived>::TransformTemplateName(
48744868

48754869
if (SubstTemplateTemplateParmStorage *S =
48764870
Name.getAsSubstTemplateTemplateParm()) {
4871+
assert(!QualifierLoc && "Unexpected qualified SubstTemplateTemplateParm");
4872+
4873+
NestedNameSpecifierLoc ReplacementQualifierLoc;
4874+
TemplateName ReplacementName = S->getReplacement();
4875+
if (NestedNameSpecifier Qualifier = ReplacementName.getQualifier()) {
4876+
NestedNameSpecifierLocBuilder Builder;
4877+
Builder.MakeTrivial(SemaRef.Context, Qualifier, NameLoc);
4878+
ReplacementQualifierLoc = Builder.getWithLocInContext(SemaRef.Context);
4879+
}
4880+
48774881
TemplateName NewName = getDerived().TransformTemplateName(
4878-
QualifierLoc, TemplateKWLoc, S->getReplacement(), NameLoc, ObjectType,
4879-
FirstQualifierInScope, AllowInjectedClassName);
4882+
ReplacementQualifierLoc, TemplateKWLoc, ReplacementName, NameLoc,
4883+
ObjectType, FirstQualifierInScope, AllowInjectedClassName);
48804884
if (NewName.isNull())
48814885
return TemplateName();
48824886
Decl *AssociatedDecl =
@@ -4892,21 +4896,17 @@ TemplateName TreeTransform<Derived>::TransformTemplateName(
48924896
assert(!Name.getAsDeducedTemplateName() &&
48934897
"DeducedTemplateName should not escape partial ordering");
48944898

4895-
if (TemplateDecl *Template = Name.getAsTemplateDecl()) {
4896-
assert(!QualifierLoc && "missed a Qualified Template");
4897-
TemplateDecl *TransTemplate
4898-
= cast_or_null<TemplateDecl>(getDerived().TransformDecl(NameLoc,
4899-
Template));
4900-
if (!TransTemplate)
4901-
return TemplateName();
4902-
4903-
CXXScopeSpec SS;
4904-
return getDerived().RebuildTemplateName(SS, /*TemplateKeyword=*/false,
4905-
TransTemplate);
4899+
// FIXME: Preserve UsingTemplateName.
4900+
if (auto *Template = Name.getAsTemplateDecl()) {
4901+
assert(!QualifierLoc && "Unexpected qualifier");
4902+
return TemplateName(cast_or_null<TemplateDecl>(
4903+
getDerived().TransformDecl(NameLoc, Template)));
49064904
}
49074905

49084906
if (SubstTemplateTemplateParmPackStorage *SubstPack
49094907
= Name.getAsSubstTemplateTemplateParmPack()) {
4908+
assert(!QualifierLoc &&
4909+
"Unexpected qualified SubstTemplateTemplateParmPack");
49104910
return getDerived().RebuildTemplateName(
49114911
SubstPack->getArgumentPack(), SubstPack->getAssociatedDecl(),
49124912
SubstPack->getIndex(), SubstPack->getFinal());
@@ -17497,13 +17497,12 @@ QualType TreeTransform<Derived>::RebuildDependentBitIntType(
1749717497
return SemaRef.BuildBitIntType(IsUnsigned, NumBitsExpr, Loc);
1749817498
}
1749917499

17500-
template<typename Derived>
17501-
TemplateName
17502-
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
17503-
bool TemplateKW,
17504-
TemplateDecl *Template) {
17500+
template <typename Derived>
17501+
TemplateName TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
17502+
bool TemplateKW,
17503+
TemplateName Name) {
1750517504
return SemaRef.Context.getQualifiedTemplateName(SS.getScopeRep(), TemplateKW,
17506-
TemplateName(Template));
17505+
Name);
1750717506
}
1750817507

1750917508
template <typename Derived>

0 commit comments

Comments
 (0)