Skip to content

Commit 40e3c0f

Browse files
committed
[clang] Preserve Qualifiers and type sugar in TemplateNames
This patch improves the preservation of qualifiers and loss of type sugar in TemplateNames. This problem is analogous to https://reviews.llvm.org/D112374 and this patch takes a very similar approach to that patch, except the impact here is much lesser. When a TemplateName was written bare, without qualifications, we wouldn't produce a QualifiedTemplate which could be used to disambiguate it from a Canonical TemplateName. This had effects in the TemplateName printer, which had workarounds to deal with this, and wouldn't print the TemplateName as-written in most situations. There are also some related fixes to help preserve this type sugar along the way into diagnostics, so that this patch can be properly tested. - Fix dropping the template keyword. - Fix type deduction to preserve sugar in TST TemplateNames.
1 parent 86e3852 commit 40e3c0f

File tree

56 files changed

+310
-235
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+310
-235
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,8 @@ Bug Fixes to AST Handling
804804
- Clang now properly preserves ``FoundDecls`` within a ``ConceptReference``. (#GH82628)
805805
- The presence of the ``typename`` keyword is now stored in ``TemplateTemplateParmDecl``.
806806
- Fixed malformed AST generated for anonymous union access in templates. (#GH90842)
807+
- Improved preservation of qualifiers and sugar in TemplateNames, including
808+
template keyword.
807809

808810
Miscellaneous Bug Fixes
809811
^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/AST/TemplateName.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ class TemplateName {
332332
/// unexpanded parameter pack (for C++0x variadic templates).
333333
bool containsUnexpandedParameterPack() const;
334334

335-
enum class Qualified { None, AsWritten, Fully };
335+
enum class Qualified { None, AsWritten };
336336
/// Print the template name.
337337
///
338338
/// \param OS the output stream to which the template name will be

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8988,6 +8988,9 @@ class Sema final : public SemaBase {
89888988
const TemplateArgumentListInfo *TemplateArgs);
89898989

89908990
void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc);
8991+
void diagnoseMissingTemplateArguments(const CXXScopeSpec &SS,
8992+
bool TemplateKeyword, TemplateDecl *TD,
8993+
SourceLocation Loc);
89918994

89928995
ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS,
89938996
SourceLocation TemplateKWLoc, LookupResult &R,

clang/lib/AST/ASTContext.cpp

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5006,9 +5006,6 @@ ASTContext::getTemplateSpecializationType(TemplateName Template,
50065006
QualType Underlying) const {
50075007
assert(!Template.getAsDependentTemplateName() &&
50085008
"No dependent template names here!");
5009-
// Look through qualified template names.
5010-
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
5011-
Template = QTN->getUnderlyingTemplate();
50125009

50135010
const auto *TD = Template.getAsTemplateDecl();
50145011
bool IsTypeAlias = TD && TD->isTypeAlias();
@@ -5044,10 +5041,6 @@ QualType ASTContext::getCanonicalTemplateSpecializationType(
50445041
assert(!Template.getAsDependentTemplateName() &&
50455042
"No dependent template names here!");
50465043

5047-
// Look through qualified template names.
5048-
if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
5049-
Template = TemplateName(QTN->getUnderlyingTemplate());
5050-
50515044
// Build the canonical template specialization type.
50525045
TemplateName CanonTemplate = getCanonicalTemplateName(Template);
50535046
bool AnyNonCanonArgs = false;
@@ -5262,10 +5255,12 @@ TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) {
52625255
Arg = TemplateArgument(E);
52635256
} else {
52645257
auto *TTP = cast<TemplateTemplateParmDecl>(Param);
5258+
TemplateName Name = getQualifiedTemplateName(
5259+
nullptr, /*TemplateKeyword=*/false, TemplateName(TTP));
52655260
if (TTP->isParameterPack())
5266-
Arg = TemplateArgument(TemplateName(TTP), std::optional<unsigned>());
5261+
Arg = TemplateArgument(Name, std::optional<unsigned>());
52675262
else
5268-
Arg = TemplateArgument(TemplateName(TTP));
5263+
Arg = TemplateArgument(Name);
52695264
}
52705265

52715266
if (Param->isTemplateParameterPack())
@@ -9304,7 +9299,8 @@ TemplateName ASTContext::getAssumedTemplateName(DeclarationName Name) const {
93049299
TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS,
93059300
bool TemplateKeyword,
93069301
TemplateName Template) const {
9307-
assert(NNS && "Missing nested-name-specifier in qualified template name");
9302+
assert(Template.getKind() == TemplateName::Template ||
9303+
Template.getKind() == TemplateName::UsingTemplate);
93089304

93099305
// FIXME: Canonicalization?
93109306
llvm::FoldingSetNodeID ID;

clang/lib/AST/DeclTemplate.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -627,9 +627,10 @@ ClassTemplateDecl::getInjectedClassNameSpecialization() {
627627
TemplateParameterList *Params = getTemplateParameters();
628628
SmallVector<TemplateArgument, 16> TemplateArgs;
629629
Context.getInjectedTemplateArgs(Params, TemplateArgs);
630-
CommonPtr->InjectedClassNameType
631-
= Context.getTemplateSpecializationType(TemplateName(this),
632-
TemplateArgs);
630+
TemplateName Name = Context.getQualifiedTemplateName(
631+
/*NNS=*/nullptr, /*TemplateKeyword=*/false, TemplateName(this));
632+
CommonPtr->InjectedClassNameType =
633+
Context.getTemplateSpecializationType(Name, TemplateArgs);
633634
return CommonPtr->InjectedClassNameType;
634635
}
635636

clang/lib/AST/ODRHash.cpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,17 @@ void ODRHash::AddTemplateName(TemplateName Name) {
146146
case TemplateName::Template:
147147
AddDecl(Name.getAsTemplateDecl());
148148
break;
149+
case TemplateName::QualifiedTemplate: {
150+
QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
151+
if (NestedNameSpecifier *NNS = QTN->getQualifier())
152+
AddNestedNameSpecifier(NNS);
153+
AddBoolean(QTN->hasTemplateKeyword());
154+
AddTemplateName(QTN->getUnderlyingTemplate());
155+
break;
156+
}
149157
// TODO: Support these cases.
150158
case TemplateName::OverloadedTemplate:
151159
case TemplateName::AssumedTemplate:
152-
case TemplateName::QualifiedTemplate:
153160
case TemplateName::DependentTemplate:
154161
case TemplateName::SubstTemplateTemplateParm:
155162
case TemplateName::SubstTemplateTemplateParmPack:

clang/lib/AST/TemplateBase.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -547,7 +547,7 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
547547
const auto *TTP = cast<TemplateTemplateParmDecl>(TD);
548548
Out << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
549549
} else {
550-
TN.print(Out, Policy, TemplateName::Qualified::Fully);
550+
TN.print(Out, Policy);
551551
}
552552
break;
553553
}

clang/lib/AST/TemplateName.cpp

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -235,8 +235,8 @@ TemplateNameDependence TemplateName::getDependence() const {
235235
auto D = TemplateNameDependence::None;
236236
switch (getKind()) {
237237
case TemplateName::NameKind::QualifiedTemplate:
238-
D |= toTemplateNameDependence(
239-
getAsQualifiedTemplateName()->getQualifier()->getDependence());
238+
if (NestedNameSpecifier *NNS = getAsQualifiedTemplateName()->getQualifier())
239+
D |= toTemplateNameDependence(NNS->getDependence());
240240
break;
241241
case TemplateName::NameKind::DependentTemplate:
242242
D |= toTemplateNameDependence(
@@ -292,9 +292,8 @@ void TemplateName::Profile(llvm::FoldingSetNodeID &ID) {
292292

293293
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
294294
Qualified Qual) const {
295-
auto Kind = getKind();
296-
TemplateDecl *Template = nullptr;
297-
if (Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
295+
if (NameKind Kind = getKind();
296+
Kind == TemplateName::Template || Kind == TemplateName::UsingTemplate) {
298297
// After `namespace ns { using std::vector }`, what is the fully-qualified
299298
// name of the UsingTemplateName `vector` within ns?
300299
//
@@ -304,46 +303,43 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
304303
// Similar to the UsingType behavior, using declarations are used to import
305304
// names more often than to export them, thus using the original name is
306305
// most useful in this case.
307-
Template = getAsTemplateDecl();
308-
}
309-
310-
if (Template)
311-
if (Policy.CleanUglifiedParameters &&
312-
isa<TemplateTemplateParmDecl>(Template) && Template->getIdentifier())
313-
OS << Template->getIdentifier()->deuglifiedName();
314-
else if (Qual == Qualified::Fully &&
315-
getDependence() !=
316-
TemplateNameDependenceScope::DependentInstantiation)
317-
Template->printQualifiedName(OS, Policy);
318-
else
306+
TemplateDecl *Template = getAsTemplateDecl();
307+
if (Qual == Qualified::None)
319308
OS << *Template;
320-
else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
321-
if (Qual == Qualified::Fully &&
322-
getDependence() !=
323-
TemplateNameDependenceScope::DependentInstantiation) {
324-
QTN->getUnderlyingTemplate().getAsTemplateDecl()->printQualifiedName(
325-
OS, Policy);
326-
return;
327-
}
328-
if (Qual == Qualified::AsWritten)
329-
QTN->getQualifier()->print(OS, Policy);
309+
else
310+
Template->printQualifiedName(OS, Policy);
311+
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
312+
if (NestedNameSpecifier *NNS = QTN->getQualifier();
313+
Qual != Qualified::None && NNS)
314+
NNS->print(OS, Policy);
330315
if (QTN->hasTemplateKeyword())
331316
OS << "template ";
332-
OS << *QTN->getUnderlyingTemplate().getAsTemplateDecl();
317+
318+
TemplateName Underlying = QTN->getUnderlyingTemplate();
319+
assert(Underlying.getKind() == TemplateName::Template ||
320+
Underlying.getKind() == TemplateName::UsingTemplate);
321+
322+
TemplateDecl *UTD = Underlying.getAsTemplateDecl();
323+
if (IdentifierInfo *II = UTD->getIdentifier();
324+
Policy.CleanUglifiedParameters && II &&
325+
isa<TemplateTemplateParmDecl>(UTD))
326+
OS << II->deuglifiedName();
327+
else
328+
OS << *UTD;
333329
} else if (DependentTemplateName *DTN = getAsDependentTemplateName()) {
334-
if (Qual == Qualified::AsWritten && DTN->getQualifier())
335-
DTN->getQualifier()->print(OS, Policy);
330+
if (NestedNameSpecifier *NNS = DTN->getQualifier())
331+
NNS->print(OS, Policy);
336332
OS << "template ";
337333

338334
if (DTN->isIdentifier())
339335
OS << DTN->getIdentifier()->getName();
340336
else
341337
OS << "operator " << getOperatorSpelling(DTN->getOperator());
342-
} else if (SubstTemplateTemplateParmStorage *subst
343-
= getAsSubstTemplateTemplateParm()) {
338+
} else if (SubstTemplateTemplateParmStorage *subst =
339+
getAsSubstTemplateTemplateParm()) {
344340
subst->getReplacement().print(OS, Policy, Qual);
345-
} else if (SubstTemplateTemplateParmPackStorage *SubstPack
346-
= getAsSubstTemplateTemplateParmPack())
341+
} else if (SubstTemplateTemplateParmPackStorage *SubstPack =
342+
getAsSubstTemplateTemplateParmPack())
347343
OS << *SubstPack->getParameterPack();
348344
else if (AssumedTemplateStorage *Assumed = getAsAssumedTemplateName()) {
349345
Assumed->getDeclName().print(OS, Policy);

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1988,15 +1988,15 @@ void TextNodeDumper::VisitAutoType(const AutoType *T) {
19881988

19891989
void TextNodeDumper::VisitDeducedTemplateSpecializationType(
19901990
const DeducedTemplateSpecializationType *T) {
1991-
if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
1991+
if (T->getTemplateName().getAsUsingShadowDecl())
19921992
OS << " using";
19931993
}
19941994

19951995
void TextNodeDumper::VisitTemplateSpecializationType(
19961996
const TemplateSpecializationType *T) {
19971997
if (T->isTypeAlias())
19981998
OS << " alias";
1999-
if (T->getTemplateName().getKind() == TemplateName::UsingTemplate)
1999+
if (T->getTemplateName().getAsUsingShadowDecl())
20002000
OS << " using";
20012001
OS << " ";
20022002
T->getTemplateName().dump(OS);

clang/lib/AST/Type.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4251,7 +4251,8 @@ TemplateSpecializationType::TemplateSpecializationType(
42514251
assert((T.getKind() == TemplateName::Template ||
42524252
T.getKind() == TemplateName::SubstTemplateTemplateParm ||
42534253
T.getKind() == TemplateName::SubstTemplateTemplateParmPack ||
4254-
T.getKind() == TemplateName::UsingTemplate) &&
4254+
T.getKind() == TemplateName::UsingTemplate ||
4255+
T.getKind() == TemplateName::QualifiedTemplate) &&
42554256
"Unexpected template name for TemplateSpecializationType");
42564257

42574258
auto *TemplateArgs = reinterpret_cast<TemplateArgument *>(this + 1);

0 commit comments

Comments
 (0)