[llvm-branch-commits] [clang] [clang] implement printing of canonical template arguments of expression kind (PR #135133)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Apr 9 23:10:38 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-debuginfo
Author: Matheus Izvekov (mizvekov)
<details>
<summary>Changes</summary>
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 https://github.com/llvm/llvm-project/issues/92292
---
Patch is 48.39 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/135133.diff
12 Files Affected:
- (modified) clang/include/clang/AST/PrettyPrinter.h (+3-3)
- (modified) clang/lib/AST/DeclPrinter.cpp (+2-2)
- (modified) clang/lib/AST/JSONNodeDumper.cpp (+2)
- (modified) clang/lib/AST/StmtPrinter.cpp (+5-1)
- (modified) clang/lib/AST/TemplateBase.cpp (+5-2)
- (modified) clang/lib/AST/TemplateName.cpp (+8-2)
- (modified) clang/lib/AST/TextNodeDumper.cpp (+2)
- (modified) clang/lib/AST/TypePrinter.cpp (+4-5)
- (modified) clang/lib/CodeGen/CGDebugInfo.cpp (+1-1)
- (modified) clang/lib/Sema/SemaTemplate.cpp (+1-1)
- (modified) clang/test/AST/ast-dump-templates.cpp (+1022)
- (modified) clang/unittests/AST/TypePrinterTest.cpp (+1-1)
``````````diff
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..725db93b558f6 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("isCanon", 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..8f57fdd4c8f84 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 << " canon";
dumpTemplateArgument(TA);
}
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4ec252e3f89b5..3d37787d7209b 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();
}
@@ -1548,7 +1548,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 +2422,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..2a384c1802a1f 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 canon 'value-parameter-0-1'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'TA2' 'bool'
+// DUMP-NEXT: |-TemplateArgument expr canon '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 canon 'value-parameter-0-2'
+// DUMP-NEXT: | `-DeclRefExpr {{.+}} 'bool' NonTypeTemplateParm {{.+}} 'U2' 'bool'
+// DUMP-NEXT: |-TemplateArgument expr canon '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": 9168,
+// 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-NE...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/135133
More information about the llvm-branch-commits
mailing list