Skip to content

Commit 77ee135

Browse files
committed
[clang] implement printing of canonical template arguments of expression kind
This patch extends the canonicalization printing policy to cover expressions and template names, and wires that up to the template argument printer, covering expressions. This is helpful for debugging, or if these template arguments somehow end up in diagnostics, as without this patch they can print as completely unrelated expressions, which can be quite confusing. This is because expressions are not uniqued, unlike types, and when a template specialization containing an expression is the first to be canonicalized, the expression ends up appearing in the canonical type of subsequent equivalent specializations. Fixes #92292
1 parent 3954d25 commit 77ee135

14 files changed

+1058
-20
lines changed

clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ void StaticAccessedThroughInstanceCheck::check(
6969
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
7070
PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
7171

72-
PrintingPolicyWithSuppressedTag.PrintCanonicalTypes =
72+
PrintingPolicyWithSuppressedTag.PrintAsCanonical =
7373
!BaseExpr->getType()->isTypedefNameType();
7474

7575
std::string BaseTypeName =

clang-tools-extra/clang-tidy/utils/Matchers.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ bool MatchesAnyListedTypeNameMatcher::matches(
3232

3333
PrintingPolicy PrintingPolicyWithSuppressedTag(
3434
Finder->getASTContext().getLangOpts());
35-
PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = true;
35+
PrintingPolicyWithSuppressedTag.PrintAsCanonical = true;
3636
PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
3737
PrintingPolicyWithSuppressedTag.SuppressScope = false;
3838
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;

clang/include/clang/AST/PrettyPrinter.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ struct PrintingPolicy {
7676
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
7777
MSVCFormatting(false), ConstantsAsWritten(false),
7878
SuppressImplicitBase(false), FullyQualifiedName(false),
79-
PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
79+
PrintAsCanonical(false), PrintInjectedClassNameWithArguments(true),
8080
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
8181
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
8282
UseEnumerators(true), UseHLSLTypes(LO.HLSL) {}
@@ -310,9 +310,9 @@ struct PrintingPolicy {
310310
LLVM_PREFERRED_TYPE(bool)
311311
unsigned FullyQualifiedName : 1;
312312

313-
/// Whether to print types as written or canonically.
313+
/// Whether to print entities as written or canonically.
314314
LLVM_PREFERRED_TYPE(bool)
315-
unsigned PrintCanonicalTypes : 1;
315+
unsigned PrintAsCanonical : 1;
316316

317317
/// Whether to print an InjectedClassNameType with template arguments or as
318318
/// written. When a template argument is unnamed, printing it results in

clang/lib/AST/DeclPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
735735
llvm::raw_string_ostream POut(Proto);
736736
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
737737
const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
738-
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
738+
if (TArgAsWritten && !Policy.PrintAsCanonical)
739739
TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), nullptr);
740740
else if (const TemplateArgumentList *TArgs =
741741
D->getTemplateSpecializationArgs())
@@ -1124,7 +1124,7 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
11241124
S->getSpecializedTemplate()->getTemplateParameters();
11251125
const ASTTemplateArgumentListInfo *TArgAsWritten =
11261126
S->getTemplateArgsAsWritten();
1127-
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
1127+
if (TArgAsWritten && !Policy.PrintAsCanonical)
11281128
printTemplateArguments(TArgAsWritten->arguments(), TParams);
11291129
else
11301130
printTemplateArguments(S->getTemplateArgs().asArray(), TParams);

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1724,6 +1724,8 @@ void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
17241724
void JSONNodeDumper::VisitExpressionTemplateArgument(
17251725
const TemplateArgument &TA) {
17261726
JOS.attribute("isExpr", true);
1727+
if (TA.isCanonicalExpr())
1728+
JOS.attribute("isCanonical", true);
17271729
}
17281730
void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
17291731
JOS.attribute("isPack", true);

clang/lib/AST/StmtPrinter.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1305,9 +1305,13 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
13051305
Qualifier->print(OS, Policy);
13061306
if (Node->hasTemplateKeyword())
13071307
OS << "template ";
1308+
1309+
bool ForceAnonymous =
1310+
Policy.PrintAsCanonical && VD->getKind() == Decl::NonTypeTemplateParm;
13081311
DeclarationNameInfo NameInfo = Node->getNameInfo();
13091312
if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
1310-
ID || NameInfo.getName().getNameKind() != DeclarationName::Identifier) {
1313+
!ForceAnonymous &&
1314+
(ID || NameInfo.getName().getNameKind() != DeclarationName::Identifier)) {
13111315
if (Policy.CleanUglifiedParameters &&
13121316
isa<ParmVarDecl, NonTypeTemplateParmDecl>(VD) && ID)
13131317
OS << ID->deuglifiedName();

clang/lib/AST/TemplateBase.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -559,9 +559,12 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
559559
printIntegral(*this, Out, Policy, IncludeType);
560560
break;
561561

562-
case Expression:
563-
getAsExpr()->printPretty(Out, nullptr, Policy);
562+
case Expression: {
563+
PrintingPolicy ExprPolicy = Policy;
564+
ExprPolicy.PrintAsCanonical = isCanonicalExpr();
565+
getAsExpr()->printPretty(Out, nullptr, ExprPolicy);
564566
break;
567+
}
565568

566569
case Pack:
567570
Out << "<";

clang/lib/AST/TemplateName.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -410,9 +410,9 @@ bool TemplateName::containsUnexpandedParameterPack() const {
410410

411411
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
412412
Qualified Qual) const {
413-
auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
413+
auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {
414414
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
415-
TTP && TTP->getIdentifier() == nullptr) {
415+
TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {
416416
OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
417417
return true;
418418
}
@@ -430,13 +430,19 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
430430
// names more often than to export them, thus using the original name is
431431
// most useful in this case.
432432
TemplateDecl *Template = getAsTemplateDecl();
433+
if (Policy.PrintAsCanonical)
434+
Template = cast<TemplateDecl>(Template->getCanonicalDecl());
433435
if (handleAnonymousTTP(Template, OS))
434436
return;
435437
if (Qual == Qualified::None)
436438
OS << *Template;
437439
else
438440
Template->printQualifiedName(OS, Policy);
439441
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
442+
if (Policy.PrintAsCanonical) {
443+
QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
444+
return;
445+
}
440446
if (NestedNameSpecifier *NNS = QTN->getQualifier();
441447
Qual != Qualified::None && NNS)
442448
NNS->print(OS, Policy);

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1357,6 +1357,8 @@ void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
13571357
void TextNodeDumper::VisitExpressionTemplateArgument(
13581358
const TemplateArgument &TA) {
13591359
OS << " expr";
1360+
if (TA.isCanonicalExpr())
1361+
OS << " canonical";
13601362
dumpTemplateArgument(TA);
13611363
}
13621364

clang/lib/AST/TypePrinter.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
177177

178178
static SplitQualType splitAccordingToPolicy(QualType QT,
179179
const PrintingPolicy &Policy) {
180-
if (Policy.PrintCanonicalTypes)
180+
if (Policy.PrintAsCanonical)
181181
QT = QT.getCanonicalType();
182182
return QT.split();
183183
}
@@ -1548,7 +1548,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
15481548
const ASTTemplateArgumentListInfo *TArgAsWritten =
15491549
S->getTemplateArgsAsWritten();
15501550
IncludeStrongLifetimeRAII Strong(Policy);
1551-
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
1551+
if (TArgAsWritten && !Policy.PrintAsCanonical)
15521552
printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,
15531553
TParams);
15541554
else
@@ -2422,9 +2422,8 @@ static void
24222422
printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
24232423
const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
24242424
// Drop trailing template arguments that match default arguments.
2425-
if (TPL && Policy.SuppressDefaultTemplateArgs &&
2426-
!Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
2427-
Args.size() <= TPL->size()) {
2425+
if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
2426+
!Args.empty() && !IsPack && Args.size() <= TPL->size()) {
24282427
llvm::SmallVector<TemplateArgument, 8> OrigArgs;
24292428
for (const TA &A : Args)
24302429
OrigArgs.push_back(getArgument(A));

clang/lib/CodeGen/CGDebugInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
287287

288288
PP.SuppressInlineNamespace =
289289
PrintingPolicy::SuppressInlineNamespaceMode::None;
290-
PP.PrintCanonicalTypes = true;
290+
PP.PrintAsCanonical = true;
291291
PP.UsePreferredNames = false;
292292
PP.AlwaysIncludeTypeForTemplateArgument = true;
293293
PP.UseEnumerators = false;

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3463,7 +3463,7 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
34633463
{
34643464
llvm::raw_string_ostream Out(Description);
34653465
PrintingPolicy Policy = getPrintingPolicy();
3466-
Policy.PrintCanonicalTypes = true;
3466+
Policy.PrintAsCanonical = true;
34673467
FailedBooleanConditionPrinterHelper Helper(Policy);
34683468
FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
34693469
}

0 commit comments

Comments
 (0)