[clang] [clang-tools-extra] [clang] implement printing of canonical expressions (PR #135133)
Matheus Izvekov via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 13 09:15:44 PDT 2025
https://github.com/mizvekov updated https://github.com/llvm/llvm-project/pull/135133
>From aaf5482c91f73431e1290cab640d01f4b3f39692 Mon Sep 17 00:00:00 2001
From: Matheus Izvekov <mizvekov at gmail.com>
Date: Thu, 10 Apr 2025 02:52:36 -0300
Subject: [PATCH] [clang] implement printing of canonical expressions
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 https://github.com/llvm/llvm-project/issues/92292
---
.../StaticAccessedThroughInstanceCheck.cpp | 2 +-
.../clang-tidy/utils/Matchers.cpp | 2 +-
clang/include/clang/AST/PrettyPrinter.h | 6 +-
clang/lib/AST/DeclPrinter.cpp | 4 +-
clang/lib/AST/JSONNodeDumper.cpp | 2 +
clang/lib/AST/StmtPrinter.cpp | 6 +-
clang/lib/AST/TemplateBase.cpp | 7 +-
clang/lib/AST/TemplateName.cpp | 10 +-
clang/lib/AST/TextNodeDumper.cpp | 2 +
clang/lib/AST/TypePrinter.cpp | 16 +-
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
clang/lib/Sema/SemaTemplate.cpp | 2 +-
clang/test/AST/ast-dump-templates.cpp | 1022 +++++++++++++++++
.../test/CXX/temp/temp.decls/temp.mem/p5.cpp | 17 +
clang/unittests/AST/TypePrinterTest.cpp | 2 +-
15 files changed, 1080 insertions(+), 22 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index 08adc7134cfea..fffb136e5a332 100644
--- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -69,7 +69,7 @@ void StaticAccessedThroughInstanceCheck::check(
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
- PrintingPolicyWithSuppressedTag.PrintCanonicalTypes =
+ PrintingPolicyWithSuppressedTag.PrintAsCanonical =
!BaseExpr->getType()->isTypedefNameType();
std::string BaseTypeName =
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index 742dc6fda8c92..4974a9cdb9f4b 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -33,7 +33,7 @@ bool MatchesAnyListedTypeNameMatcher::matches(
PrintingPolicy PrintingPolicyWithSuppressedTag(
Finder->getASTContext().getLangOpts());
- PrintingPolicyWithSuppressedTag.PrintCanonicalTypes = CanonicalTypes;
+ PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes;
PrintingPolicyWithSuppressedTag.SuppressElaboration = true;
PrintingPolicyWithSuppressedTag.SuppressScope = false;
PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 91818776b770c..5a98ae1987b16 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -76,7 +76,7 @@ struct PrintingPolicy {
MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true),
MSVCFormatting(false), ConstantsAsWritten(false),
SuppressImplicitBase(false), FullyQualifiedName(false),
- PrintCanonicalTypes(false), PrintInjectedClassNameWithArguments(true),
+ PrintAsCanonical(false), PrintInjectedClassNameWithArguments(true),
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
UseEnumerators(true), UseHLSLTypes(LO.HLSL) {}
@@ -310,9 +310,9 @@ struct PrintingPolicy {
LLVM_PREFERRED_TYPE(bool)
unsigned FullyQualifiedName : 1;
- /// Whether to print types as written or canonically.
+ /// Whether to print entities as written or canonically.
LLVM_PREFERRED_TYPE(bool)
- unsigned PrintCanonicalTypes : 1;
+ unsigned PrintAsCanonical : 1;
/// Whether to print an InjectedClassNameType with template arguments or as
/// written. When a template argument is unnamed, printing it results in
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 28098b242d494..22da5bf251ecd 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -735,7 +735,7 @@ void DeclPrinter::VisitFunctionDecl(FunctionDecl *D) {
llvm::raw_string_ostream POut(Proto);
DeclPrinter TArgPrinter(POut, SubPolicy, Context, Indentation);
const auto *TArgAsWritten = D->getTemplateSpecializationArgsAsWritten();
- if (TArgAsWritten && !Policy.PrintCanonicalTypes)
+ if (TArgAsWritten && !Policy.PrintAsCanonical)
TArgPrinter.printTemplateArguments(TArgAsWritten->arguments(), nullptr);
else if (const TemplateArgumentList *TArgs =
D->getTemplateSpecializationArgs())
@@ -1124,7 +1124,7 @@ void DeclPrinter::VisitCXXRecordDecl(CXXRecordDecl *D) {
S->getSpecializedTemplate()->getTemplateParameters();
const ASTTemplateArgumentListInfo *TArgAsWritten =
S->getTemplateArgsAsWritten();
- if (TArgAsWritten && !Policy.PrintCanonicalTypes)
+ if (TArgAsWritten && !Policy.PrintAsCanonical)
printTemplateArguments(TArgAsWritten->arguments(), TParams);
else
printTemplateArguments(S->getTemplateArgs().asArray(), TParams);
diff --git a/clang/lib/AST/JSONNodeDumper.cpp b/clang/lib/AST/JSONNodeDumper.cpp
index 3420c1f343cf5..164b3cad4f7aa 100644
--- a/clang/lib/AST/JSONNodeDumper.cpp
+++ b/clang/lib/AST/JSONNodeDumper.cpp
@@ -1724,6 +1724,8 @@ void JSONNodeDumper::VisitTemplateExpansionTemplateArgument(
void JSONNodeDumper::VisitExpressionTemplateArgument(
const TemplateArgument &TA) {
JOS.attribute("isExpr", true);
+ if (TA.isCanonicalExpr())
+ JOS.attribute("isCanonical", true);
}
void JSONNodeDumper::VisitPackTemplateArgument(const TemplateArgument &TA) {
JOS.attribute("isPack", true);
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index dbe2432d5c799..aae10fd3bd885 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1305,9 +1305,13 @@ void StmtPrinter::VisitDeclRefExpr(DeclRefExpr *Node) {
Qualifier->print(OS, Policy);
if (Node->hasTemplateKeyword())
OS << "template ";
+
+ bool ForceAnonymous =
+ Policy.PrintAsCanonical && VD->getKind() == Decl::NonTypeTemplateParm;
DeclarationNameInfo NameInfo = Node->getNameInfo();
if (IdentifierInfo *ID = NameInfo.getName().getAsIdentifierInfo();
- ID || NameInfo.getName().getNameKind() != DeclarationName::Identifier) {
+ !ForceAnonymous &&
+ (ID || NameInfo.getName().getNameKind() != DeclarationName::Identifier)) {
if (Policy.CleanUglifiedParameters &&
isa<ParmVarDecl, NonTypeTemplateParmDecl>(VD) && ID)
OS << ID->deuglifiedName();
diff --git a/clang/lib/AST/TemplateBase.cpp b/clang/lib/AST/TemplateBase.cpp
index ad4f919b7483e..17a4462dd5188 100644
--- a/clang/lib/AST/TemplateBase.cpp
+++ b/clang/lib/AST/TemplateBase.cpp
@@ -559,9 +559,12 @@ void TemplateArgument::print(const PrintingPolicy &Policy, raw_ostream &Out,
printIntegral(*this, Out, Policy, IncludeType);
break;
- case Expression:
- getAsExpr()->printPretty(Out, nullptr, Policy);
+ case Expression: {
+ PrintingPolicy ExprPolicy = Policy;
+ ExprPolicy.PrintAsCanonical = isCanonicalExpr();
+ getAsExpr()->printPretty(Out, nullptr, ExprPolicy);
break;
+ }
case Pack:
Out << "<";
diff --git a/clang/lib/AST/TemplateName.cpp b/clang/lib/AST/TemplateName.cpp
index 4404552f84fbb..c5861ba33f850 100644
--- a/clang/lib/AST/TemplateName.cpp
+++ b/clang/lib/AST/TemplateName.cpp
@@ -410,9 +410,9 @@ bool TemplateName::containsUnexpandedParameterPack() const {
void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
Qualified Qual) const {
- auto handleAnonymousTTP = [](TemplateDecl *TD, raw_ostream &OS) {
+ auto handleAnonymousTTP = [&](TemplateDecl *TD, raw_ostream &OS) {
if (TemplateTemplateParmDecl *TTP = dyn_cast<TemplateTemplateParmDecl>(TD);
- TTP && TTP->getIdentifier() == nullptr) {
+ TTP && (Policy.PrintAsCanonical || TTP->getIdentifier() == nullptr)) {
OS << "template-parameter-" << TTP->getDepth() << "-" << TTP->getIndex();
return true;
}
@@ -430,6 +430,8 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
// names more often than to export them, thus using the original name is
// most useful in this case.
TemplateDecl *Template = getAsTemplateDecl();
+ if (Policy.PrintAsCanonical)
+ Template = cast<TemplateDecl>(Template->getCanonicalDecl());
if (handleAnonymousTTP(Template, OS))
return;
if (Qual == Qualified::None)
@@ -437,6 +439,10 @@ void TemplateName::print(raw_ostream &OS, const PrintingPolicy &Policy,
else
Template->printQualifiedName(OS, Policy);
} else if (QualifiedTemplateName *QTN = getAsQualifiedTemplateName()) {
+ if (Policy.PrintAsCanonical) {
+ QTN->getUnderlyingTemplate().print(OS, Policy, Qual);
+ return;
+ }
if (NestedNameSpecifier *NNS = QTN->getQualifier();
Qual != Qualified::None && NNS)
NNS->print(OS, Policy);
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index be8d609974d81..7861e180338bc 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1357,6 +1357,8 @@ void TextNodeDumper::VisitTemplateExpansionTemplateArgument(
void TextNodeDumper::VisitExpressionTemplateArgument(
const TemplateArgument &TA) {
OS << " expr";
+ if (TA.isCanonicalExpr())
+ OS << " canonical";
dumpTemplateArgument(TA);
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4f2b00d19a446..cc8c874140167 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -177,7 +177,7 @@ void TypePrinter::spaceBeforePlaceHolder(raw_ostream &OS) {
static SplitQualType splitAccordingToPolicy(QualType QT,
const PrintingPolicy &Policy) {
- if (Policy.PrintCanonicalTypes)
+ if (Policy.PrintAsCanonical)
QT = QT.getCanonicalType();
return QT.split();
}
@@ -1273,8 +1273,11 @@ void TypePrinter::printTypeOfAfter(const TypeOfType *T, raw_ostream &OS) {}
void TypePrinter::printDecltypeBefore(const DecltypeType *T, raw_ostream &OS) {
OS << "decltype(";
- if (T->getUnderlyingExpr())
- T->getUnderlyingExpr()->printPretty(OS, nullptr, Policy);
+ if (const Expr *E = T->getUnderlyingExpr()) {
+ PrintingPolicy ExprPolicy = Policy;
+ ExprPolicy.PrintAsCanonical = T->isCanonicalUnqualified();
+ E->printPretty(OS, nullptr, ExprPolicy);
+ }
OS << ')';
spaceBeforePlaceHolder(OS);
}
@@ -1548,7 +1551,7 @@ void TypePrinter::printTag(TagDecl *D, raw_ostream &OS) {
const ASTTemplateArgumentListInfo *TArgAsWritten =
S->getTemplateArgsAsWritten();
IncludeStrongLifetimeRAII Strong(Policy);
- if (TArgAsWritten && !Policy.PrintCanonicalTypes)
+ if (TArgAsWritten && !Policy.PrintAsCanonical)
printTemplateArgumentList(OS, TArgAsWritten->arguments(), Policy,
TParams);
else
@@ -2422,9 +2425,8 @@ static void
printTo(raw_ostream &OS, ArrayRef<TA> Args, const PrintingPolicy &Policy,
const TemplateParameterList *TPL, bool IsPack, unsigned ParmIndex) {
// Drop trailing template arguments that match default arguments.
- if (TPL && Policy.SuppressDefaultTemplateArgs &&
- !Policy.PrintCanonicalTypes && !Args.empty() && !IsPack &&
- Args.size() <= TPL->size()) {
+ if (TPL && Policy.SuppressDefaultTemplateArgs && !Policy.PrintAsCanonical &&
+ !Args.empty() && !IsPack && Args.size() <= TPL->size()) {
llvm::SmallVector<TemplateArgument, 8> OrigArgs;
for (const TA &A : Args)
OrigArgs.push_back(getArgument(A));
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index d659243d38d5f..0dc503f6f83f7 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -287,7 +287,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.SuppressInlineNamespace =
PrintingPolicy::SuppressInlineNamespaceMode::None;
- PP.PrintCanonicalTypes = true;
+ PP.PrintAsCanonical = true;
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
PP.UseEnumerators = false;
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 40e29bb18807a..6b7892fa30989 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3463,7 +3463,7 @@ Sema::findFailedBooleanCondition(Expr *Cond) {
{
llvm::raw_string_ostream Out(Description);
PrintingPolicy Policy = getPrintingPolicy();
- Policy.PrintCanonicalTypes = true;
+ Policy.PrintAsCanonical = true;
FailedBooleanConditionPrinterHelper Helper(Policy);
FailedCond->printPretty(Out, &Helper, Policy, 0, "\n", nullptr);
}
diff --git a/clang/test/AST/ast-dump-templates.cpp b/clang/test/AST/ast-dump-templates.cpp
index d6982a0927e8c..b504accb927dc 100644
--- a/clang/test/AST/ast-dump-templates.cpp
+++ b/clang/test/AST/ast-dump-templates.cpp
@@ -178,6 +178,48 @@ namespace TestDependentMemberPointer {
// DUMP-NEXT: `-BuiltinType {{.+}} 'int'
} // namespace TestDependentMemberPointer
+namespace TestPartialSpecNTTP {
+// DUMP-LABEL: NamespaceDecl {{.+}} TestPartialSpecNTTP{{$}}
+ template <class TA1, bool TA2> struct Template1 {};
+ template <class TB1, bool TB2> struct Template2 {};
+
+ template <class U1, bool U2, bool U3>
+ struct Template2<Template1<U1, U2>, U3> {};
+// DUMP: ClassTemplatePartialSpecializationDecl {{.+}} struct Template2
+// DUMP: |-TemplateArgument type 'Template1<type-parameter-0-0, value-parameter-0-1>'
+// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'Template1<type-parameter-0-0, value-parameter-0-1>' dependent
+// DUMP-NEXT: | |-name: 'TestPartialSpecNTTP::Template1'
+// DUMP-NEXT: | | `-ClassTemplateDecl {{.+}} Template1
+// DUMP-NEXT: | |-TemplateArgument type 'type-parameter-0-0'
+// DUMP-NEXT: | | `-TemplateTypeParmType {{.+}} 'type-parameter-0-0' dependent depth 0 index 0
+// DUMP-NEXT: | `-TemplateArgument expr canonical 'value-parameter-0-1'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'TA2' 'bool'
+// DUMP-NEXT: |-TemplateArgument expr canonical 'value-parameter-0-2'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U3' 'bool'
+// DUMP-NEXT: |-TemplateTypeParmDecl {{.+}} referenced class depth 0 index 0 U1
+// DUMP-NEXT: |-NonTypeTemplateParmDecl {{.+}} referenced 'bool' depth 0 index 1 U2
+// DUMP-NEXT: |-NonTypeTemplateParmDecl {{.+}} referenced 'bool' depth 0 index 2 U3
+// DUMP-NEXT: `-CXXRecordDecl {{.+}} implicit struct Template2
+
+ template <typename U1, bool U3, bool U2>
+ struct Template2<Template1<U1, U2>, U3> {};
+// DUMP: ClassTemplatePartialSpecializationDecl {{.+}} struct Template2 definition explicit_specialization
+// DUMP: |-TemplateArgument type 'Template1<type-parameter-0-0, value-parameter-0-2>'
+// DUMP-NEXT: | `-TemplateSpecializationType {{.+}} 'Template1<type-parameter-0-0, value-parameter-0-2>' dependent
+// DUMP-NEXT: | |-name: 'TestPartialSpecNTTP::Template1'
+// DUMP-NEXT: | | `-ClassTemplateDecl {{.+}} Template1
+// DUMP-NEXT: | |-TemplateArgument type 'type-parameter-0-0'
+// DUMP-NEXT: | | `-TemplateTypeParmType {{.+}} 'type-parameter-0-0' dependent depth 0 index 0
+// DUMP-NEXT: | `-TemplateArgument expr canonical 'value-parameter-0-2'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U2' 'bool'
+// DUMP-NEXT: |-TemplateArgument expr canonical 'value-parameter-0-1'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U3' 'bool'
+// DUMP-NEXT: |-TemplateTypeParmDecl {{.+}} referenced typename depth 0 index 0 U1
+// DUMP-NEXT: |-NonTypeTemplateParmDecl {{.+}} referenced 'bool' depth 0 index 1 U3
+// DUMP-NEXT: |-NonTypeTemplateParmDecl {{.+}} referenced 'bool' depth 0 index 2 U2
+// DUMP-NEXT: `-CXXRecordDecl {{.+}} implicit struct Template2
+} // namespace TestPartialSpecNTTP
+
// NOTE: CHECK lines have been autogenerated by gen_ast_dump_json_test.py
@@ -6917,6 +6959,986 @@ namespace TestDependentMemberPointer {
// JSON-NEXT: ]
// JSON-NEXT: }
// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NamespaceDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6409,
+// JSON-NEXT: "line": 181,
+// JSON-NEXT: "col": 11,
+// JSON-NEXT: "tokLen": 19
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6399,
+// JSON-NEXT: "col": 1,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 9184,
+// JSON-NEXT: "line": 221,
+// JSON-NEXT: "col": 1,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TestPartialSpecNTTP",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplateDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6532,
+// JSON-NEXT: "line": 183,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6494,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6543,
+// JSON-NEXT: "col": 52,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template1",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6510,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6504,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6510,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TA1",
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6520,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6515,
+// JSON-NEXT: "col": 24,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6520,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TA2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6532,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6525,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6543,
+// JSON-NEXT: "col": 52,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template1",
+// JSON-NEXT: "tagUsed": "struct",
+// JSON-NEXT: "completeDefinition": true,
+// JSON-NEXT: "definitionData": {
+// JSON-NEXT: "canConstDefaultInit": true,
+// JSON-NEXT: "copyAssign": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "copyCtor": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "defaultCtor": {
+// JSON-NEXT: "defaultedIsConstexpr": true,
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "isConstexpr": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "dtor": {
+// JSON-NEXT: "irrelevant": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "hasConstexprNonCopyMoveConstructor": true,
+// JSON-NEXT: "isAggregate": true,
+// JSON-NEXT: "isEmpty": true,
+// JSON-NEXT: "isLiteral": true,
+// JSON-NEXT: "isPOD": true,
+// JSON-NEXT: "isStandardLayout": true,
+// JSON-NEXT: "isTrivial": true,
+// JSON-NEXT: "isTriviallyCopyable": true,
+// JSON-NEXT: "moveAssign": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "moveCtor": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6532,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6525,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6532,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isImplicit": true,
+// JSON-NEXT: "name": "Template1",
+// JSON-NEXT: "tagUsed": "struct"
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplateDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6586,
+// JSON-NEXT: "line": 184,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6548,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6597,
+// JSON-NEXT: "col": 52,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6564,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6558,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6564,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TB1",
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6574,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6569,
+// JSON-NEXT: "col": 24,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6574,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "TB2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6586,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6579,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6597,
+// JSON-NEXT: "col": 52,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct",
+// JSON-NEXT: "completeDefinition": true,
+// JSON-NEXT: "definitionData": {
+// JSON-NEXT: "canConstDefaultInit": true,
+// JSON-NEXT: "copyAssign": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "copyCtor": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "defaultCtor": {
+// JSON-NEXT: "defaultedIsConstexpr": true,
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "isConstexpr": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "dtor": {
+// JSON-NEXT: "irrelevant": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "hasConstexprNonCopyMoveConstructor": true,
+// JSON-NEXT: "isAggregate": true,
+// JSON-NEXT: "isEmpty": true,
+// JSON-NEXT: "isLiteral": true,
+// JSON-NEXT: "isPOD": true,
+// JSON-NEXT: "isStandardLayout": true,
+// JSON-NEXT: "isTrivial": true,
+// JSON-NEXT: "isTriviallyCopyable": true,
+// JSON-NEXT: "moveAssign": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "moveCtor": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6586,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6579,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6586,
+// JSON-NEXT: "col": 41,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isImplicit": true,
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct"
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplatePartialSpecializationDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6650,
+// JSON-NEXT: "line": 187,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6603,
+// JSON-NEXT: "line": 186,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6684,
+// JSON-NEXT: "line": 187,
+// JSON-NEXT: "col": 44,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct",
+// JSON-NEXT: "completeDefinition": true,
+// JSON-NEXT: "definitionData": {
+// JSON-NEXT: "canConstDefaultInit": true,
+// JSON-NEXT: "copyAssign": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "copyCtor": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "defaultCtor": {
+// JSON-NEXT: "defaultedIsConstexpr": true,
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "isConstexpr": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "dtor": {
+// JSON-NEXT: "irrelevant": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "hasConstexprNonCopyMoveConstructor": true,
+// JSON-NEXT: "isAggregate": true,
+// JSON-NEXT: "isEmpty": true,
+// JSON-NEXT: "isLiteral": true,
+// JSON-NEXT: "isPOD": true,
+// JSON-NEXT: "isStandardLayout": true,
+// JSON-NEXT: "isTrivial": true,
+// JSON-NEXT: "isTriviallyCopyable": true,
+// JSON-NEXT: "moveAssign": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "moveCtor": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "Template1<type-parameter-0-0, value-parameter-0-1>"
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateSpecializationType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "Template1<type-parameter-0-0, value-parameter-0-1>"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "templateName": "TestPartialSpecNTTP::Template1",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0"
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0,
+// JSON-NEXT: "decl": {
+// JSON-NEXT: "id": "0x0"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "isExpr": true,
+// JSON-NEXT: "isCanonical": true,
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "DeclRefExpr",
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6520,
+// JSON-NEXT: "line": 183,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6520,
+// JSON-NEXT: "col": 29,
+// JSON-NEXT: "tokLen": 3
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "valueCategory": "prvalue",
+// JSON-NEXT: "referencedDecl": {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "name": "TA2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "isExpr": true,
+// JSON-NEXT: "isCanonical": true,
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "DeclRefExpr",
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6679,
+// JSON-NEXT: "line": 187,
+// JSON-NEXT: "col": 39,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6679,
+// JSON-NEXT: "col": 39,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "valueCategory": "prvalue",
+// JSON-NEXT: "referencedDecl": {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "name": "U3",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6619,
+// JSON-NEXT: "line": 186,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6613,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 5
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6619,
+// JSON-NEXT: "col": 19,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U1",
+// JSON-NEXT: "tagUsed": "class",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6628,
+// JSON-NEXT: "col": 28,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6623,
+// JSON-NEXT: "col": 23,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6628,
+// JSON-NEXT: "col": 28,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6637,
+// JSON-NEXT: "col": 37,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6632,
+// JSON-NEXT: "col": 32,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6637,
+// JSON-NEXT: "col": 37,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U3",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 2
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 6650,
+// JSON-NEXT: "line": 187,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 6643,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 6650,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isImplicit": true,
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct"
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "ClassTemplatePartialSpecializationDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 7925,
+// JSON-NEXT: "line": 205,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7875,
+// JSON-NEXT: "line": 204,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7959,
+// JSON-NEXT: "line": 205,
+// JSON-NEXT: "col": 44,
+// JSON-NEXT: "tokLen": 1
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct",
+// JSON-NEXT: "completeDefinition": true,
+// JSON-NEXT: "definitionData": {
+// JSON-NEXT: "canConstDefaultInit": true,
+// JSON-NEXT: "copyAssign": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "copyCtor": {
+// JSON-NEXT: "hasConstParam": true,
+// JSON-NEXT: "implicitHasConstParam": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "defaultCtor": {
+// JSON-NEXT: "defaultedIsConstexpr": true,
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "isConstexpr": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "dtor": {
+// JSON-NEXT: "irrelevant": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "hasConstexprNonCopyMoveConstructor": true,
+// JSON-NEXT: "isAggregate": true,
+// JSON-NEXT: "isEmpty": true,
+// JSON-NEXT: "isLiteral": true,
+// JSON-NEXT: "isPOD": true,
+// JSON-NEXT: "isStandardLayout": true,
+// JSON-NEXT: "isTrivial": true,
+// JSON-NEXT: "isTriviallyCopyable": true,
+// JSON-NEXT: "moveAssign": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: },
+// JSON-NEXT: "moveCtor": {
+// JSON-NEXT: "exists": true,
+// JSON-NEXT: "needsImplicit": true,
+// JSON-NEXT: "simple": true,
+// JSON-NEXT: "trivial": true
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "Template1<type-parameter-0-0, value-parameter-0-2>"
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateSpecializationType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "Template1<type-parameter-0-0, value-parameter-0-2>"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "templateName": "TestPartialSpecNTTP::Template1",
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0"
+// JSON-NEXT: },
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmType",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "type-parameter-0-0"
+// JSON-NEXT: },
+// JSON-NEXT: "isDependent": true,
+// JSON-NEXT: "isInstantiationDependent": true,
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0,
+// JSON-NEXT: "decl": {
+// JSON-NEXT: "id": "0x0"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "isExpr": true,
+// JSON-NEXT: "isCanonical": true,
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "DeclRefExpr",
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7949,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7949,
+// JSON-NEXT: "col": 34,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "valueCategory": "prvalue",
+// JSON-NEXT: "referencedDecl": {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "name": "U2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "kind": "TemplateArgument",
+// JSON-NEXT: "isExpr": true,
+// JSON-NEXT: "isCanonical": true,
+// JSON-NEXT: "inner": [
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "DeclRefExpr",
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7954,
+// JSON-NEXT: "col": 39,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7954,
+// JSON-NEXT: "col": 39,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "valueCategory": "prvalue",
+// JSON-NEXT: "referencedDecl": {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "name": "U3",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "TemplateTypeParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 7894,
+// JSON-NEXT: "line": 204,
+// JSON-NEXT: "col": 22,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7885,
+// JSON-NEXT: "col": 13,
+// JSON-NEXT: "tokLen": 8
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7894,
+// JSON-NEXT: "col": 22,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U1",
+// JSON-NEXT: "tagUsed": "typename",
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 0
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 7903,
+// JSON-NEXT: "col": 31,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7898,
+// JSON-NEXT: "col": 26,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7903,
+// JSON-NEXT: "col": 31,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U3",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 1
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "NonTypeTemplateParmDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 7912,
+// JSON-NEXT: "col": 40,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7907,
+// JSON-NEXT: "col": 35,
+// JSON-NEXT: "tokLen": 4
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7912,
+// JSON-NEXT: "col": 40,
+// JSON-NEXT: "tokLen": 2
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isReferenced": true,
+// JSON-NEXT: "name": "U2",
+// JSON-NEXT: "type": {
+// JSON-NEXT: "qualType": "bool"
+// JSON-NEXT: },
+// JSON-NEXT: "depth": 0,
+// JSON-NEXT: "index": 2
+// JSON-NEXT: },
+// JSON-NEXT: {
+// JSON-NEXT: "id": "0x{{.*}}",
+// JSON-NEXT: "kind": "CXXRecordDecl",
+// JSON-NEXT: "loc": {
+// JSON-NEXT: "offset": 7925,
+// JSON-NEXT: "line": 205,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: },
+// JSON-NEXT: "range": {
+// JSON-NEXT: "begin": {
+// JSON-NEXT: "offset": 7918,
+// JSON-NEXT: "col": 3,
+// JSON-NEXT: "tokLen": 6
+// JSON-NEXT: },
+// JSON-NEXT: "end": {
+// JSON-NEXT: "offset": 7925,
+// JSON-NEXT: "col": 10,
+// JSON-NEXT: "tokLen": 9
+// JSON-NEXT: }
+// JSON-NEXT: },
+// JSON-NEXT: "isImplicit": true,
+// JSON-NEXT: "name": "Template2",
+// JSON-NEXT: "tagUsed": "struct"
+// JSON-NEXT: }
+// JSON-NEXT: ]
+// JSON-NEXT: }
+// JSON-NEXT: ]
// JSON-NEXT: }
// JSON-NEXT: ]
// JSON-NEXT: }
diff --git a/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp
index 668941b401419..65d8345ecc3aa 100644
--- a/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.mem/p5.cpp
@@ -56,6 +56,10 @@ class Foo {
template float Foo::As();
template double Foo::As2();
+template<int B1> struct B {};
+template<class C1> struct C {};
+template<class D1, int D2> struct D {};
+
// Partial ordering with conversion function templates.
struct X0 {
template<typename T> operator T*() {
@@ -64,6 +68,11 @@ struct X0 {
}
template<typename T> operator T*() const; // expected-note{{explicit instantiation refers here}}
+ template<int V> operator B<V>() const; // expected-note{{explicit instantiation refers here}}
+ template<class T, int V> operator C<T[V]>() const; // expected-note{{explicit instantiation refers here}}
+#if __cplusplus >= 201103L
+ template<int V> operator D<decltype(V), V>() const; // expected-note{{explicit instantiation refers here}}
+#endif
template<typename T> operator const T*() const {
T x = T();
@@ -76,7 +85,15 @@ struct X0 {
template X0::operator const char*() const; // expected-note{{'X0::operator const char *<char>' requested here}}
template X0::operator const int*(); // expected-note{{'X0::operator const int *<const int>' requested here}}
+// FIXME: These diagnostics are printing canonical types.
template X0::operator float*() const; // expected-error{{explicit instantiation of undefined function template 'operator type-parameter-0-0 *'}}
+template X0::operator B<0>() const; // expected-error {{undefined function template 'operator B<value-parameter-0-0>'}}
+// FIXME: Within the above issue were we print canonical types here, printing the array
+// index expression as non-canonical is extra bad.
+template X0::operator C<int[1]>() const; // expected-error {{undefined function template 'operator C<type-parameter-0-0[V]>'}}
+#if __cplusplus >= 201103L
+template X0::operator D<int, 0>() const; // expected-error {{undefined function template 'operator D<decltype(value-parameter-0-0), value-parameter-0-0>'}}
+#endif
void test_X0(X0 x0, const X0 &x0c) {
x0.operator const int*(); // expected-note{{in instantiation of function template specialization}}
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index dd6df43864481..2b37add007086 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -76,7 +76,7 @@ TEST(TypePrinter, TemplateId2) {
ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "<int>",
[](PrintingPolicy &Policy) {
Policy.FullyQualifiedName = true;
- Policy.PrintCanonicalTypes = true;
+ Policy.PrintAsCanonical = true;
}));
}
More information about the cfe-commits
mailing list