Skip to content

Commit 13b55ad

Browse files
authored
[clang] implement printing of canonical expressions (#135133)
This patch extends the canonicalization printing policy to cover expressions and template names, and wires that up to the template argument printer, covering expressions, and to the expression within a dependent decltype. This is helpful for debugging, or if these expressions 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 dba757a commit 13b55ad

File tree

15 files changed

+1080
-22
lines changed

15 files changed

+1080
-22
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
@@ -33,7 +33,7 @@ bool MatchesAnyListedTypeNameMatcher::matches(
3333

3434
PrintingPolicy PrintingPolicyWithSuppressedTag(
3535
Finder->getASTContext().getLangOpts());
36-
PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = CanonicalTypes;
36+
PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes;
3737
PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
3838
PrintingPolicyWithSuppressedTag.SuppressScope = false;
3939
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: 9 additions & 7 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
}
@@ -1273,8 +1273,11 @@ void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
12731273

12741274
void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
12751275
OS << "decltype(";
1276-
if (T->getUnderlyingExpr())
1277-
T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
1276+
if (const Expr *E = T->getUnderlyingExpr()) {
1277+
PrintingPolicy ExprPolicy = Policy;
1278+
ExprPolicy.PrintAsCanonical = T->isCanonicalUnqualified();
1279+
E->printPretty(OS, nullptr, ExprPolicy);
1280+
}
12781281
OS << ')';
12791282
spaceBeforePlaceHolder(OS);
12801283
}
@@ -1548,7 +1551,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
15481551
const ASTTemplateArgumentListInfo *TArgAsWritten =
15491552
S->getTemplateArgsAsWritten();
15501553
IncludeStrongLifetimeRAII Strong(Policy);
1551-
if (TArgAsWritten && !Policy.PrintCanonicalTypes)
1554+
if (TArgAsWritten && !Policy.PrintAsCanonical)
15521555
printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,
15531556
TParams);
15541557
else
@@ -2422,9 +2425,8 @@ static void
24222425
printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
24232426
const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
24242427
// Drop trailing template arguments that match default arguments.
2425-
if (TPL && Policy.SuppressDefaultTemplateArgs &&
2426-
!Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
2427-
Args.size() <= TPL->size()) {
2428+
if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
2429+
!Args.empty() && !IsPack && Args.size() <= TPL->size()) {
24282430
llvm::SmallVector<TemplateArgument, 8> OrigArgs;
24292431
for (const TA &A : Args)
24302432
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)