From 4f075f52c7c0ca1c4248e5565e4f960eb61f098c Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Mon, 24 Nov 2025 16:58:02 +0000 Subject: [PATCH 1/3] [Clang][TypePrinter] Make printNestedNameSpecifier look at typedefs This is to resolve a regression caused by #168534. Now when we have an anonymous object like a struct or union that has a typedef attached, we print the typedef name instead of listing it as anonymous. --- clang/lib/AST/Decl.cpp | 4 +++- clang/unittests/AST/TypePrinterTest.cpp | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 555aa5c050ffd..13919a56af0e8 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1790,7 +1790,9 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, else OS << *ND; } else if (const auto *RD = dyn_cast(DC)) { - if (!RD->getIdentifier()) + if (TypedefNameDecl *Typedef = RD->getTypedefNameForAnonDecl()) + OS << Typedef->getIdentifier()->getName(); + else if (!RD->getIdentifier()) OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp index 410ec021d6e72..7bf2bef5ac641 100644 --- a/clang/unittests/AST/TypePrinterTest.cpp +++ b/clang/unittests/AST/TypePrinterTest.cpp @@ -341,3 +341,23 @@ TEST(TypePrinter, NestedNameSpecifiers) { Policy.AnonymousTagLocations = false; })); } + +TEST(TypePrinter, NestedNameSpecifiersTypedef) { + constexpr char Code[] = R"cpp( + typedef union { + struct { + struct { + unsigned int baz; + } bar; + }; + } foo; + )cpp"; + + ASSERT_TRUE(PrintedTypeMatches( + Code, {}, fieldDecl(hasName("bar"), hasType(qualType().bind("id"))), + "struct foo::(anonymous struct)::(unnamed)", + [](PrintingPolicy &Policy) { + Policy.FullyQualifiedName = true; + Policy.AnonymousTagLocations = false; + })); +} From 5df8461b34ccf614915e057c7ee17b0674403c46 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Mon, 24 Nov 2025 17:15:38 +0000 Subject: [PATCH 2/3] formatting --- clang/unittests/AST/TypePrinterTest.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp index 7bf2bef5ac641..3cadf9b265bd1 100644 --- a/clang/unittests/AST/TypePrinterTest.cpp +++ b/clang/unittests/AST/TypePrinterTest.cpp @@ -355,8 +355,7 @@ TEST(TypePrinter, NestedNameSpecifiersTypedef) { ASSERT_TRUE(PrintedTypeMatches( Code, {}, fieldDecl(hasName("bar"), hasType(qualType().bind("id"))), - "struct foo::(anonymous struct)::(unnamed)", - [](PrintingPolicy &Policy) { + "struct foo::(anonymous struct)::(unnamed)", [](PrintingPolicy &Policy) { Policy.FullyQualifiedName = true; Policy.AnonymousTagLocations = false; })); From 5ef3e7be54cd7dae1c6a53e434a5c054d2eac1c9 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Mon, 24 Nov 2025 17:35:35 +0000 Subject: [PATCH 3/3] feedback --- clang/lib/AST/Decl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 13919a56af0e8..591457b1d66b4 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -1790,8 +1790,8 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS, else OS << *ND; } else if (const auto *RD = dyn_cast(DC)) { - if (TypedefNameDecl *Typedef = RD->getTypedefNameForAnonDecl()) - OS << Typedef->getIdentifier()->getName(); + if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl()) + OS << *TD; else if (!RD->getIdentifier()) OS << "(anonymous " << RD->getKindName() << ')'; else