https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/168533
>From 744585fc5c9cc79f24683db6ed69a2e96c7e8413 Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Mon, 16 Feb 2026 16:23:08 +0000 Subject: [PATCH 1/2] [clang][TypePrinter] Helper to print tag locations --- clang/include/clang/AST/Decl.h | 3 +++ clang/lib/AST/Decl.cpp | 48 ++++++++++++++++++---------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 5c46c912186c4..c3cd74a5b34db 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -3774,6 +3774,9 @@ class TagDecl : public TypeDecl, void printAnonymousTagDecl(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const; + void printAnonymousTagDeclLocation(llvm::raw_ostream &OS, + const PrintingPolicy &Policy) const; + public: friend class ASTDeclReader; friend class ASTDeclWriter; diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 4148e0ce16b7d..37b00eeca539c 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -4961,6 +4961,30 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { } } +void TagDecl::printAnonymousTagDeclLocation( + llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { + PresumedLoc PLoc = + getASTContext().getSourceManager().getPresumedLoc(getLocation()); + if (!PLoc.isValid()) + return; + + OS << " at "; + StringRef File = PLoc.getFilename(); + llvm::SmallString<1024> WrittenFile(File); + if (auto *Callbacks = Policy.Callbacks) + WrittenFile = Callbacks->remapPath(File); + // Fix inconsistent path separator created by + // clang::DirectoryLookup::LookupFile when the file path is relative + // path. + llvm::sys::path::Style Style = + llvm::sys::path::is_absolute(WrittenFile) + ? llvm::sys::path::Style::native + : (Policy.MSVCFormatting ? llvm::sys::path::Style::windows_backslash + : llvm::sys::path::Style::posix); + llvm::sys::path::native(WrittenFile, Style); + OS << WrittenFile << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); +} + void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS, const PrintingPolicy &Policy) const { if (TypedefNameDecl *Typedef = getTypedefNameForAnonDecl()) { @@ -4996,28 +5020,8 @@ void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS, OS << ' ' << getKindName(); if (Policy.AnonymousTagNameStyle == - llvm::to_underlying(PrintingPolicy::AnonymousTagMode::SourceLocation)) { - PresumedLoc PLoc = - getASTContext().getSourceManager().getPresumedLoc(getLocation()); - if (PLoc.isValid()) { - OS << " at "; - StringRef File = PLoc.getFilename(); - llvm::SmallString<1024> WrittenFile(File); - if (auto *Callbacks = Policy.Callbacks) - WrittenFile = Callbacks->remapPath(File); - // Fix inconsistent path separator created by - // clang::DirectoryLookup::LookupFile when the file path is relative - // path. - llvm::sys::path::Style Style = - llvm::sys::path::is_absolute(WrittenFile) - ? llvm::sys::path::Style::native - : (Policy.MSVCFormatting - ? llvm::sys::path::Style::windows_backslash - : llvm::sys::path::Style::posix); - llvm::sys::path::native(WrittenFile, Style); - OS << WrittenFile << ':' << PLoc.getLine() << ':' << PLoc.getColumn(); - } - } + llvm::to_underlying(PrintingPolicy::AnonymousTagMode::SourceLocation)) + printAnonymousTagDeclLocation(OS, Policy); OS << (Policy.MSVCFormatting ? '\'' : ')'); } >From 4efbed704d9176e790e1f4eaf2f74691d85915ed Mon Sep 17 00:00:00 2001 From: Michael Buch <[email protected]> Date: Fri, 14 Nov 2025 16:28:19 +0000 Subject: [PATCH 2/2] [clang][TypePrinter] Add AnonymousTagMode::CanonicalName --- clang/include/clang/AST/Decl.h | 5 +++-- clang/include/clang/AST/PrettyPrinter.h | 6 ++++-- clang/lib/AST/Decl.cpp | 12 +++++++++--- clang/lib/AST/TypePrinter.cpp | 12 +++++++++--- clang/lib/CodeGen/CGDebugInfo.cpp | 4 ++++ clang/test/DebugInfo/CXX/prefix-map-lambda.cpp | 10 ---------- clang/test/DebugInfo/CXX/simple-template-names.cpp | 12 ++++++------ .../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 ---------- 11 files changed, 35 insertions(+), 55 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/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index c3cd74a5b34db..4b869d9d2404a 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 a937d020b7277..d849bc7845a98 100644 --- a/clang/include/clang/AST/PrettyPrinter.h +++ b/clang/include/clang/AST/PrettyPrinter.h @@ -65,7 +65,9 @@ struct PrintingPolicy { /// When printing an anonymous tag name, also print the location of that /// entity (e.g., "enum <anonymous at t.h:10:5>"). - SourceLocation + SourceLocation, + + CanonicalName, }; /// Create a default printing policy for the specified language. @@ -208,7 +210,7 @@ struct PrintingPolicy { unsigned ConstantArraySizeAsWritten : 1; LLVM_PREFERRED_TYPE(AnonymousTagMode) - unsigned AnonymousTagNameStyle : 1; + unsigned AnonymousTagNameStyle : 2; /// When true, suppress printing of the __strong lifetime qualifier in ARC. LLVM_PREFERRED_TYPE(bool) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 37b00eeca539c..f89d619514599 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>; @@ -5016,6 +5018,10 @@ void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS, OS << "unnamed"; } + if (Policy.AnonymousTagNameStyle == + llvm::to_underlying(PrintingPolicy::AnonymousTagMode::CanonicalName)) + OS << getASTContext().getManglingNumber(this); + if (!SuppressTagKeywordInName) OS << ' ' << getKindName(); diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp index d8a48af62bb75..bcc17a158639b 100644 --- a/clang/lib/AST/TypePrinter.cpp +++ b/clang/lib/AST/TypePrinter.cpp @@ -1534,20 +1534,26 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) { } } + const IdentifierInfo *II = D->getIdentifier(); + const bool PrintingCanonicalAnonName = + !II && + Policy.AnonymousTagNameStyle == + llvm::to_underlying(PrintingPolicy::AnonymousTagMode::CanonicalName); + 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=*/PrintingCanonicalAnonName); } - if (const IdentifierInfo *II = D->getIdentifier()) + if (II) OS << II->getName(); else { clang::PrintingPolicy Copy(Policy); - // Suppress the redundant tag keyword if we just printed one. if (PrintedKindDecoration) { Copy.SuppressTagKeywordInAnonNames = true; diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 2b123631c526c..c3e4181e3b74a 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -27,6 +27,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/LambdaCapture.h" +#include "clang/AST/PrettyPrinter.h" #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/VTableBuilder.h" @@ -39,6 +40,7 @@ #include "clang/Lex/ModuleMap.h" #include "clang/Lex/PreprocessorOptions.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/STLForwardCompat.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/IR/Constants.h" @@ -430,6 +432,8 @@ PrintingPolicy CGDebugInfo::getPrintingPolicy() const { PP.UsePreferredNames = false; PP.AlwaysIncludeTypeForTemplateArgument = true; PP.UseEnumerators = false; + PP.AnonymousTagNameStyle = + llvm::to_underlying(PrintingPolicy::AnonymousTagMode::CanonicalName); // 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 a682a087e1406..446d3ced99a26 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<(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)>(); - // 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 @@ -145,5 +145,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>" } 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 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
