[clang] [WIP] [clang][DebugInfo] Use mangling number and scope to create unambiguous names for anonymous structures (PR #168533)
Michael Buch via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 21 02:33:02 PST 2025
https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/168533
>From b831720a3e0a8b6d100a0e04f330228f2a0caf3e Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 14 Nov 2025 16:28:19 +0000
Subject: [PATCH 1/3] [clang][TypePrinter] Add CanonicalAnonymousLambdaName
---
clang/include/clang/AST/Decl.h | 5 +++--
clang/include/clang/AST/PrettyPrinter.h | 8 +++++++-
clang/lib/AST/Decl.cpp | 8 +++++---
clang/lib/AST/TypePrinter.cpp | 23 +++++++++++++++++------
4 files changed, 32 insertions(+), 12 deletions(-)
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index ee2321dd158d4..9254101d37939 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -357,9 +357,10 @@ class NamedDecl : public Decl {
/// including the '::' at the end. E.g.
/// when `printQualifiedName(D)` prints "A::B::i",
/// this function prints "A::B::".
- void printNestedNameSpecifier(raw_ostream &OS) const;
void printNestedNameSpecifier(raw_ostream &OS,
- const PrintingPolicy &Policy) const;
+ bool AllowFunctionContext = false) const;
+ void printNestedNameSpecifier(raw_ostream &OS, const PrintingPolicy &Policy,
+ bool AllowFunctionContext = false) const;
// FIXME: Remove string version.
std::string getQualifiedNameAsString() const;
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index fd995a653d167..9bb6a7f203cf5 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -79,7 +79,8 @@ struct PrintingPolicy {
PrintAsCanonical(false), PrintInjectedClassNameWithArguments(true),
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
- UseEnumerators(true), UseHLSLTypes(LO.HLSL) {}
+ UseEnumerators(true), UseHLSLTypes(LO.HLSL),
+ CanonicalAnonymousLambdaName(false) {}
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -346,6 +347,11 @@ struct PrintingPolicy {
LLVM_PREFERRED_TYPE(bool)
unsigned UseHLSLTypes : 1;
+ // TODO: this shouldn't be specific to unnamed lambdas, but also unnamed
+ // structures/unions/enums (?)
+ LLVM_PREFERRED_TYPE(bool)
+ unsigned CanonicalAnonymousLambdaName : 1;
+
/// Callbacks to use to allow the behavior of printing to be customized.
const PrintingCallbacks *Callbacks = nullptr;
};
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 555aa5c050ffd..ee1ff41b937c8 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1711,12 +1711,14 @@ void NamedDecl::printQualifiedName(raw_ostream &OS,
}
}
-void NamedDecl::printNestedNameSpecifier(raw_ostream &OS) const {
+void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
+ bool AllowFunctionContext) const {
printNestedNameSpecifier(OS, getASTContext().getPrintingPolicy());
}
void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
- const PrintingPolicy &P) const {
+ const PrintingPolicy &P,
+ bool AllowFunctionContext) const {
const DeclContext *Ctx = getDeclContext();
// For ObjC methods and properties, look through categories and use the
@@ -1733,7 +1735,7 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
Ctx = CI;
}
- if (Ctx->isFunctionOrMethod())
+ if (Ctx->isFunctionOrMethod() && !AllowFunctionContext)
return;
using ContextsTy = SmallVector<const DeclContext *, 8>;
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index d2881d5ac518a..ed50fe71e0537 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1532,16 +1532,23 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
OS << ' ';
}
+ const IdentifierInfo *II = D->getIdentifier();
+ const bool IsLambda =
+ isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda();
+ const bool PrintingCanonicalLambdaName =
+ !II && IsLambda && Policy.CanonicalAnonymousLambdaName;
+
if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
T->getQualifier().print(OS, Policy);
} else if (!Policy.SuppressScope) {
// Compute the full nested-name-specifier for this type.
// In C, this will always be empty except when the type
// being printed is anonymous within other Record.
- D->printNestedNameSpecifier(OS, Policy);
+ D->printNestedNameSpecifier(
+ OS, Policy, /*AllowFunctionContext=*/PrintingCanonicalLambdaName);
}
- if (const IdentifierInfo *II = D->getIdentifier())
+ if (II)
OS << II->getName();
else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
assert(Typedef->getIdentifier() && "Typedef without identifier?");
@@ -1549,12 +1556,15 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
} else {
// Make an unambiguous representation for anonymous types, e.g.
// (anonymous enum at /usr/include/string.h:120:9)
- OS << (Policy.MSVCFormatting ? '`' : '(');
+ const bool AddParen = !PrintingCanonicalLambdaName || Policy.AnonymousTagLocations;
+ if (AddParen)
+ OS << (Policy.MSVCFormatting ? '`' : '(');
- if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
+ if (IsLambda) {
OS << "lambda";
HasKindDecoration = true;
- } else if ((isa<RecordDecl>(D) && cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
+ } else if ((isa<RecordDecl>(D) &&
+ cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
OS << "anonymous";
} else {
OS << "unnamed";
@@ -1589,7 +1599,8 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
}
}
- OS << (Policy.MSVCFormatting ? '\'' : ')');
+ if (AddParen)
+ OS << (Policy.MSVCFormatting ? '\'' : ')');
}
// If this is a class template specialization, print the template
>From 8dc734a54d8cf770d2206ab4e99f05440de203b0 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 14 Nov 2025 16:28:39 +0000
Subject: [PATCH 2/3] [clang][DebugInfo] Canonical lambda names in debug-info
---
clang/lib/AST/TypePrinter.cpp | 7 +++++--
clang/lib/CodeGen/CGDebugInfo.cpp | 1 +
clang/test/DebugInfo/CXX/prefix-map-lambda.cpp | 10 ----------
clang/test/DebugInfo/CXX/simple-template-names.cpp | 4 ++--
.../DebugInfo/Generic/Inputs/debug-info-slash.cpp | 2 --
.../test/DebugInfo/Generic/Inputs/debug-info-slash.h | 6 ------
clang/test/DebugInfo/Generic/debug-prefix-map.cpp | 11 -----------
clang/test/DebugInfo/Generic/slash.test | 10 ----------
8 files changed, 8 insertions(+), 43 deletions(-)
delete mode 100644 clang/test/DebugInfo/CXX/prefix-map-lambda.cpp
delete mode 100644 clang/test/DebugInfo/Generic/Inputs/debug-info-slash.cpp
delete mode 100644 clang/test/DebugInfo/Generic/Inputs/debug-info-slash.h
delete mode 100644 clang/test/DebugInfo/Generic/debug-prefix-map.cpp
delete mode 100644 clang/test/DebugInfo/Generic/slash.test
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ed50fe71e0537..ec65a7d6f438d 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1556,12 +1556,15 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
} else {
// Make an unambiguous representation for anonymous types, e.g.
// (anonymous enum at /usr/include/string.h:120:9)
- const bool AddParen = !PrintingCanonicalLambdaName || Policy.AnonymousTagLocations;
+ const bool AddParen = !PrintingCanonicalLambdaName;
if (AddParen)
OS << (Policy.MSVCFormatting ? '`' : '(');
if (IsLambda) {
OS << "lambda";
+ if (PrintingCanonicalLambdaName)
+ OS << D->getASTContext().getManglingNumber(D);
+
HasKindDecoration = true;
} else if ((isa<RecordDecl>(D) &&
cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
@@ -1570,7 +1573,7 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
OS << "unnamed";
}
- if (Policy.AnonymousTagLocations) {
+ if (Policy.AnonymousTagLocations && !PrintingCanonicalLambdaName) {
// Suppress the redundant tag keyword if we just printed one.
// We don't have to worry about ElaboratedTypes here because you can't
// refer to an anonymous type with one.
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 1489b5116e6ce..15d8d26d3a87a 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -422,6 +422,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
PP.UseEnumerators = false;
+ PP.CanonicalAnonymousLambdaName = true;
// Apply -fdebug-prefix-map.
PP.Callbacks = &PrintCB;
diff --git a/clang/test/DebugInfo/CXX/prefix-map-lambda.cpp b/clang/test/DebugInfo/CXX/prefix-map-lambda.cpp
deleted file mode 100644
index f0fb1a312c8be..0000000000000
--- a/clang/test/DebugInfo/CXX/prefix-map-lambda.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
-// RUN: -fdebug-prefix-map=%S=/SOURCE_ROOT %s -emit-llvm -o - | FileCheck %s
-
-template <typename T> void b(T) {}
-void c() {
- // CHECK: !DISubprogram(name: "b<(lambda at
- // CHECK-SAME: SOURCE_ROOT
- // CHECK-SAME: [[@LINE+1]]:{{[0-9]+}})>"
- b([]{});
-}
diff --git a/clang/test/DebugInfo/CXX/simple-template-names.cpp b/clang/test/DebugInfo/CXX/simple-template-names.cpp
index 3c8ff2780b66a..c6d21fc656709 100644
--- a/clang/test/DebugInfo/CXX/simple-template-names.cpp
+++ b/clang/test/DebugInfo/CXX/simple-template-names.cpp
@@ -70,9 +70,9 @@ void f() {
// anything other than another unnamed class/struct.
auto Lambda = [] {};
f1<decltype(Lambda)>();
- // CHECK: !DISubprogram(name: "f1<(lambda at {{.*}}simple-template-names.cpp:[[# @LINE - 2]]:17)>",
+ // CHECK: !DISubprogram(name: "f1<f()::lambda1>",
f1<t1<t1<decltype(Lambda)>>>();
- // CHECK: !DISubprogram(name: "f1<t1<t1<(lambda at {{.*}}> > >",
+ // CHECK: !DISubprogram(name: "f1<t1<t1<f()::lambda1> > >",
struct {
} unnamed_struct;
f1<decltype(unnamed_struct)>();
diff --git a/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.cpp b/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.cpp
deleted file mode 100644
index 563077ed342a1..0000000000000
--- a/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-#include "Inputs/debug-info-slash.h"
-int main() { a(); return 0; }
diff --git a/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.h b/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.h
deleted file mode 100644
index 9092f4a5e8170..0000000000000
--- a/clang/test/DebugInfo/Generic/Inputs/debug-info-slash.h
+++ /dev/null
@@ -1,6 +0,0 @@
-template <typename... T>
-void f1() {}
-void a() {
- auto Lambda = [] {};
- f1<decltype(Lambda)>();
-}
diff --git a/clang/test/DebugInfo/Generic/debug-prefix-map.cpp b/clang/test/DebugInfo/Generic/debug-prefix-map.cpp
deleted file mode 100644
index 174bef5a07699..0000000000000
--- a/clang/test/DebugInfo/Generic/debug-prefix-map.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-// RUN: %clang_cc1 -debug-info-kind=standalone -fdebug-prefix-map=%p=./UNLIKELY_PATH/empty %s -emit-llvm -o - | FileCheck %s
-
-struct alignas(64) an {
- struct {
- unsigned char x{0};
- } arr[64];
-};
-
-struct an *pan = new an;
-
-// CHECK: !DISubprogram(name: "(unnamed struct at ./UNLIKELY_PATH/empty{{/|\\\\}}{{.*}}",
diff --git a/clang/test/DebugInfo/Generic/slash.test b/clang/test/DebugInfo/Generic/slash.test
deleted file mode 100644
index 0e42912c18d21..0000000000000
--- a/clang/test/DebugInfo/Generic/slash.test
+++ /dev/null
@@ -1,10 +0,0 @@
-RUN: rm -rf %t-dir
-RUN: mkdir -p %t-dir/header/Inputs
-RUN: cp %S/Inputs/debug-info-slash.cpp %t-dir/
-RUN: cp %S/Inputs/debug-info-slash.h %t-dir/header/Inputs
-RUN: cd %t-dir
-RUN: %clang -target x86_64-pc-win32 -emit-llvm -S -g %t-dir/debug-info-slash.cpp -Iheader -o - | FileCheck --check-prefix=WIN %s
-RUN: %clang -target x86_64-linux-gnu -emit-llvm -S -g %t-dir/debug-info-slash.cpp -Iheader -o - | FileCheck --check-prefix=LINUX %s
-
-WIN: lambda at header\\Inputs\\debug-info-slash.h
-LINUX: lambda at header/Inputs/debug-info-slash.h
>From 6fd0246d91333e484e814dd9492bd796892f2b76 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 14 Nov 2025 17:28:48 +0000
Subject: [PATCH 3/3] [clang][DebugInfo] Treat unnamed records the same as
lambdas
---
clang/include/clang/AST/PrettyPrinter.h | 6 ++--
clang/lib/AST/TypePrinter.cpp | 35 ++++++++-----------
clang/lib/CodeGen/CGDebugInfo.cpp | 2 +-
.../DebugInfo/CXX/simple-template-names.cpp | 12 +++----
4 files changed, 24 insertions(+), 31 deletions(-)
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 9bb6a7f203cf5..4c5a34b90fc72 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -80,7 +80,7 @@ struct PrintingPolicy {
UsePreferredNames(true), AlwaysIncludeTypeForTemplateArgument(false),
CleanUglifiedParameters(false), EntireContentsOfLargeArray(true),
UseEnumerators(true), UseHLSLTypes(LO.HLSL),
- CanonicalAnonymousLambdaName(false) {}
+ CanonicalAnonymousEntities(false) {}
/// Adjust this printing policy for cases where it's known that we're
/// printing C++ code (for instance, if AST dumping reaches a C++-only
@@ -347,10 +347,8 @@ struct PrintingPolicy {
LLVM_PREFERRED_TYPE(bool)
unsigned UseHLSLTypes : 1;
- // TODO: this shouldn't be specific to unnamed lambdas, but also unnamed
- // structures/unions/enums (?)
LLVM_PREFERRED_TYPE(bool)
- unsigned CanonicalAnonymousLambdaName : 1;
+ unsigned CanonicalAnonymousEntities : 1;
/// Callbacks to use to allow the behavior of printing to be customized.
const PrintingCallbacks *Callbacks = nullptr;
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index ec65a7d6f438d..eeb565b921fad 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1533,10 +1533,8 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
}
const IdentifierInfo *II = D->getIdentifier();
- const bool IsLambda =
- isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda();
- const bool PrintingCanonicalLambdaName =
- !II && IsLambda && Policy.CanonicalAnonymousLambdaName;
+ const bool PrintingCanonicalAnonName =
+ !II && Policy.CanonicalAnonymousEntities;
if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
T->getQualifier().print(OS, Policy);
@@ -1545,7 +1543,7 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
// In C, this will always be empty except when the type
// being printed is anonymous within other Record.
D->printNestedNameSpecifier(
- OS, Policy, /*AllowFunctionContext=*/PrintingCanonicalLambdaName);
+ OS, Policy, /*AllowFunctionContext=*/PrintingCanonicalAnonName);
}
if (II)
@@ -1556,15 +1554,10 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
} else {
// Make an unambiguous representation for anonymous types, e.g.
// (anonymous enum at /usr/include/string.h:120:9)
- const bool AddParen = !PrintingCanonicalLambdaName;
- if (AddParen)
- OS << (Policy.MSVCFormatting ? '`' : '(');
+ OS << (Policy.MSVCFormatting ? '`' : '(');
- if (IsLambda) {
+ if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
OS << "lambda";
- if (PrintingCanonicalLambdaName)
- OS << D->getASTContext().getManglingNumber(D);
-
HasKindDecoration = true;
} else if ((isa<RecordDecl>(D) &&
cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
@@ -1573,13 +1566,16 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
OS << "unnamed";
}
- if (Policy.AnonymousTagLocations && !PrintingCanonicalLambdaName) {
- // Suppress the redundant tag keyword if we just printed one.
- // We don't have to worry about ElaboratedTypes here because you can't
- // refer to an anonymous type with one.
- if (!HasKindDecoration)
- OS << " " << D->getKindName();
+ if (PrintingCanonicalAnonName)
+ OS << D->getASTContext().getManglingNumber(D);
+
+ // Suppress the redundant tag keyword if we just printed one.
+ // We don't have to worry about ElaboratedTypes here because you can't
+ // refer to an anonymous type with one.
+ if (!HasKindDecoration)
+ OS << " " << D->getKindName();
+ if (Policy.AnonymousTagLocations && !PrintingCanonicalAnonName) {
PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
D->getLocation());
if (PLoc.isValid()) {
@@ -1602,8 +1598,7 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
}
}
- if (AddParen)
- OS << (Policy.MSVCFormatting ? '\'' : ')');
+ OS << (Policy.MSVCFormatting ? '\'' : ')');
}
// If this is a class template specialization, print the template
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 15d8d26d3a87a..2851f1c7a5049 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -422,7 +422,7 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const {
PP.UsePreferredNames = false;
PP.AlwaysIncludeTypeForTemplateArgument = true;
PP.UseEnumerators = false;
- PP.CanonicalAnonymousLambdaName = true;
+ PP.CanonicalAnonymousEntities = true;
// Apply -fdebug-prefix-map.
PP.Callbacks = &PrintCB;
diff --git a/clang/test/DebugInfo/CXX/simple-template-names.cpp b/clang/test/DebugInfo/CXX/simple-template-names.cpp
index c6d21fc656709..9021bed07be6e 100644
--- a/clang/test/DebugInfo/CXX/simple-template-names.cpp
+++ b/clang/test/DebugInfo/CXX/simple-template-names.cpp
@@ -70,18 +70,18 @@ void f() {
// anything other than another unnamed class/struct.
auto Lambda = [] {};
f1<decltype(Lambda)>();
- // CHECK: !DISubprogram(name: "f1<f()::lambda1>",
+ // CHECK: !DISubprogram(name: "f1<f()::(lambda1)>",
f1<t1<t1<decltype(Lambda)>>>();
- // CHECK: !DISubprogram(name: "f1<t1<t1<f()::lambda1> > >",
+ // CHECK: !DISubprogram(name: "f1<t1<t1<f()::(lambda1)> > >",
struct {
} unnamed_struct;
f1<decltype(unnamed_struct)>();
- // CHECK: !DISubprogram(name: "f1<(unnamed struct at {{.*}}simple-template-names.cpp:[[# @LINE - 3]]:3)>",
+ // CHECK: !DISubprogram(name: "f1<f()::(unnamed1 struct)>",
f1<void (decltype(unnamed_struct))>();
- // CHECK: !DISubprogram(name: "f1<void ((unnamed struct at {{.*}}simple-template-names.cpp:[[# @LINE - 5]]:3))>",
+ // CHECK: !DISubprogram(name: "f1<void (f()::(unnamed1 struct))>",
enum {} unnamed_enum;
f1<decltype(unnamed_enum)>();
- // CHECK: !DISubprogram(name: "f1<(unnamed enum at {{.*}}simple-template-names.cpp:[[# @LINE - 2]]:3)>",
+ // CHECK: !DISubprogram(name: "f1<f()::(unnamed1 enum)>",
// Declarations can't readily be reversed as the value in the DWARF only
// contains the address of the value - we'd have to do symbol lookup to find
@@ -144,5 +144,5 @@ void f() {
// CHECK: !DISubprogram(name: "f1<int () __attribute__((noreturn))>",
f4<UnnamedEnum1>();
- // CHECK: !DISubprogram(name: "f4<((unnamed enum at {{.*}}))0>"
+ // CHECK: !DISubprogram(name: "f4<((unnamed1 enum))0>"
}
More information about the cfe-commits
mailing list