[Lldb-commits] [clang] [clang-tools-extra] [lldb] [clang][TypePrinter] Unify printing of anonymous/unnamed tag types (PR #169445)

Michael Buch via lldb-commits lldb-commits at lists.llvm.org
Tue Dec 9 07:17:06 PST 2025


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/169445

>From 7101f8a69f89b048dd1bc2e21aef7b09efe879c2 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Nov 2025 09:46:57 +0900
Subject: [PATCH 01/16] [clang][TypePrinter] Make printing of anonymous/unnamed
 tag types consistent

In https://github.com/llvm/llvm-project/pull/168534 we made the `TypePrinter` re-use `printNestedNameSpecifier` for printing scopes. However, the way that the names of anonymous/unnamed get printed by the two are slightly inconsistent with each other.

`printNestedNameSpecifier` calls all `TagType`s without an identifer `(anonymous)`. On the other hand, `TypePrinter` prints them slightly more accurate (it differentiates anonymous vs. unnamed decls) and allows for some additional customization points. E.g., with `MSVCFormatting`, it will print `\`'` instead of `()`. `printNestedNameSpecifier` already accounts for `MSVCFormatting` for namespaces, but doesn't for `TagType`s. This inconsistency means that if an unnamed tag is printed as part of a scope it's displayed as `(anonymous struct)`, but if it's the entity being whose scope is being printed, then it shows as `(unnamed struct)`.

This patch moves the printing of anonymous/unnamed tags into a common helper and re-uses it from `TypePrinter` and `printNestedNameSpecifier`.  We also do this from the AST matchers because they were aligned with how `printNestedNameSpecifier` represents the name.

I wasn't sure where to put the helper, so I just put it in `TypeBase.h` for now. Though I suspect there's a better home for it, possibly `DeclBase.h`?
---
 clang/include/clang/AST/TypeBase.h            |   4 +
 clang/lib/AST/Decl.cpp                        |   5 +-
 clang/lib/AST/TypePrinter.cpp                 | 106 ++++++++++--------
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp |  10 +-
 clang/unittests/AST/NamedDeclPrinterTest.cpp  |  28 +++++
 clang/unittests/AST/TypePrinterTest.cpp       |   2 +-
 .../ASTMatchers/ASTMatchersNarrowingTest.cpp  |  33 +++++-
 7 files changed, 133 insertions(+), 55 deletions(-)

diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index 30b9efe5a31b7..1c36067ff35b2 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -7374,6 +7374,10 @@ bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
                                   ArrayRef<TemplateArgument> Args,
                                   unsigned Depth);
 
+void printAnonymousTagDecl(llvm::raw_ostream &OS, const TagDecl *D,
+                           const PrintingPolicy &Policy,
+                           bool PrintKindDecoration, bool PrintTagLocations);
+
 /// Represents a qualified type name for which the type name is
 /// dependent.
 ///
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 4444b10db8cc0..101b25dcc6494 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -35,6 +35,7 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeBase.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
@@ -1795,7 +1796,9 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
       if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl())
         OS << *TD;
       else if (!RD->getIdentifier())
-        OS << "(anonymous " << RD->getKindName() << ')';
+        printAnonymousTagDecl(OS, llvm::cast<TagDecl>(RD), P,
+                              /*PrintKindDecoration=*/true,
+                              /*AllowSourceLocations=*/false);
       else
         OS << *RD;
     } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index d2881d5ac518a..93bd068ccee08 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -23,6 +23,7 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
+#include "clang/AST/TypeBase.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/AttrKinds.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
@@ -1518,11 +1519,11 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
     return;
   }
 
-  bool HasKindDecoration = false;
+  bool PrintKindDecoration = Policy.AnonymousTagLocations;
 
   if (T->isCanonicalUnqualified()) {
     if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
-      HasKindDecoration = true;
+      PrintKindDecoration = false;
       OS << D->getKindName();
       OS << ' ';
     }
@@ -1546,51 +1547,10 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
   else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
     assert(Typedef->getIdentifier() && "Typedef without identifier?");
     OS << Typedef->getIdentifier()->getName();
-  } else {
-    // Make an unambiguous representation for anonymous types, e.g.
-    //   (anonymous enum at /usr/include/string.h:120:9)
-    OS << (Policy.MSVCFormatting ? '`' : '(');
-
-    if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
-      OS << "lambda";
-      HasKindDecoration = true;
-    } else if ((isa<RecordDecl>(D) && cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
-      OS << "anonymous";
-    } else {
-      OS << "unnamed";
-    }
-
-    if (Policy.AnonymousTagLocations) {
-      // 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();
-
-      PresumedLoc PLoc = D->getASTContext().getSourceManager().getPresumedLoc(
-          D->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();
-      }
-    }
-
-    OS << (Policy.MSVCFormatting ? '\'' : ')');
-  }
+  } else
+    printAnonymousTagDecl(OS, D, Policy,
+                          /*PrintKindDecoration=*/PrintKindDecoration,
+                          /*PrintTagLocations=*/Policy.AnonymousTagLocations);
 
   // If this is a class template specialization, print the template
   // arguments.
@@ -2469,6 +2429,58 @@ static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
   return false;
 }
 
+void clang::printAnonymousTagDecl(llvm::raw_ostream &OS, const TagDecl *D,
+                                  const PrintingPolicy &Policy,
+                                  bool PrintKindDecoration,
+                                  bool PrintTagLocations) {
+  assert(D);
+
+  // Make an unambiguous representation for anonymous types, e.g.
+  //   (anonymous enum at /usr/include/string.h:120:9)
+  OS << (Policy.MSVCFormatting ? '`' : '(');
+
+  if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
+    PrintKindDecoration = false;
+    OS << "lambda";
+  } else if ((isa<RecordDecl>(D) &&
+              cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
+    OS << "anonymous";
+  } else {
+    OS << "unnamed";
+  }
+
+  // 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 (PrintKindDecoration)
+    OS << " " << D->getKindName();
+
+  if (PrintTagLocations) {
+    PresumedLoc PLoc =
+        D->getASTContext().getSourceManager().getPresumedLoc(D->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();
+    }
+  }
+
+  OS << (Policy.MSVCFormatting ? '\'' : ')');
+}
+
 bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
                                          const NamedDecl *Param,
                                          ArrayRef<TemplateArgument> Args,
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index a556ffca96903..1760e9f732437 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -18,6 +18,7 @@
 #include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ParentMapContext.h"
 #include "clang/AST/PrettyPrinter.h"
+#include "clang/AST/TypeBase.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Lex/Lexer.h"
@@ -514,7 +515,14 @@ static StringRef getNodeName(const RecordDecl &Node,
     return Node.getName();
   }
   Scratch.clear();
-  return ("(anonymous " + Node.getKindName() + ")").toStringRef(Scratch);
+
+  llvm::raw_svector_ostream OS(Scratch);
+
+  printAnonymousTagDecl(
+      OS, llvm::cast<TagDecl>(&Node), Node.getASTContext().getPrintingPolicy(),
+      /*PrintKindDecoration=*/true, /*PrintTagLocations=*/false);
+
+  return OS.str();
 }
 
 static StringRef getNodeName(const NamespaceDecl &Node,
diff --git a/clang/unittests/AST/NamedDeclPrinterTest.cpp b/clang/unittests/AST/NamedDeclPrinterTest.cpp
index cd833725b448d..2fdda1929b2a3 100644
--- a/clang/unittests/AST/NamedDeclPrinterTest.cpp
+++ b/clang/unittests/AST/NamedDeclPrinterTest.cpp
@@ -265,3 +265,31 @@ TEST(NamedDeclPrinter, NestedNameSpecifierTemplateArgs) {
   ASSERT_TRUE(
       PrintedNestedNameSpecifierMatches(Code, "method", "vector<int>::"));
 }
+
+TEST(NamedDeclPrinter, NestedNameSpecifierLambda) {
+  const char *Code =
+      R"(
+        auto l = [] {
+          struct Foo {
+            void method();
+          };
+        };
+)";
+  ASSERT_TRUE(PrintedNestedNameSpecifierMatches(
+      Code, "method", "(lambda)::operator()()::Foo::"));
+}
+
+TEST(NamedDeclPrinter, NestedNameSpecifierAnonymousTags) {
+  const char *Code =
+      R"(
+        struct Foo {
+          struct {
+            struct {
+              void method();
+            } i;
+          };
+        };
+)";
+  ASSERT_TRUE(PrintedNestedNameSpecifierMatches(
+      Code, "method", "Foo::(anonymous)::(unnamed)::"));
+}
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index 3cadf9b265bd1..de4cfa4074eba 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -328,7 +328,7 @@ TEST(TypePrinter, NestedNameSpecifiers) {
   // Further levels of nesting print the entire scope.
   ASSERT_TRUE(PrintedTypeMatches(
       Code, {}, fieldDecl(hasName("u"), hasType(qualType().bind("id"))),
-      "union level1()::Inner::Inner(int)::(anonymous struct)::(unnamed)",
+      "union level1()::Inner::Inner(int)::(unnamed struct)::(unnamed)",
       [](PrintingPolicy &Policy) {
         Policy.FullyQualifiedName = true;
         Policy.AnonymousTagLocations = false;
diff --git a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
index 5d452355d0e43..697623c8a48e8 100644
--- a/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
+++ b/clang/unittests/ASTMatchers/ASTMatchersNarrowingTest.cpp
@@ -2709,25 +2709,48 @@ TEST_P(ASTMatchersTest, HasName_MatchesAnonymousNamespaces) {
   EXPECT_TRUE(matches(code, recordDecl(hasName("::a::C"))));
 }
 
-TEST_P(ASTMatchersTest, HasName_MatchesAnonymousOuterClasses) {
+TEST_P(ASTMatchersTest, HasName_MatchesUnnamedOuterClasses) {
   if (!GetParam().isCXX()) {
     return;
   }
 
   EXPECT_TRUE(matches("class A { class { class C; } x; };",
-                      recordDecl(hasName("A::(anonymous class)::C"))));
+                      recordDecl(hasName("A::(unnamed class)::C"))));
   EXPECT_TRUE(matches("class A { class { class C; } x; };",
-                      recordDecl(hasName("::A::(anonymous class)::C"))));
+                      recordDecl(hasName("::A::(unnamed class)::C"))));
   EXPECT_FALSE(matches("class A { class { class C; } x; };",
                        recordDecl(hasName("::A::C"))));
   EXPECT_TRUE(matches("class A { struct { class C; } x; };",
-                      recordDecl(hasName("A::(anonymous struct)::C"))));
+                      recordDecl(hasName("A::(unnamed struct)::C"))));
   EXPECT_TRUE(matches("class A { struct { class C; } x; };",
-                      recordDecl(hasName("::A::(anonymous struct)::C"))));
+                      recordDecl(hasName("::A::(unnamed struct)::C"))));
   EXPECT_FALSE(matches("class A { struct { class C; } x; };",
                        recordDecl(hasName("::A::C"))));
 }
 
+TEST_P(ASTMatchersTest, HasName_MatchesAnonymousOuterClasses) {
+  if (!GetParam().isCXX()) {
+    return;
+  }
+
+  EXPECT_TRUE(matches(
+      "class A { struct { struct { class C; } x; }; };",
+      recordDecl(hasName("A::(anonymous struct)::(unnamed struct)::C"))));
+  EXPECT_TRUE(matches(
+      "class A { struct { struct { class C; } x; }; };",
+      recordDecl(hasName("::A::(anonymous struct)::(unnamed struct)::C"))));
+  EXPECT_FALSE(matches("class A { struct { struct { class C; } x; }; };",
+                       recordDecl(hasName("A::(unnamed struct)::C"))));
+  EXPECT_TRUE(matches(
+      "class A { class { public: struct { class C; } x; }; };",
+      recordDecl(hasName("A::(anonymous class)::(unnamed struct)::C"))));
+  EXPECT_TRUE(matches(
+      "class A { class { public: struct { class C; } x; }; };",
+      recordDecl(hasName("::A::(anonymous class)::(unnamed struct)::C"))));
+  EXPECT_FALSE(matches("class A { class { public: struct { class C; } x; }; };",
+                       recordDecl(hasName("A::(unnamed struct)::C"))));
+}
+
 TEST_P(ASTMatchersTest, HasName_MatchesFunctionScope) {
   if (!GetParam().isCXX()) {
     return;

>From 17a0ee34158e9a125de41ba6c2857a838a487628 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Nov 2025 12:55:37 +0900
Subject: [PATCH 02/16] fixup! fix test

---
 clang/unittests/AST/NamedDeclPrinterTest.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/clang/unittests/AST/NamedDeclPrinterTest.cpp b/clang/unittests/AST/NamedDeclPrinterTest.cpp
index 2fdda1929b2a3..599ccd7f06fc6 100644
--- a/clang/unittests/AST/NamedDeclPrinterTest.cpp
+++ b/clang/unittests/AST/NamedDeclPrinterTest.cpp
@@ -283,7 +283,8 @@ TEST(NamedDeclPrinter, NestedNameSpecifierAnonymousTags) {
   const char *Code =
       R"(
         struct Foo {
-          struct {
+          class {
+            public:
             struct {
               void method();
             } i;
@@ -291,5 +292,5 @@ TEST(NamedDeclPrinter, NestedNameSpecifierAnonymousTags) {
         };
 )";
   ASSERT_TRUE(PrintedNestedNameSpecifierMatches(
-      Code, "method", "Foo::(anonymous)::(unnamed)::"));
+      Code, "method", "Foo::(anonymous class)::(unnamed struct)::"));
 }

>From 25565237e451f984e2574b6a6109b5e78415a3e6 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Nov 2025 13:40:48 +0900
Subject: [PATCH 03/16] fixup! fix more tests

---
 clang/test/ASTMerge/struct/test.c                         | 4 ++--
 .../Inputs/expected-plists/lambda-notes.cpp.plist         | 2 +-
 .../test/Analysis/analyzer-note-analysis-entry-points.cpp | 6 +++---
 clang/test/Analysis/bug_hash_test.cpp                     | 2 +-
 clang/test/Analysis/debug-CallGraph.cpp                   | 8 ++++----
 .../inlining/Inputs/expected-plists/path-notes.cpp.plist  | 2 +-
 clang/test/CodeGenCXX/predefined-expr.cpp                 | 2 +-
 clang/test/Index/print-type.c                             | 2 +-
 clang/test/Layout/ms-x86-alias-avoidance-padding.cpp      | 4 ++--
 clang/test/SemaCXX/builtin-bswapg.cpp                     | 6 +++---
 clang/test/SemaCXX/cxx2b-consteval-propagate.cpp          | 2 +-
 clang/test/SemaCXX/undefined-internal.cpp                 | 2 +-
 12 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/clang/test/ASTMerge/struct/test.c b/clang/test/ASTMerge/struct/test.c
index d11234472ef29..fe500e6b1ba82 100644
--- a/clang/test/ASTMerge/struct/test.c
+++ b/clang/test/ASTMerge/struct/test.c
@@ -44,10 +44,10 @@
 // CHECK: struct2.c:72:7: note: field 'i' has type 'int' here
 // CHECK: struct2.c:76:5: warning: external variable 'x13' declared with incompatible types in different translation units ('S13' vs. 'S13')
 // CHECK: struct1.c:79:5: note: declared here with type 'S13'
-// CHECK: struct1.c:130:7: warning: type 'struct DeepUnnamedError::(anonymous union)::(anonymous union)::(unnamed at [[PATH_TO_INPUTS:.+]]struct1.c:130:7)' has incompatible definitions in different translation units
+// CHECK: struct1.c:130:7: warning: type 'struct DeepUnnamedError::(unnamed union)::(unnamed union)::(unnamed at [[PATH_TO_INPUTS:.+]]struct1.c:130:7)' has incompatible definitions in different translation units
 // CHECK: struct1.c:131:14: note: field 'i' has type 'long' here
 // CHECK: struct2.c:128:15: note: field 'i' has type 'float' here
-// CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(anonymous union)::(unnamed at [[PATH_TO_INPUTS]]struct1.c:129:5)' has incompatible definitions in different translation units
+// CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(unnamed union)::(unnamed at [[PATH_TO_INPUTS]]struct1.c:129:5)' has incompatible definitions in different translation units
 // CHECK: struct1.c:132:9: note: field 'S' has type 'struct (unnamed struct at [[PATH_TO_INPUTS]]struct1.c:130:7)' here
 // CHECK: struct2.c:129:9: note: field 'S' has type 'struct (unnamed struct at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
 // CHECK: struct2.c:138:3: warning: external variable 'x16' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError')
diff --git a/clang/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist b/clang/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist
index 5c7768cb97ef4..d5859dca9630b 100644
--- a/clang/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist
+++ b/clang/test/Analysis/Inputs/expected-plists/lambda-notes.cpp.plist
@@ -174,7 +174,7 @@
    <key>type</key><string>Division by zero</string>
    <key>check_name</key><string>core.DivideZero</string>
    <!-- This hash is experimental and going to change! -->
-   <key>issue_hash_content_of_line_in_context</key><string>bd4eed3234018edced5efc2ed5562a74</string>
+   <key>issue_hash_content_of_line_in_context</key><string>d3cd158ad0fd8ce44df89c6779a1faec</string>
   <key>issue_context_kind</key><string>C++ method</string>
   <key>issue_context</key><string>operator()</string>
   <key>issue_hash_function_offset</key><string>1</string>
diff --git a/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp
index 7d321bfae61c9..d0cf3a334e647 100644
--- a/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp
+++ b/clang/test/Analysis/analyzer-note-analysis-entry-points.cpp
@@ -51,10 +51,10 @@ void checkASTCodeBodyHasAnalysisEntryPoints() {
 }
 
 void notInvokedLambdaScope() {
-  // CHECK: note: [debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()()
+  // CHECK: note: [debug] analyzing from notInvokedLambdaScope()::(lambda)::operator()()
   // CHECK-NEXT: |   auto notInvokedLambda = []() {
   // CHECK-NEXT: |                           ^
-  // textout-note at +1 {{[debug] analyzing from notInvokedLambdaScope()::(anonymous class)::operator()()}}
+  // textout-note at +1 {{[debug] analyzing from notInvokedLambdaScope()::(lambda)::operator()()}}
   auto notInvokedLambda = []() {
     // common-warning at +1 {{REACHABLE}} textout-note at +1 {{REACHABLE}}
     clang_analyzer_warnIfReached();
@@ -72,4 +72,4 @@ void invokedLambdaScope() {
     clang_analyzer_warnIfReached();
   };
   invokedLambda(); // textout-note {{Calling 'operator()'}}
-}
\ No newline at end of file
+}
diff --git a/clang/test/Analysis/bug_hash_test.cpp b/clang/test/Analysis/bug_hash_test.cpp
index 7b812a76558dd..184d3a9dce255 100644
--- a/clang/test/Analysis/bug_hash_test.cpp
+++ b/clang/test/Analysis/bug_hash_test.cpp
@@ -65,7 +65,7 @@ void AA::X::OutOfLine() {
 
 void testLambda() {
   []() {
-    clang_analyzer_hashDump(5); // expected-warning {{debug.ExprInspection$void testLambda()::(anonymous class)::operator()() const$29$clang_analyzer_hashDump(5);$Category}}
+    clang_analyzer_hashDump(5); // expected-warning {{debug.ExprInspection$void testLambda()::(lambda)::operator()() const$29$clang_analyzer_hashDump(5);$Category}}
   }();
 }
 
diff --git a/clang/test/Analysis/debug-CallGraph.cpp b/clang/test/Analysis/debug-CallGraph.cpp
index 120bb38d3bb33..04d6e5f14f963 100644
--- a/clang/test/Analysis/debug-CallGraph.cpp
+++ b/clang/test/Analysis/debug-CallGraph.cpp
@@ -97,14 +97,14 @@ namespace CallDecl {
 }
 
 // CHECK:--- Call graph Dump ---
-// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call SomeNS::templ SomeNS::templ SomeNS::templUser Lambdas::Callee Lambdas::f1 Lambdas::f1\(\)::\(anonymous class\)::operator\(\) Lambdas::f1\(\)::\(anonymous class\)::operator\(\) CallDecl::SomeDef CallDecl::Caller CallDecl::SomeDecl CallDecl::SomeOtherDecl $}}
+// CHECK-NEXT: {{Function: < root > calls: get5 add test_add mmm foo aaa < > bbb ddd ccc eee fff do_nothing test_single_call SomeNS::templ SomeNS::templ SomeNS::templUser Lambdas::Callee Lambdas::f1 Lambdas::f1\(\)::\(lambda\)::operator\(\) Lambdas::f1\(\)::\(lambda\)::operator\(\) CallDecl::SomeDef CallDecl::Caller CallDecl::SomeDecl CallDecl::SomeOtherDecl $}}
 // CHECK-NEXT: {{Function: CallDecl::Caller calls: CallDecl::SomeDecl CallDecl::SomeOtherDecl $}}
 // CHECK-NEXT: {{Function: CallDecl::SomeOtherDecl calls: CallDecl::SomeDef $}}
 // CHECK-NEXT: {{Function: CallDecl::SomeDecl calls: $}}
 // CHECK-NEXT: {{Function: CallDecl::SomeDef calls: $}}
-// CHECK-NEXT: {{Function: Lambdas::f1 calls: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) Lambdas::f1\(\)::\(anonymous class\)::operator\(\) $}}
-// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
-// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(anonymous class\)::operator\(\) calls: Lambdas::Callee $}}
+// CHECK-NEXT: {{Function: Lambdas::f1 calls: Lambdas::f1\(\)::\(lambda\)::operator\(\) Lambdas::f1\(\)::\(lambda\)::operator\(\) $}}
+// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(lambda\)::operator\(\) calls: Lambdas::Callee $}}
+// CHECK-NEXT: {{Function: Lambdas::f1\(\)::\(lambda\)::operator\(\) calls: Lambdas::Callee $}}
 // CHECK-NEXT: {{Function: Lambdas::Callee calls: $}}
 // CHECK-NEXT: {{Function: SomeNS::templUser calls: SomeNS::templ SomeNS::templ $}}
 // CHECK-NEXT: {{Function: SomeNS::templ calls: eee $}}
diff --git a/clang/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist b/clang/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist
index 6215d48ebd2c8..62aaf0fe8e2d5 100644
--- a/clang/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist
+++ b/clang/test/Analysis/inlining/Inputs/expected-plists/path-notes.cpp.plist
@@ -722,7 +722,7 @@
    <key>type</key><string>Dereference of null pointer</string>
    <key>check_name</key><string>core.NullDereference</string>
    <!-- This hash is experimental and going to change! -->
-   <key>issue_hash_content_of_line_in_context</key><string>efde323086a985fe1e8ccc6cd0123c12</string>
+   <key>issue_hash_content_of_line_in_context</key><string>c13b0c1fd27df0a9d9c0b4c125ade016</string>
   <key>issue_context_kind</key><string>C++ method</string>
   <key>issue_context</key><string>method</string>
   <key>issue_hash_function_offset</key><string>1</string>
diff --git a/clang/test/CodeGenCXX/predefined-expr.cpp b/clang/test/CodeGenCXX/predefined-expr.cpp
index 815bcbb3bd899..48c1205d80d39 100644
--- a/clang/test/CodeGenCXX/predefined-expr.cpp
+++ b/clang/test/CodeGenCXX/predefined-expr.cpp
@@ -10,7 +10,7 @@
 // CHECK-DAG: private unnamed_addr constant [103 x i8] c"static void ClassWithTemplateTemplateParam<char>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
 // CHECK-DAG: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00"
 // CHECK-DAG: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00"
-// CHECK-DAG: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::(anonymous class)::operator()() const\00"
+// CHECK-DAG: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::(lambda)::operator()() const\00"
 // CHECK-DAG: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00"
 
 // CHECK-DAG: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00"
diff --git a/clang/test/Index/print-type.c b/clang/test/Index/print-type.c
index 9fb85f8da4e66..3ceecbd90b250 100644
--- a/clang/test/Index/print-type.c
+++ b/clang/test/Index/print-type.c
@@ -71,7 +71,7 @@ _Atomic(unsigned long) aul;
 // CHECK: TypeRef=struct Struct:16:8 [type=struct Struct] [typekind=Record] [isPOD=1]
 // CHECK: StructDecl=struct (unnamed at {{.*}}):18:1 (Definition) [type=struct (unnamed at {{.*}}print-type.c:18:1)] [typekind=Record] [isPOD=1] [nbFields=2] [isAnon=1] [isAnonRecDecl=0]
 // CHECK: StructDecl=struct (unnamed at {{.*}}):23:1 (Definition) [type=struct (unnamed at {{.*}}print-type.c:23:1)] [typekind=Record] [isPOD=1] [nbFields=1] [isAnon=1] [isAnonRecDecl=0]
-// CHECK: StructDecl=struct (anonymous at {{.*}}):24:3 (Definition) [type=struct (anonymous struct)::(anonymous at {{.*}}print-type.c:24:3)] [typekind=Record] [isPOD=1] [nbFields=2] [isAnon=1] [isAnonRecDecl=1]
+// CHECK: StructDecl=struct (anonymous at {{.*}}):24:3 (Definition) [type=struct (unnamed struct)::(anonymous at {{.*}}print-type.c:24:3)] [typekind=Record] [isPOD=1] [nbFields=2] [isAnon=1] [isAnonRecDecl=1]
 // CHECK: FieldDecl=x:25:17 (Definition) [type=_Atomic(int)] [typekind=Atomic] [valuetype=int] [valuetypekind=Int] [isPOD=0] [isAnonRecDecl=0]
 // CHECK: FieldDecl=y:26:9 (Definition) [type=int] [typekind=Int] [isPOD=1] [isAnonRecDecl=0]
 // CHECK: StructDecl=struct (unnamed at {{.*}}):30:10 (Definition) [type=struct (unnamed at {{.*}}print-type.c:30:10)] [typekind=Record] [isPOD=1] [nbFields=2] [isAnon=1] [isAnonRecDecl=0]
diff --git a/clang/test/Layout/ms-x86-alias-avoidance-padding.cpp b/clang/test/Layout/ms-x86-alias-avoidance-padding.cpp
index bc6a56ef37538..a83810e28741b 100644
--- a/clang/test/Layout/ms-x86-alias-avoidance-padding.cpp
+++ b/clang/test/Layout/ms-x86-alias-avoidance-padding.cpp
@@ -49,7 +49,7 @@ struct AT3 : AT2, AT1 {
 // CHECK-NEXT:    0 |   struct AT2 (base)
 // CHECK-NEXT:    0 |     struct AT0 t
 // CHECK-NEXT:    0 |       union AT0::(unnamed at {{.*}} x
-// CHECK-NEXT:    0 |         struct AT0::(anonymous union)::(unnamed at {{.*}} y
+// CHECK-NEXT:    0 |         struct AT0::(unnamed union)::(unnamed at {{.*}} y
 // CHECK-NEXT:    0 |           int a
 // CHECK-NEXT:    4 |           struct AT t (empty)
 // CHECK:         0 |         int b
@@ -66,7 +66,7 @@ struct AT3 : AT2, AT1 {
 // CHECK-X64-NEXT:    0 |   struct AT2 (base)
 // CHECK-X64-NEXT:    0 |     struct AT0 t
 // CHECK-X64-NEXT:    0 |       union AT0::(unnamed at {{.*}} x
-// CHECK-X64-NEXT:    0 |         struct AT0::(anonymous union)::(unnamed at {{.*}} y
+// CHECK-X64-NEXT:    0 |         struct AT0::(unnamed union)::(unnamed at {{.*}} y
 // CHECK-X64-NEXT:    0 |           int a
 // CHECK-X64-NEXT:    4 |           struct AT t (empty)
 // CHECK-X64:         0 |         int b
diff --git a/clang/test/SemaCXX/builtin-bswapg.cpp b/clang/test/SemaCXX/builtin-bswapg.cpp
index 9d8d103e77c51..539390fa9b606 100644
--- a/clang/test/SemaCXX/builtin-bswapg.cpp
+++ b/clang/test/SemaCXX/builtin-bswapg.cpp
@@ -135,13 +135,13 @@ void test_lambda_errors() {
   
   lambda(1.0f);
   // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'float')}}
-  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<float>' requested here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(lambda)::operator()<float>' requested here}}
   lambda(1.0l);
   // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'long double')}}
-  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<long double>' requested here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(lambda)::operator()<long double>' requested here}}
   lambda("hello");
   // expected-error@#lambda_use {{1st argument must be a scalar integer type (was 'const char *')}}
-  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(anonymous class)::operator()<const char *>' requested here}}
+  // expected-note at -2 {{in instantiation of function template specialization 'test_lambda_errors()::(lambda)::operator()<const char *>' requested here}}
 }
 
 template <class... Args> void test_variadic_template_argument_count(Args... args) {
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index ff104243a9735..6da589dcf1b25 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -636,7 +636,7 @@ template <typename T>
 struct scope_exit {
     T t;
     constexpr ~scope_exit() { t(); }
-    // expected-error at -1 {{call to immediate function 'GH109096::(anonymous class)::operator()' is not a constant expression}} \
+    // expected-error at -1 {{call to immediate function 'GH109096::(lambda)::operator()' is not a constant expression}} \
     // expected-note at -1 {{implicit use of 'this' pointer is only allowed within the evaluation}}
 };
 
diff --git a/clang/test/SemaCXX/undefined-internal.cpp b/clang/test/SemaCXX/undefined-internal.cpp
index 9745f097c76b7..9cd27ee2c981b 100644
--- a/clang/test/SemaCXX/undefined-internal.cpp
+++ b/clang/test/SemaCXX/undefined-internal.cpp
@@ -227,7 +227,7 @@ namespace test7 {
 
 namespace test8 {
   typedef struct {
-    void bar(); // expected-warning {{function 'test8::(anonymous struct)::bar' has internal linkage but is not defined}}
+    void bar(); // expected-warning {{function 'test8::(unnamed struct)::bar' has internal linkage but is not defined}}
     void foo() {
       bar(); // expected-note {{used here}}
     }

>From 3b8f20ebecc486170fc05ca25702f767dcc618fa Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Nov 2025 13:43:42 +0900
Subject: [PATCH 04/16] fixup! fix SemaObjCXX/arc-0x.mm test

---
 clang/test/SemaObjCXX/arc-0x.mm | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/clang/test/SemaObjCXX/arc-0x.mm b/clang/test/SemaObjCXX/arc-0x.mm
index a7418eceb244b..dd8b8e80c2817 100644
--- a/clang/test/SemaObjCXX/arc-0x.mm
+++ b/clang/test/SemaObjCXX/arc-0x.mm
@@ -195,8 +195,8 @@ void test() {
   };
 
   static union { // expected-error {{call to implicitly-deleted default constructor of}}
-    union { // expected-note-re {{default constructor of '(unnamed union at {{.*}}' is implicitly deleted because field 'test_union::(anonymous union)::(anonymous union at {{.*}})' has a deleted default constructor}}
-      union { // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because field 'test_union::(anonymous union)::(anonymous union)::(anonymous union at {{.*}})' has a deleted default constructor}}
+    union { // expected-note-re {{default constructor of '(unnamed union at {{.*}}' is implicitly deleted because field 'test_union::(unnamed union)::(anonymous union at {{.*}})' has a deleted default constructor}}
+      union { // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because field 'test_union::(unnamed union)::(anonymous union)::(anonymous union at {{.*}})' has a deleted default constructor}}
         __weak id g1; // expected-note-re {{default constructor of '(anonymous union at {{.*}}' is implicitly deleted because variant field 'g1' is an ObjC pointer}}
         int g2;
       };

>From c7f6a6a7c307f549f4671075b31cd18493a8ae6b Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 25 Nov 2025 21:30:20 +0900
Subject: [PATCH 05/16] fixup! fix more tests

---
 clang/test/CodeGen/block-with-perdefinedexpr.cpp |  4 ++--
 clang/test/CodeGenCXX/predefined-expr.cpp        |  8 ++++----
 clang/test/SemaCXX/predefined-expr.cpp           | 12 ++++++------
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/clang/test/CodeGen/block-with-perdefinedexpr.cpp b/clang/test/CodeGen/block-with-perdefinedexpr.cpp
index 890c2d6358569..597971e6fb6be 100644
--- a/clang/test/CodeGen/block-with-perdefinedexpr.cpp
+++ b/clang/test/CodeGen/block-with-perdefinedexpr.cpp
@@ -67,11 +67,11 @@ class Foo {
   }
   void inside_lambda() {
     auto lambda = []() {
-      // CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke = private unnamed_addr constant [92 x i8] c"auto foonamespace::Foo::inside_lambda()::(anonymous class)::operator()() const_block_invoke\00", align 1
+      // CHECK-DAG: @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke = private unnamed_addr constant [83 x i8] c"auto foonamespace::Foo::inside_lambda()::(lambda)::operator()() const_block_invoke\00", align 1
       const char * (^block1)() = ^() {
         return __PRETTY_FUNCTION__;
       };
-      // CHECK-DAG: 	  @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_2 = private unnamed_addr constant [94 x i8] c"auto foonamespace::Foo::inside_lambda()::(anonymous class)::operator()() const_block_invoke_2\00", align 1
+      // CHECK-DAG: 	  @__PRETTY_FUNCTION__.___ZZN12foonamespace3Foo13inside_lambdaEvENKUlvE_clEv_block_invoke_2 = private unnamed_addr constant [85 x i8] c"auto foonamespace::Foo::inside_lambda()::(lambda)::operator()() const_block_invoke_2\00", align 1
       const char * (^block2)() = ^() {
         return __PRETTY_FUNCTION__;
       };
diff --git a/clang/test/CodeGenCXX/predefined-expr.cpp b/clang/test/CodeGenCXX/predefined-expr.cpp
index 48c1205d80d39..1f036c5d520c9 100644
--- a/clang/test/CodeGenCXX/predefined-expr.cpp
+++ b/clang/test/CodeGenCXX/predefined-expr.cpp
@@ -10,7 +10,7 @@
 // CHECK-DAG: private unnamed_addr constant [103 x i8] c"static void ClassWithTemplateTemplateParam<char>::staticMember() [T = char, Param = NS::ClassTemplate]\00"
 // CHECK-DAG: private unnamed_addr constant [106 x i8] c"void OuterClass<int *>::MiddleClass::InnerClass<float>::memberFunction(T, U) const [T = int *, U = float]\00"
 // CHECK-DAG: private unnamed_addr constant [51 x i8] c"void functionTemplateWithCapturedStmt(T) [T = int]\00"
-// CHECK-DAG: private unnamed_addr constant [76 x i8] c"auto functionTemplateWithLambda(int)::(lambda)::operator()() const\00"
+// CHECK-DAG: private unnamed_addr constant [67 x i8] c"auto functionTemplateWithLambda(int)::(lambda)::operator()() const\00"
 // CHECK-DAG: private unnamed_addr constant [65 x i8] c"void functionTemplateWithUnnamedTemplateParameter(T) [T = float]\00"
 
 // CHECK-DAG: private unnamed_addr constant [60 x i8] c"void functionTemplateExplicitSpecialization(T) [T = double]\00"
@@ -28,13 +28,13 @@
 // CHECK-DAG: private unnamed_addr constant [46 x i8] c"void NS::Base::functionTemplate1(T) [T = int]\00"
 
 // CHECK-DAG: private unnamed_addr constant [23 x i8] c"anonymousUnionFunction\00"
-// CHECK-DAG: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous union)::anonymousUnionFunction()\00"
+// CHECK-DAG: private unnamed_addr constant [81 x i8] c"void NS::ContainerForAnonymousRecords::(unnamed union)::anonymousUnionFunction()\00"
 
 // CHECK-DAG: private unnamed_addr constant [24 x i8] c"anonymousStructFunction\00"
-// CHECK-DAG: private unnamed_addr constant [85 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous struct)::anonymousStructFunction()\00"
+// CHECK-DAG: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(unnamed struct)::anonymousStructFunction()\00"
 
 // CHECK-DAG: private unnamed_addr constant [23 x i8] c"anonymousClassFunction\00"
-// CHECK-DAG: private unnamed_addr constant [83 x i8] c"void NS::ContainerForAnonymousRecords::(anonymous class)::anonymousClassFunction()\00"
+// CHECK-DAG: private unnamed_addr constant [81 x i8] c"void NS::ContainerForAnonymousRecords::(unnamed class)::anonymousClassFunction()\00"
 
 // CHECK-DAG: private unnamed_addr constant [12 x i8] c"~Destructor\00"
 // CHECK-DAG: private unnamed_addr constant [30 x i8] c"NS::Destructor::~Destructor()\00"
diff --git a/clang/test/SemaCXX/predefined-expr.cpp b/clang/test/SemaCXX/predefined-expr.cpp
index 8cba0d41a2997..ea41f0b505d31 100644
--- a/clang/test/SemaCXX/predefined-expr.cpp
+++ b/clang/test/SemaCXX/predefined-expr.cpp
@@ -26,8 +26,8 @@ int baz() {
   []() {
     static_assert(sizeof(__func__) == 11, "operator()");
     static_assert(sizeof(__FUNCTION__) == 11, "operator()");
-    static_assert(sizeof(__PRETTY_FUNCTION__) == 50,
-                  "auto baz()::<anonymous class>::operator()() const");
+    static_assert(sizeof(__PRETTY_FUNCTION__) == 41,
+                  "auto baz()::<lambda>::operator()() const");
     return 0;
   }
   ();
@@ -56,8 +56,8 @@ int main() {
   []() {
     static_assert(sizeof(__func__) == 11, "operator()");
     static_assert(sizeof(__FUNCTION__) == 11, "operator()");
-    static_assert(sizeof(__PRETTY_FUNCTION__) == 51,
-                  "auto main()::<anonymous class>::operator()() const");
+    static_assert(sizeof(__PRETTY_FUNCTION__) == 42,
+                  "auto main()::<lambda>::operator()() const");
     return 0;
   }
   ();
@@ -87,8 +87,8 @@ int main() {
     {
       static_assert(sizeof(__func__) == 11, "operator()");
       static_assert(sizeof(__FUNCTION__) == 11, "operator()");
-      static_assert(sizeof(__PRETTY_FUNCTION__) == 51,
-                    "auto main()::<anonymous class>::operator()() const");
+      static_assert(sizeof(__PRETTY_FUNCTION__) == 42,
+                    "auto main()::<lambda>::operator()() const");
     }
   }
   ();

>From 3f2d73549a668ae2debeb27e7af0918449c83050 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 26 Nov 2025 07:38:56 +0900
Subject: [PATCH 06/16] fixup! fix SymbolCollectorTests.cpp

---
 clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index 1ce28c91a420c..d62aebab72bf9 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1471,7 +1471,7 @@ TEST_F(SymbolCollectorTest, NamelessSymbols) {
   )";
   runSymbolCollector(Header, /*Main=*/"");
   EXPECT_THAT(Symbols, UnorderedElementsAre(qName("Foo"),
-                                            qName("(anonymous struct)::a")));
+                                            qName("(unnamed struct)::a")));
 }
 
 TEST_F(SymbolCollectorTest, SymbolFormedFromRegisteredSchemeFromMacro) {

>From c843a0369b43d1f9b7e65b877a0b256ec1938220 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 26 Nov 2025 07:39:36 +0900
Subject: [PATCH 07/16] fixup! fix FindSymbolsTests.cpp

---
 clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp     | 2 +-
 clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
index 5b1630eb00cb1..217305a7c60c2 100644
--- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -106,7 +106,7 @@ TEST(WorkspaceSymbols, Unnamed) {
               ElementsAre(AllOf(qName("UnnamedStruct"),
                                 withKind(SymbolKind::Variable))));
   EXPECT_THAT(getSymbols(TU, "InUnnamed"),
-              ElementsAre(AllOf(qName("(anonymous struct)::InUnnamed"),
+              ElementsAre(AllOf(qName("(unnamed struct)::InUnnamed"),
                                 withKind(SymbolKind::Field))));
 }
 
diff --git a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
index d62aebab72bf9..94116fca3cbb2 100644
--- a/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SymbolCollectorTests.cpp
@@ -1470,8 +1470,8 @@ TEST_F(SymbolCollectorTest, NamelessSymbols) {
     } Foo;
   )";
   runSymbolCollector(Header, /*Main=*/"");
-  EXPECT_THAT(Symbols, UnorderedElementsAre(qName("Foo"),
-                                            qName("(unnamed struct)::a")));
+  EXPECT_THAT(Symbols,
+              UnorderedElementsAre(qName("Foo"), qName("(unnamed struct)::a")));
 }
 
 TEST_F(SymbolCollectorTest, SymbolFormedFromRegisteredSchemeFromMacro) {

>From 9653cd09e08b8d0549d49a63aaa9dc5e39000e9b Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Wed, 26 Nov 2025 10:25:03 +0900
Subject: [PATCH 08/16] fixup! implement TagDecl::printName

---
 .../clangd/unittests/FindSymbolsTests.cpp     | 11 +--
 .../clangd/unittests/FindTargetTests.cpp      |  2 +-
 .../clangd/unittests/HoverTests.cpp           |  2 +-
 clang/include/clang/AST/Decl.h                |  3 +
 clang/include/clang/AST/PrettyPrinter.h       |  7 +-
 clang/include/clang/AST/TypeBase.h            |  4 -
 clang/lib/AST/Decl.cpp                        | 89 +++++++++++++++----
 clang/lib/AST/TypePrinter.cpp                 | 79 ++++------------
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp |  6 +-
 clang/test/AST/HLSL/cbuffer.hlsl              |  4 +-
 clang/test/AST/ast-dump-decl-json.c           |  8 +-
 clang/test/AST/ast-dump-records-json.cpp      |  4 +-
 clang/test/AST/ast-dump-records.c             |  4 +-
 clang/test/AST/ast-dump-records.cpp           |  4 +-
 clang/test/ASTMerge/struct/test.c             |  4 +-
 clang/test/Analysis/cfg.cpp                   |  6 +-
 clang/test/C/C23/n3006.c                      |  2 +-
 clang/test/C/C23/n3037.c                      |  8 +-
 clang/test/Sema/assign.c                      |  2 +-
 clang/test/Sema/switch.c                      | 32 +++----
 clang/test/SemaCXX/cxx0x-nontrivial-union.cpp |  2 +-
 clang/test/SemaCXX/cxx1z-decomposition.cpp    |  2 +-
 clang/unittests/Tooling/QualTypeNamesTest.cpp |  6 +-
 23 files changed, 153 insertions(+), 138 deletions(-)

diff --git a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
index 217305a7c60c2..d6e94bf752452 100644
--- a/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindSymbolsTests.cpp
@@ -656,15 +656,16 @@ TEST(DocumentSymbols, Enums) {
       getSymbols(TU.build()),
       ElementsAre(
           AllOf(withName("(anonymous enum)"), withDetail("enum"),
-                children(AllOf(withName("Red"), withDetail("(unnamed)")))),
+                children(AllOf(withName("Red"), withDetail("(unnamed enum)")))),
           AllOf(withName("Color"), withDetail("enum"),
                 children(AllOf(withName("Green"), withDetail("Color")))),
           AllOf(withName("Color2"), withDetail("enum"),
                 children(AllOf(withName("Yellow"), withDetail("Color2")))),
-          AllOf(withName("ns"),
-                children(AllOf(withName("(anonymous enum)"), withDetail("enum"),
-                               children(AllOf(withName("Black"),
-                                              withDetail("(unnamed)"))))))));
+          AllOf(
+              withName("ns"),
+              children(AllOf(withName("(anonymous enum)"), withDetail("enum"),
+                             children(AllOf(withName("Black"),
+                                            withDetail("(unnamed enum)"))))))));
 }
 
 TEST(DocumentSymbols, Macro) {
diff --git a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
index dd26182630ae1..6aee310208e5c 100644
--- a/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
+++ b/clang-tools-extra/clangd/unittests/FindTargetTests.cpp
@@ -1827,7 +1827,7 @@ TEST_F(FindExplicitReferencesTest, AllRefsInFoo) {
               int (*$2^fptr)(int $3^a, int) = nullptr;
              }
            )cpp",
-           "0: targets = {(unnamed)}\n"
+           "0: targets = {(unnamed class)}\n"
            "1: targets = {x}, decl\n"
            "2: targets = {fptr}, decl\n"
            "3: targets = {a}, decl\n"},
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index eb858ff616e90..00fa14b32dd6c 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2103,7 +2103,7 @@ TEST(Hover, All) {
             HI.NamespaceScope = "";
             // FIXME: This should be `(anon enum)::`
             HI.LocalScope = "";
-            HI.Type = "enum (unnamed)";
+            HI.Type = "enum (unnamed enum)";
             HI.Definition = "ONE";
             HI.Value = "0";
           }},
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 2e8ceff453547..5c46c912186c4 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -3771,6 +3771,9 @@ class TagDecl : public TypeDecl,
   /// True if this decl is currently being defined.
   void setBeingDefined(bool V = true) { TagDeclBits.IsBeingDefined = V; }
 
+  void printAnonymousTagDecl(llvm::raw_ostream &OS,
+                             const PrintingPolicy &Policy) const;
+
 public:
   friend class ASTDeclReader;
   friend class ASTDeclWriter;
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 48105b3b9d4cd..fb679e50a2d68 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -61,8 +61,10 @@ struct PrintingPolicy {
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
       : Indentation(2), SuppressSpecifiers(false),
-        SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
-        SuppressScope(false), SuppressUnwrittenScope(false),
+        SuppressTagKeyword(LO.CPlusPlus),
+        SuppressTagKeywordInAnonymousTagNames(false),
+        IncludeTagDefinition(false), SuppressScope(false),
+        SuppressUnwrittenScope(false),
         SuppressInlineNamespace(
             llvm::to_underlying(SuppressInlineNamespaceMode::Redundant)),
         SuppressInitializers(false), ConstantArraySizeAsWritten(false),
@@ -123,6 +125,7 @@ struct PrintingPolicy {
   /// \endcode
   LLVM_PREFERRED_TYPE(bool)
   unsigned SuppressTagKeyword : 1;
+  unsigned SuppressTagKeywordInAnonymousTagNames : 1;
 
   /// When true, include the body of a tag definition.
   ///
diff --git a/clang/include/clang/AST/TypeBase.h b/clang/include/clang/AST/TypeBase.h
index 1c36067ff35b2..30b9efe5a31b7 100644
--- a/clang/include/clang/AST/TypeBase.h
+++ b/clang/include/clang/AST/TypeBase.h
@@ -7374,10 +7374,6 @@ bool isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
                                   ArrayRef<TemplateArgument> Args,
                                   unsigned Depth);
 
-void printAnonymousTagDecl(llvm::raw_ostream &OS, const TagDecl *D,
-                           const PrintingPolicy &Policy,
-                           bool PrintKindDecoration, bool PrintTagLocations);
-
 /// Represents a qualified type name for which the type name is
 /// dependent.
 ///
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 101b25dcc6494..ce29ba49b03d0 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1792,15 +1792,17 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
       }
       else
         OS << *ND;
-    } else if (const auto *RD = dyn_cast<RecordDecl>(DC)) {
-      if (TypedefNameDecl *TD = RD->getTypedefNameForAnonDecl())
-        OS << *TD;
-      else if (!RD->getIdentifier())
-        printAnonymousTagDecl(OS, llvm::cast<TagDecl>(RD), P,
-                              /*PrintKindDecoration=*/true,
-                              /*AllowSourceLocations=*/false);
-      else
-        OS << *RD;
+    } else if (const auto *RD = llvm::dyn_cast<RecordDecl>(DC)) {
+      PrintingPolicy Copy(P);
+      // As part of a scope we want to print anonymous names as:
+      // ..::(anonymous struct)::..
+      //
+      // I.e., suppress tag locations, suppress leading keyword, *don't*
+      // suppress tag in name
+      Copy.SuppressTagKeyword = true;
+      Copy.SuppressTagKeywordInAnonymousTagNames = false;
+      Copy.AnonymousTagLocations = false;
+      RD->printName(OS, Copy);
     } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
       const FunctionProtoType *FT = nullptr;
       if (FD->hasWrittenPrototype())
@@ -4959,19 +4961,76 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) {
   }
 }
 
+void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS,
+                                    const PrintingPolicy &Policy) const {
+  if (TypedefNameDecl *Typedef = getTypedefNameForAnonDecl()) {
+    assert(Typedef->getIdentifier() && "Typedef without identifier?");
+    OS << Typedef->getIdentifier()->getName();
+    return;
+  }
+
+  bool SuppressTagKeywordInName = Policy.SuppressTagKeywordInAnonymousTagNames;
+
+  // Emit leading keyword. Since we printed a leading keyword make sure we
+  // don't print the tag as part of the name too.
+  if (!Policy.SuppressTagKeyword) {
+    OS << getKindName() << ' ';
+    SuppressTagKeywordInName = true;
+  }
+
+  // Make an unambiguous representation for anonymous types, e.g.
+  //   (anonymous enum at /usr/include/string.h:120:9)
+  OS << (Policy.MSVCFormatting ? '`' : '(');
+
+  if (isa<CXXRecordDecl>(this) && cast<CXXRecordDecl>(this)->isLambda()) {
+    OS << "lambda";
+    SuppressTagKeywordInName = true;
+  } else if ((isa<RecordDecl>(this) &&
+              cast<RecordDecl>(this)->isAnonymousStructOrUnion())) {
+    OS << "anonymous";
+  } else {
+    OS << "unnamed";
+  }
+
+  if (!SuppressTagKeywordInName)
+    OS << ' ' << getKindName();
+
+  if (Policy.AnonymousTagLocations) {
+    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();
+    }
+  }
+
+  OS << (Policy.MSVCFormatting ? '\'' : ')');
+}
+
 void TagDecl::printName(raw_ostream &OS, const PrintingPolicy &Policy) const {
   DeclarationName Name = getDeclName();
   // If the name is supposed to have an identifier but does not have one, then
   // the tag is anonymous and we should print it differently.
   if (Name.isIdentifier() && !Name.getAsIdentifierInfo()) {
-    // If the caller wanted to print a qualified name, they've already printed
-    // the scope. And if the caller doesn't want that, the scope information
-    // is already printed as part of the type.
-    PrintingPolicy Copy(Policy);
-    Copy.SuppressScope = true;
-    QualType(getASTContext().getCanonicalTagType(this)).print(OS, Copy);
+    printAnonymousTagDecl(OS, Policy);
+
     return;
   }
+
   // Otherwise, do the normal printing.
   Name.print(OS, Policy);
 }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 93bd068ccee08..61c27782c7468 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1519,18 +1519,19 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
     return;
   }
 
-  bool PrintKindDecoration = Policy.AnonymousTagLocations;
-
+  bool PrintedKindDecoration = false;
   if (T->isCanonicalUnqualified()) {
     if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
-      PrintKindDecoration = false;
+      PrintedKindDecoration = true;
       OS << D->getKindName();
       OS << ' ';
     }
   } else {
     OS << TypeWithKeyword::getKeywordName(T->getKeyword());
-    if (T->getKeyword() != ElaboratedTypeKeyword::None)
+    if (T->getKeyword() != ElaboratedTypeKeyword::None) {
+      PrintedKindDecoration = true;
       OS << ' ';
+    }
   }
 
   if (!Policy.FullyQualifiedName && !T->isCanonicalUnqualified()) {
@@ -1544,13 +1545,17 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
   if (const IdentifierInfo *II = D->getIdentifier())
     OS << II->getName();
-  else if (TypedefNameDecl *Typedef = D->getTypedefNameForAnonDecl()) {
-    assert(Typedef->getIdentifier() && "Typedef without identifier?");
-    OS << Typedef->getIdentifier()->getName();
-  } else
-    printAnonymousTagDecl(OS, D, Policy,
-                          /*PrintKindDecoration=*/PrintKindDecoration,
-                          /*PrintTagLocations=*/Policy.AnonymousTagLocations);
+  else {
+    clang::PrintingPolicy Copy(Policy);
+
+    // Suppress the redundant tag keyword if we just printed one.
+    if (PrintedKindDecoration) {
+      Copy.SuppressTagKeywordInAnonymousTagNames = true;
+      Copy.SuppressTagKeyword = true;
+    }
+
+    D->printName(OS, Copy);
+  }
 
   // If this is a class template specialization, print the template
   // arguments.
@@ -2429,58 +2434,6 @@ static bool isSubstitutedTemplateArgument(ASTContext &Ctx, TemplateArgument Arg,
   return false;
 }
 
-void clang::printAnonymousTagDecl(llvm::raw_ostream &OS, const TagDecl *D,
-                                  const PrintingPolicy &Policy,
-                                  bool PrintKindDecoration,
-                                  bool PrintTagLocations) {
-  assert(D);
-
-  // Make an unambiguous representation for anonymous types, e.g.
-  //   (anonymous enum at /usr/include/string.h:120:9)
-  OS << (Policy.MSVCFormatting ? '`' : '(');
-
-  if (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda()) {
-    PrintKindDecoration = false;
-    OS << "lambda";
-  } else if ((isa<RecordDecl>(D) &&
-              cast<RecordDecl>(D)->isAnonymousStructOrUnion())) {
-    OS << "anonymous";
-  } else {
-    OS << "unnamed";
-  }
-
-  // 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 (PrintKindDecoration)
-    OS << " " << D->getKindName();
-
-  if (PrintTagLocations) {
-    PresumedLoc PLoc =
-        D->getASTContext().getSourceManager().getPresumedLoc(D->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();
-    }
-  }
-
-  OS << (Policy.MSVCFormatting ? '\'' : ')');
-}
-
 bool clang::isSubstitutedDefaultArgument(ASTContext &Ctx, TemplateArgument Arg,
                                          const NamedDecl *Param,
                                          ArrayRef<TemplateArgument> Args,
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 1760e9f732437..965f766170957 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -518,9 +518,9 @@ static StringRef getNodeName(const RecordDecl &Node,
 
   llvm::raw_svector_ostream OS(Scratch);
 
-  printAnonymousTagDecl(
-      OS, llvm::cast<TagDecl>(&Node), Node.getASTContext().getPrintingPolicy(),
-      /*PrintKindDecoration=*/true, /*PrintTagLocations=*/false);
+  PrintingPolicy Copy(Node.getASTContext().getPrintingPolicy());
+  Copy.AnonymousTagLocations = false;
+  Node.printName(OS, Copy);
 
   return OS.str();
 }
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index b0b5b989e36c2..487261af19133 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -191,7 +191,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s9;
-  // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:[[# @LINE - 8]]:3
+  // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed at {{.*}}cbuffer.hlsl:[[# @LINE - 8]]:3
   // CHECK: CXXRecordDecl {{.*}} struct definition
   struct {
     // CHECK: FieldDecl {{.*}} g 'float'
@@ -199,7 +199,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s10;
-  // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:[[# @LINE - 6]]:3
+  // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed at {{.*}}cbuffer.hlsl:[[# @LINE - 6]]:3
   // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_anon definition
   // CHECK: PackedAttr
   // CHECK-NEXT: FieldDecl {{.*}} e 'float'
diff --git a/clang/test/AST/ast-dump-decl-json.c b/clang/test/AST/ast-dump-decl-json.c
index b84ddf93f44c3..50eaaaffb52d9 100644
--- a/clang/test/AST/ast-dump-decl-json.c
+++ b/clang/test/AST/ast-dump-decl-json.c
@@ -585,7 +585,7 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "e",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "qualType": "enum (unnamed enum at {{.*}}:31:3)"
+// CHECK-NEXT:     "qualType": "enum (unnamed at {{.*}}:31:3)"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
@@ -776,7 +776,7 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "testRecordDeclAnon1",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "qualType": "struct (unnamed struct at {{.*}}:46:3)"
+// CHECK-NEXT:     "qualType": "struct (unnamed at {{.*}}:46:3)"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
@@ -1150,7 +1150,7 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:  "name": "TestFunctionDecl",
 // CHECK-NEXT:  "mangledName": "TestFunctionDecl",
 // CHECK-NEXT:  "type": {
-// CHECK-NEXT:   "qualType": "int (int, enum (unnamed enum at {{.*}}:69:29))"
+// CHECK-NEXT:   "qualType": "int (int, enum (unnamed at {{.*}}:69:29))"
 // CHECK-NEXT:  },
 // CHECK-NEXT:  "inner": [
 // CHECK-NEXT:   {
@@ -1202,7 +1202,7 @@ void testParmVarDecl(int TestParmVarDecl);
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "y",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "qualType": "enum (unnamed enum at {{.*}}:69:29)"
+// CHECK-NEXT:     "qualType": "enum (unnamed at {{.*}}:69:29)"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
diff --git a/clang/test/AST/ast-dump-records-json.cpp b/clang/test/AST/ast-dump-records-json.cpp
index 941c6a675448a..03ae098dab037 100644
--- a/clang/test/AST/ast-dump-records-json.cpp
+++ b/clang/test/AST/ast-dump-records-json.cpp
@@ -795,7 +795,7 @@ struct Derived6 : virtual public Bases... {
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "b",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "qualType": "struct (unnamed struct at {{.*}}:16:3)"
+// CHECK-NEXT:     "qualType": "struct (unnamed at {{.*}}:16:3)"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
@@ -2071,7 +2071,7 @@ struct Derived6 : virtual public Bases... {
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "name": "b",
 // CHECK-NEXT:    "type": {
-// CHECK-NEXT:     "qualType": "struct (unnamed struct at {{.*}}:50:3)"
+// CHECK-NEXT:     "qualType": "struct (unnamed at {{.*}}:50:3)"
 // CHECK-NEXT:    }
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
diff --git a/clang/test/AST/ast-dump-records.c b/clang/test/AST/ast-dump-records.c
index 1dc175c4a8560..b8320a1e064f2 100644
--- a/clang/test/AST/ast-dump-records.c
+++ b/clang/test/AST/ast-dump-records.c
@@ -47,7 +47,7 @@ struct C {
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
   } b;
-  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-5]]:3)'
+  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed at {{.*}}:[[@LINE-5]]:3)'
 
   union {
     // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+5]]:3> line:[[@LINE-1]]:3 union definition
@@ -128,7 +128,7 @@ union G {
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
   } b;
-  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-5]]:3)'
+  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-5]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed at {{.*}}:[[@LINE-5]]:3)'
 
   union {
     // CHECK-NEXT: RecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+5]]:3> line:[[@LINE-1]]:3 union definition
diff --git a/clang/test/AST/ast-dump-records.cpp b/clang/test/AST/ast-dump-records.cpp
index edd13ba1c6f12..5801672a0f9d6 100644
--- a/clang/test/AST/ast-dump-records.cpp
+++ b/clang/test/AST/ast-dump-records.cpp
@@ -72,7 +72,7 @@ struct C {
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
   } b;
-  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-12]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-12]]:3)'
+  // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-12]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed at {{.*}}:[[@LINE-12]]:3)'
 
   union {
     // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+12]]:3> line:[[@LINE-1]]:3 union definition
@@ -202,7 +202,7 @@ union G {
     int a;
     // CHECK-NEXT: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:5, col:9> col:9 a 'int'
   } b;
-  // CHECK: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-13]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed struct at {{.*}}:[[@LINE-13]]:3)'
+  // CHECK: FieldDecl 0x{{[^ ]*}} <line:[[@LINE-13]]:3, line:[[@LINE-1]]:5> col:5 b 'struct (unnamed at {{.*}}:[[@LINE-13]]:3)'
 
   union {
     // CHECK-NEXT: CXXRecordDecl 0x{{[^ ]*}} <line:[[@LINE-1]]:3, line:[[@LINE+13]]:3> line:[[@LINE-1]]:3 union definition
diff --git a/clang/test/ASTMerge/struct/test.c b/clang/test/ASTMerge/struct/test.c
index fe500e6b1ba82..b34869c1eed44 100644
--- a/clang/test/ASTMerge/struct/test.c
+++ b/clang/test/ASTMerge/struct/test.c
@@ -48,8 +48,8 @@
 // CHECK: struct1.c:131:14: note: field 'i' has type 'long' here
 // CHECK: struct2.c:128:15: note: field 'i' has type 'float' here
 // CHECK: struct1.c:129:5: warning: type 'union DeepUnnamedError::(unnamed union)::(unnamed at [[PATH_TO_INPUTS]]struct1.c:129:5)' has incompatible definitions in different translation units
-// CHECK: struct1.c:132:9: note: field 'S' has type 'struct (unnamed struct at [[PATH_TO_INPUTS]]struct1.c:130:7)' here
-// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (unnamed struct at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
+// CHECK: struct1.c:132:9: note: field 'S' has type 'struct (unnamed at [[PATH_TO_INPUTS]]struct1.c:130:7)' here
+// CHECK: struct2.c:129:9: note: field 'S' has type 'struct (unnamed at [[PATH_TO_INPUTS]]struct2.c:127:7)' here
 // CHECK: struct2.c:138:3: warning: external variable 'x16' declared with incompatible types in different translation units ('struct DeepUnnamedError' vs. 'struct DeepUnnamedError')
 // CHECK: struct1.c:141:3: note: declared here with type 'struct DeepUnnamedError'
 // CHECK: 20 warnings generated
diff --git a/clang/test/Analysis/cfg.cpp b/clang/test/Analysis/cfg.cpp
index d6cef88dc18a6..2a88b73d27756 100644
--- a/clang/test/Analysis/cfg.cpp
+++ b/clang/test/Analysis/cfg.cpp
@@ -26,9 +26,9 @@
 // WARNINGS-NEXT: (CXXConstructExpr, struct standalone)
 // ANALYZER-NEXT: (CXXConstructExpr, [B1.9], struct standalone)
 // CHECK-NEXT:   9: struct standalone myStandalone;
-// WARNINGS-NEXT: (CXXConstructExpr, struct (unnamed struct at {{.*}}))
-// ANALYZER-NEXT: (CXXConstructExpr, [B1.11], struct (unnamed struct at {{.*}}))
-// CHECK-NEXT:  11: struct (unnamed struct at {{.*}}) myAnon;
+// WARNINGS-NEXT: (CXXConstructExpr, struct (unnamed at {{.*}}))
+// ANALYZER-NEXT: (CXXConstructExpr, [B1.11], struct (unnamed at {{.*}}))
+// CHECK-NEXT:  11: struct (unnamed at {{.*}}) myAnon;
 // WARNINGS-NEXT: (CXXConstructExpr, struct named)
 // ANALYZER-NEXT: (CXXConstructExpr, [B1.13], struct named)
 // CHECK-NEXT:  13: struct named myNamed;
diff --git a/clang/test/C/C23/n3006.c b/clang/test/C/C23/n3006.c
index e0713fa9969c4..14d73da9db49c 100644
--- a/clang/test/C/C23/n3006.c
+++ b/clang/test/C/C23/n3006.c
@@ -103,7 +103,7 @@ void misc_struct_test(void) {
 
   constexpr struct {
       int b;
-  } b = (struct S { int x; }){ 0 };  // expected-error-re {{initializing 'const struct (unnamed struct at {{.*}}n3006.c:104:13)' with an expression of incompatible type 'struct S'}}
+  } b = (struct S { int x; }){ 0 };  // expected-error-re {{initializing 'const struct (unnamed at {{.*}}n3006.c:104:13)' with an expression of incompatible type 'struct S'}}
 
   auto z = ({
       int a = 12;
diff --git a/clang/test/C/C23/n3037.c b/clang/test/C/C23/n3037.c
index 113ecf74d8bef..aec0407e2bfd4 100644
--- a/clang/test/C/C23/n3037.c
+++ b/clang/test/C/C23/n3037.c
@@ -45,7 +45,7 @@ union barp { int x; float y; };     // c17-note {{previous definition is here}}
 union barp { int x; float y; };     // c17-error {{redefinition of 'barp'}}
 typedef struct q { int x; } q_t;    // c17-note 2 {{previous definition is here}}
 typedef struct q { int x; } q_t;    // c17-error {{redefinition of 'q'}} \
-                                       c17-error-re {{typedef redefinition with different types ('struct (unnamed struct at {{.*}})' vs 'struct q')}}
+                                       c17-error-re {{typedef redefinition with different types ('struct (unnamed at {{.*}})' vs 'struct q')}}
 typedef struct { int x; } untagged_q_t; // both-note {{previous definition is here}}
 typedef struct { int x; } untagged_q_t; // both-error {{typedef redefinition with different types}}
 void func3(void) {
@@ -432,9 +432,9 @@ void compare_unnamed_struct_from_different_outer_type(
     struct InnerUnnamedStruct_differentNaming differentFieldName,
     struct InnerUnnamedStruct_differentShape differentType) {
   inner_unnamed_tagged.untagged = sameOuterType.untagged;
-  inner_unnamed_tagged.untagged = matchingType.untagged; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}
-  inner_unnamed_tagged.untagged = differentFieldName.untaggedDifferent; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}
-  inner_unnamed_tagged.untagged = differentType.untagged; // both-error-re {{assigning to 'struct (unnamed struct at {{.*}})' from incompatible type 'struct (unnamed struct at {{.*}})'}}
+  inner_unnamed_tagged.untagged = matchingType.untagged; // both-error-re {{assigning to 'struct (unnamed at {{.*}})' from incompatible type 'struct (unnamed at {{.*}})'}}
+  inner_unnamed_tagged.untagged = differentFieldName.untaggedDifferent; // both-error-re {{assigning to 'struct (unnamed at {{.*}})' from incompatible type 'struct (unnamed at {{.*}})'}}
+  inner_unnamed_tagged.untagged = differentType.untagged; // both-error-re {{assigning to 'struct (unnamed at {{.*}})' from incompatible type 'struct (unnamed at {{.*}})'}}
 }
 
 // Test the same thing with enumerations (test for unions is omitted because
diff --git a/clang/test/Sema/assign.c b/clang/test/Sema/assign.c
index 13ea1062b9e1e..711e68ce4e44c 100644
--- a/clang/test/Sema/assign.c
+++ b/clang/test/Sema/assign.c
@@ -6,7 +6,7 @@ void test2 (const struct {int a;} *x) {
   // expected-note at -1 {{variable 'x' declared const here}}
 
   x->a = 10;
-  // expected-error-re at -1 {{cannot assign to variable 'x' with const-qualified type 'const struct (unnamed struct at {{.*}}assign.c:5:19) *'}}
+  // expected-error-re at -1 {{cannot assign to variable 'x' with const-qualified type 'const struct (unnamed at {{.*}}assign.c:5:19) *'}}
 }
 
 typedef int arr[10];
diff --git a/clang/test/Sema/switch.c b/clang/test/Sema/switch.c
index 6e912d02d6cc7..76068b6415c08 100644
--- a/clang/test/Sema/switch.c
+++ b/clang/test/Sema/switch.c
@@ -110,14 +110,14 @@ void test7(void) {
   switch(a) {
     case A:
     case B:
-    case 3: // expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 3: // expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
   switch(a) {
     case A:
     case B:
-    case 3 ... //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
-        4: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 3 ... //expected-warning{{case value not in enumerated type 'enum (unnamed}}
+        4: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
   switch(a) {
@@ -125,16 +125,16 @@ void test7(void) {
       break;
   }
   switch(a) {
-    case 0 ... 2: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 0 ... 2: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
   switch(a) {
-    case 1 ... 3: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 1 ... 3: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
   switch(a) {
-    case 0 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
-      3:  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 0 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
+      3:  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
 
@@ -168,11 +168,11 @@ void test9(void) {
     C = 1
   } a;
   switch(a) {
-    case 0: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 0: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
     case 1:
-    case 2: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 2: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
     case 3:
-    case 4: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 4: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
 }
@@ -185,14 +185,14 @@ void test10(void) {
     D = 12
   } a;
   switch(a) {
-    case 0 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
-	    1:  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 0 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
+	    1:  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
     case 2 ... 4:
-    case 5 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}	
-	      9:  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 5 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed}}	
+	      9:  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
     case 10 ... 12:
-    case 13 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
-              16: //expected-warning{{case value not in enumerated type 'enum (unnamed enum}}
+    case 13 ...  //expected-warning{{case value not in enumerated type 'enum (unnamed}}
+              16: //expected-warning{{case value not in enumerated type 'enum (unnamed}}
       break;
   }
 }
diff --git a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
index 1eb7e3a2dea8b..3d80794f44375 100644
--- a/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
+++ b/clang/test/SemaCXX/cxx0x-nontrivial-union.cpp
@@ -136,7 +136,7 @@ namespace pr16061 {
 
   template<typename T> struct Test2 {
     union {
-      struct {  // expected-note-re {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field 'struct (anonymous struct at{{.+}})' has a non-trivial default constructor}}
+      struct {  // expected-note-re {{default constructor of 'Test2<pr16061::X>' is implicitly deleted because variant field 'struct (anonymous at{{.+}})' has a non-trivial default constructor}}
         T x;
       };
     };
diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp
index 158a3a66deb47..6425f1ee7796e 100644
--- a/clang/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp
@@ -105,7 +105,7 @@ void enclosing() {
 void bitfield() {
   struct { int a : 3, : 4, b : 5; } a;
   auto &[x, y] = a;
-  auto &[p, q, r] = a; // expected-error-re {{type 'struct (unnamed struct at {{.*}})' binds to 2 elements, but 3 names were provided}}
+  auto &[p, q, r] = a; // expected-error-re {{type 'struct (unnamed at {{.*}})' binds to 2 elements, but 3 names were provided}}
 }
 
 void for_range() {
diff --git a/clang/unittests/Tooling/QualTypeNamesTest.cpp b/clang/unittests/Tooling/QualTypeNamesTest.cpp
index 1139392983fce..3dfc94a9d27de 100644
--- a/clang/unittests/Tooling/QualTypeNamesTest.cpp
+++ b/clang/unittests/Tooling/QualTypeNamesTest.cpp
@@ -361,14 +361,14 @@ TEST(QualTypeNameTest, AnonStrucs) {
   TypeNameVisitor AnonStrucs;
   AnonStrucs.ExpectedQualTypeNames["a"] = "short";
   AnonStrucs.ExpectedQualTypeNames["un_in_st_1"] =
-      "union (unnamed struct at input.cc:1:1)::(unnamed union at "
+      "union (unnamed struct at input.cc:1:1)::(unnamed at "
       "input.cc:2:27)";
   AnonStrucs.ExpectedQualTypeNames["b"] = "short";
   AnonStrucs.ExpectedQualTypeNames["un_in_st_2"] =
-      "union (unnamed struct at input.cc:1:1)::(unnamed union at "
+      "union (unnamed struct at input.cc:1:1)::(unnamed at "
       "input.cc:5:27)";
   AnonStrucs.ExpectedQualTypeNames["anon_st"] =
-      "struct (unnamed struct at input.cc:1:1)";
+      "struct (unnamed at input.cc:1:1)";
   AnonStrucs.runOver(R"(struct {
                           union {
                             short a;

>From 700ea0da8f51d3fcaff8640e5b08eb58473c6579 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 5 Dec 2025 15:10:42 +0800
Subject: [PATCH 09/16] [clang][TypePrinter][NFC] Turn SuppressTagKeyword into
 an enum

In preparation for a follow-up patch that adds a new mode to this enum.

(cherry picked from commit 8fd09a8bfca3658e47a28a486e6a5fa94acf5bf4)
---
 .../performance/MoveConstArgCheck.cpp         |  3 +-
 .../StaticAccessedThroughInstanceCheck.cpp    |  3 +-
 .../clang-tidy/utils/Matchers.cpp             |  3 +-
 clang-tools-extra/clangd/AST.cpp              |  3 +-
 clang-tools-extra/clangd/Hover.cpp            |  5 +-
 clang/include/clang/AST/PrettyPrinter.h       | 10 +-
 clang/lib/AST/Expr.cpp                        |  5 +-
 clang/lib/AST/InferAlloc.cpp                  |  3 +-
 clang/lib/AST/NestedNameSpecifier.cpp         |  3 +-
 clang/lib/AST/TypePrinter.cpp                 | 14 ++-
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         |  3 +-
 clang/lib/Index/USRGeneration.cpp             |  3 +-
 clang/tools/libclang/CIndex.cpp               | 11 ++-
 clang/unittests/AST/DeclPrinterTest.cpp       | 91 +++++++++++--------
 clang/unittests/AST/TypePrinterTest.cpp       | 11 ++-
 .../Clang/ClangExpressionParser.cpp           |  3 +-
 .../TypeSystem/Clang/TypeSystemClang.cpp      |  6 +-
 17 files changed, 114 insertions(+), 66 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
index 4d26c39fcbd18..5aa25e44d8735 100644
--- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
@@ -187,7 +187,8 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
 
       QualType NoRefType = (*InvocationParmType)->getPointeeType();
       PrintingPolicy PolicyWithSuppressedTag(getLangOpts());
-      PolicyWithSuppressedTag.SuppressTagKeyword = true;
+      PolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
+          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
       PolicyWithSuppressedTag.SuppressUnwrittenScope = true;
       std::string ExpectParmTypeName =
           NoRefType.getAsString(PolicyWithSuppressedTag);
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index 7ef8ef3d947f3..6acbb9bf12fa6 100644
--- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -72,7 +72,8 @@ void StaticAccessedThroughInstanceCheck::check(
 
   const ASTContext *AstContext = Result.Context;
   PrintingPolicy PrintingPolicyWithSuppressedTag(AstContext->getLangOpts());
-  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
+  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
 
   PrintingPolicyWithSuppressedTag.PrintAsCanonical =
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index b1591fb8e3619..6d6ca0b36335e 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -35,7 +35,8 @@ bool MatchesAnyListedTypeNameMatcher::matches(
   PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes;
   PrintingPolicyWithSuppressedTag.FullyQualifiedName = true;
   PrintingPolicyWithSuppressedTag.SuppressScope = false;
-  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
+  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
   std::string TypeName =
       Node.getUnqualifiedType().getAsString(PrintingPolicyWithSuppressedTag);
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index 0dcff2eae05e7..a4677efe63b7a 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -419,7 +419,8 @@ std::string printType(const QualType QT, const DeclContext &CurContext,
   std::string Result;
   llvm::raw_string_ostream OS(Result);
   PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
-  PP.SuppressTagKeyword = true;
+  PP.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   PP.SuppressUnwrittenScope = true;
   PP.FullyQualifiedName = FullyQualify;
 
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 34369e188d4ec..b00eb5c8ed9d4 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -176,7 +176,10 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   // tag for extra clarity. This isn't very idiomatic, so don't attempt it for
   // complex cases, including pointers/references, template specializations,
   // etc.
-  if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) {
+  if (!QT.isNull() && !QT.hasQualifiers() &&
+      PP.SuppressTagKeyword ==
+          llvm::to_underlying(
+              PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
         TT && TT->isCanonicalUnqualified())
       OS << TT->getDecl()->getKindName() << " ";
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index fb679e50a2d68..806fd207fc789 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -57,11 +57,14 @@ class PrintingCallbacks {
 /// It is very frequently copied.
 struct PrintingPolicy {
   enum class SuppressInlineNamespaceMode : uint8_t { None, Redundant, All };
+  enum class SuppressTagKeywordMode : uint8_t { None, InElaboratedNames };
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
       : Indentation(2), SuppressSpecifiers(false),
-        SuppressTagKeyword(LO.CPlusPlus),
+        SuppressTagKeyword(llvm::to_underlying(
+            LO.CPlusPlus ? SuppressTagKeywordMode::InElaboratedNames
+                         : SuppressTagKeywordMode::None)),
         SuppressTagKeywordInAnonymousTagNames(false),
         IncludeTagDefinition(false), SuppressScope(false),
         SuppressUnwrittenScope(false),
@@ -90,7 +93,8 @@ struct PrintingPolicy {
   /// construct). This should not be used if a real LangOptions object is
   /// available.
   void adjustForCPlusPlus() {
-    SuppressTagKeyword = true;
+    SuppressTagKeyword =
+        llvm::to_underlying(SuppressTagKeywordMode::InElaboratedNames);
     Bool = true;
     UseVoidForZeroParams = false;
   }
@@ -123,7 +127,7 @@ struct PrintingPolicy {
   /// \code
   /// struct Geometry::Point;
   /// \endcode
-  LLVM_PREFERRED_TYPE(bool)
+  LLVM_PREFERRED_TYPE(SuppressTagKeywordMode)
   unsigned SuppressTagKeyword : 1;
   unsigned SuppressTagKeywordInAnonymousTagNames : 1;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index ca7f3e16a9276..426733785850a 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -759,7 +759,10 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
     if (IK == PredefinedIdentKind::Function && ForceElaboratedPrinting)
-      Policy.SuppressTagKeyword = !LO.MSVCCompat;
+      Policy.SuppressTagKeyword = llvm::to_underlying(
+          LO.MSVCCompat
+              ? PrintingPolicy::SuppressTagKeywordMode::None
+              : PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
diff --git a/clang/lib/AST/InferAlloc.cpp b/clang/lib/AST/InferAlloc.cpp
index e439ed4dbb386..b161fab6ca3f5 100644
--- a/clang/lib/AST/InferAlloc.cpp
+++ b/clang/lib/AST/InferAlloc.cpp
@@ -184,7 +184,8 @@ infer_alloc::getAllocTokenMetadata(QualType T, const ASTContext &Ctx) {
 
   // Get unique type name.
   PrintingPolicy Policy(Ctx.getLangOpts());
-  Policy.SuppressTagKeyword = true;
+  Policy.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   Policy.FullyQualifiedName = true;
   llvm::raw_svector_ostream TypeNameOS(ATMD.TypeName);
   T.getCanonicalType().print(TypeNameOS, Policy);
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index c6af91f5c0083..2a227f31026d8 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -111,7 +111,8 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
     break;
   case Kind::Type: {
     PrintingPolicy InnerPolicy(Policy);
-    InnerPolicy.SuppressTagKeyword = true;
+    InnerPolicy.SuppressTagKeyword = llvm::to_underlying(
+        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
     QualType(getAsType(), 0).print(OS, InnerPolicy);
     break;
   }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 61c27782c7468..3ada671a48cfc 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -93,19 +93,21 @@ class DefaultTemplateArgsPolicyRAII {
 
 class ElaboratedTypePolicyRAII {
   PrintingPolicy &Policy;
-  bool SuppressTagKeyword;
+  PrintingPolicy::SuppressTagKeywordMode SuppressTagKeyword;
   bool SuppressScope;
 
 public:
   explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
-    SuppressTagKeyword = Policy.SuppressTagKeyword;
+    SuppressTagKeyword = static_cast<PrintingPolicy::SuppressTagKeywordMode>(
+        Policy.SuppressTagKeyword);
     SuppressScope = Policy.SuppressScope;
-    Policy.SuppressTagKeyword = true;
+    Policy.SuppressTagKeyword = llvm::to_underlying(
+        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
     Policy.SuppressScope = true;
   }
 
   ~ElaboratedTypePolicyRAII() {
-    Policy.SuppressTagKeyword = SuppressTagKeyword;
+    Policy.SuppressTagKeyword = llvm::to_underlying(SuppressTagKeyword);
     Policy.SuppressScope = SuppressScope;
   }
 };
@@ -1521,7 +1523,9 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
   bool PrintedKindDecoration = false;
   if (T->isCanonicalUnqualified()) {
-    if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
+    if (Policy.SuppressTagKeyword ==
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None) &&
+        !D->getTypedefNameForAnonDecl()) {
       PrintedKindDecoration = true;
       OS << D->getKindName();
       OS << ' ';
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 24b106b4bcee7..3cdcad7dfa75d 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -101,7 +101,8 @@ std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
       llvm::to_underlying(PrintingPolicy::SuppressInlineNamespaceMode::None);
   policy.AlwaysIncludeTypeForTemplateArgument = true;
   policy.PrintAsCanonical = true;
-  policy.SuppressTagKeyword = true;
+  policy.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
 
   if (recordDecl->getIdentifier())
     QualType(astContext.getCanonicalTagType(recordDecl))
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index 08835ea786997..d7c5a813e660d 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -656,7 +656,8 @@ static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
                            NestedNameSpecifier NNS) {
   // FIXME: Encode the qualifier, don't just print it.
   PrintingPolicy PO(LangOpts);
-  PO.SuppressTagKeyword = true;
+  PO.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   PO.SuppressUnwrittenScope = true;
   PO.ConstantArraySizeAsWritten = false;
   PO.AnonymousTagLocations = false;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 32e84248c1b27..6b17c02b21ffa 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5342,7 +5342,8 @@ CXString clang_getCursorSpelling(CXCursor C) {
 
       PrintingPolicy Policy = Ctx.getPrintingPolicy();
       Policy.FullyQualifiedName = true;
-      Policy.SuppressTagKeyword = false;
+      Policy.SuppressTagKeyword =
+          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
       return cxstring::createDup(T.getAsString(Policy));
     }
     case CXCursor_TemplateRef: {
@@ -5642,7 +5643,9 @@ clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
   case CXPrintingPolicy_SuppressSpecifiers:
     return P->SuppressSpecifiers;
   case CXPrintingPolicy_SuppressTagKeyword:
-    return P->SuppressTagKeyword;
+    return P->SuppressTagKeyword ==
+           llvm::to_underlying(
+               PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   case CXPrintingPolicy_IncludeTagDefinition:
     return P->IncludeTagDefinition;
   case CXPrintingPolicy_SuppressScope:
@@ -5710,7 +5713,9 @@ void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
     P->SuppressSpecifiers = Value;
     return;
   case CXPrintingPolicy_SuppressTagKeyword:
-    P->SuppressTagKeyword = Value;
+    P->SuppressTagKeyword = llvm::to_underlying(
+        Value ? PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames
+              : PrintingPolicy::SuppressTagKeywordMode::None);
     return;
   case CXPrintingPolicy_IncludeTagDefinition:
     P->IncludeTagDefinition = Value;
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index a412a9813b470..4649994bf4b5b 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -356,40 +356,44 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl12) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
-                                      "namespace NS { class C {};}"
-                                      "void foo() {using namespace NS; C c;}",
-                                      "foo",
-                                      "void foo() {\nusing namespace NS;\n"
-                                      "C c;\n}\n",
-                                      [](PrintingPolicy &Policy) {
-                                        Policy.SuppressTagKeyword = false;
-                                        Policy.SuppressScope = true;
-                                        Policy.TerseOutput = false;
-                                      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct S { int x; };"
+      "namespace NS { class C {};}"
+      "void foo() {using namespace NS; C c;}",
+      "foo",
+      "void foo() {\nusing namespace NS;\n"
+      "C c;\n}\n",
+      [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+        Policy.SuppressScope = true;
+        Policy.TerseOutput = false;
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl13) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
-                                      "S s1;"
-                                      "S foo() {return s1;}",
-                                      "foo", "S foo() {\nreturn s1;\n}\n",
-                                      [](PrintingPolicy &Policy) {
-                                        Policy.SuppressTagKeyword = false;
-                                        Policy.SuppressScope = true;
-                                        Policy.TerseOutput = false;
-                                      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct S { int x; };"
+      "S s1;"
+      "S foo() {return s1;}",
+      "foo", "S foo() {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+        Policy.SuppressScope = true;
+        Policy.TerseOutput = false;
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl14) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
-                                      "S foo(S s1) {return s1;}",
-                                      "foo", "S foo(S s1) {\nreturn s1;\n}\n",
-                                      [](PrintingPolicy &Policy) {
-                                        Policy.SuppressTagKeyword = false;
-                                        Policy.SuppressScope = true;
-                                        Policy.TerseOutput = false;
-                                      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches(
+      "struct S { int x; };"
+      "S foo(S s1) {return s1;}",
+      "foo", "S foo(S s1) {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+        Policy.SuppressScope = true;
+        Policy.TerseOutput = false;
+      }));
 }
 TEST(DeclPrinter, TestCXXRecordDecl15) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
@@ -400,7 +404,8 @@ TEST(DeclPrinter, TestCXXRecordDecl15) {
       "S foo(S s1, NS::C c1) {\nusing namespace NS;\n"
       "C c;\nreturn s1;\n}\n",
       [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword = false;
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
         Policy.SuppressScope = true;
         Policy.TerseOutput = false;
       }));
@@ -1385,8 +1390,10 @@ TEST(DeclPrinter, TestCXXRecordDecl17) {
       "template<typename T> struct Z {};"
       "struct X {};"
       "Z<X> A;",
-      "A", "Z<X> A",
-      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
+      "A", "Z<X> A", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl18) {
@@ -1397,8 +1404,10 @@ TEST(DeclPrinter, TestCXXRecordDecl18) {
       "template <typename T1, int>"
       "struct Y{};"
       "Y<Z<X>, 2> B;",
-      "B", "Y<Z<X>, 2> B",
-      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
+      "B", "Y<Z<X>, 2> B", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl19) {
@@ -1409,8 +1418,10 @@ TEST(DeclPrinter, TestCXXRecordDecl19) {
       "template <typename T1, int>"
       "struct Y{};"
       "Y<Z<X>, 2> B;",
-      "B", "Y<Z<X>, 2> B",
-      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }));
+      "B", "Y<Z<X>, 2> B", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword = llvm::to_underlying(
+            PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl20) {
@@ -1430,7 +1441,10 @@ TEST(DeclPrinter, TestCXXRecordDecl20) {
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);",
       "nestedInstance",
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)",
-      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
+      [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl21) {
@@ -1450,7 +1464,10 @@ TEST(DeclPrinter, TestCXXRecordDecl21) {
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);",
       "nestedInstance",
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)",
-      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }));
+      [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword = llvm::to_underlying(
+            PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+      }));
 }
 
 TEST(DeclPrinter, TestFunctionParamUglified) {
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index de4cfa4074eba..1afa2741ce750 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -161,11 +161,12 @@ TEST(TypePrinter, TemplateArgumentsSubstitution) {
        }
   )cpp";
   auto Matcher = typedefNameDecl(hasName("A"), hasType(qualType().bind("id")));
-  ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "X<int>",
-                                 [](PrintingPolicy &Policy) {
-                                   Policy.SuppressTagKeyword = false;
-                                   Policy.SuppressScope = true;
-                                 }));
+  ASSERT_TRUE(PrintedTypeMatches(
+      Code, {}, Matcher, "X<int>", [](PrintingPolicy &Policy) {
+        Policy.SuppressTagKeyword =
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+        Policy.SuppressScope = true;
+      }));
 }
 
 TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index bae3c44e333b6..8199846c8ff5a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1000,7 +1000,8 @@ class CodeComplete : public CodeCompleteConsumer {
     // Ensure that the printing policy is producing a description that is as
     // short as possible.
     m_desc_policy.SuppressScope = true;
-    m_desc_policy.SuppressTagKeyword = true;
+    m_desc_policy.SuppressTagKeyword = llvm::to_underlying(
+        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
     m_desc_policy.FullyQualifiedName = false;
     m_desc_policy.TerseOutput = true;
     m_desc_policy.IncludeNewlines = false;
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 2cb4a46130c84..5caf89d4c24f3 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2146,7 +2146,8 @@ TypeSystemClang::GetDeclarationName(llvm::StringRef name,
 
 PrintingPolicy TypeSystemClang::GetTypePrintingPolicy() {
   clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
-  printing_policy.SuppressTagKeyword = true;
+  printing_policy.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   // Inline namespaces are important for some type formatters (e.g., libc++
   // and libstdc++ are differentiated by their inline namespaces).
   printing_policy.SuppressInlineNamespace =
@@ -3868,7 +3869,8 @@ TypeSystemClang::GetDisplayTypeName(lldb::opaque_compiler_type_t type) {
 
   clang::QualType qual_type(GetQualType(type));
   clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
-  printing_policy.SuppressTagKeyword = true;
+  printing_policy.SuppressTagKeyword = llvm::to_underlying(
+      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
   printing_policy.SuppressScope = false;
   printing_policy.SuppressUnwrittenScope = true;
   // FIXME: should we suppress "All" inline namespaces?

>From db33841a523f11c1999a40c922f039d6fd01ad52 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 5 Dec 2025 16:47:25 +0800
Subject: [PATCH 10/16] fixup! turn SuppressTagKeywordInAnonymousTagNames into
 an SuppressTagKeyword enum case

---
 clang-tools-extra/clangd/Hover.cpp      |  2 +-
 clang/include/clang/AST/PrettyPrinter.h | 11 +++++++----
 clang/lib/AST/Decl.cpp                  | 15 +++++++++++----
 clang/lib/AST/TypePrinter.cpp           | 12 ++++++------
 4 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index b00eb5c8ed9d4..f745a680908fe 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -177,7 +177,7 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   // complex cases, including pointers/references, template specializations,
   // etc.
   if (!QT.isNull() && !QT.hasQualifiers() &&
-      PP.SuppressTagKeyword ==
+      PP.SuppressTagKeyword >=
           llvm::to_underlying(
               PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 806fd207fc789..060a086ae4cad 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -57,7 +57,12 @@ class PrintingCallbacks {
 /// It is very frequently copied.
 struct PrintingPolicy {
   enum class SuppressInlineNamespaceMode : uint8_t { None, Redundant, All };
-  enum class SuppressTagKeywordMode : uint8_t { None, InElaboratedNames };
+  enum class SuppressTagKeywordMode : uint8_t {
+    None,
+    InAnonNames,
+    InElaboratedNames,
+    All
+  };
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
@@ -65,7 +70,6 @@ struct PrintingPolicy {
         SuppressTagKeyword(llvm::to_underlying(
             LO.CPlusPlus ? SuppressTagKeywordMode::InElaboratedNames
                          : SuppressTagKeywordMode::None)),
-        SuppressTagKeywordInAnonymousTagNames(false),
         IncludeTagDefinition(false), SuppressScope(false),
         SuppressUnwrittenScope(false),
         SuppressInlineNamespace(
@@ -128,8 +132,7 @@ struct PrintingPolicy {
   /// struct Geometry::Point;
   /// \endcode
   LLVM_PREFERRED_TYPE(SuppressTagKeywordMode)
-  unsigned SuppressTagKeyword : 1;
-  unsigned SuppressTagKeywordInAnonymousTagNames : 1;
+  unsigned SuppressTagKeyword : 2;
 
   /// When true, include the body of a tag definition.
   ///
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index ce29ba49b03d0..1e5345594a4ef 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1799,8 +1799,8 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
       //
       // I.e., suppress tag locations, suppress leading keyword, *don't*
       // suppress tag in name
-      Copy.SuppressTagKeyword = true;
-      Copy.SuppressTagKeywordInAnonymousTagNames = false;
+      Copy.SuppressTagKeyword = llvm::to_underlying(
+          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
       Copy.AnonymousTagLocations = false;
       RD->printName(OS, Copy);
     } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
@@ -4969,11 +4969,18 @@ void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS,
     return;
   }
 
-  bool SuppressTagKeywordInName = Policy.SuppressTagKeywordInAnonymousTagNames;
+  bool SuppressTagKeywordInName =
+      (Policy.SuppressTagKeyword ==
+       llvm::to_underlying(
+           PrintingPolicy::SuppressTagKeywordMode::InAnonNames)) ||
+      (Policy.SuppressTagKeyword ==
+       llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All));
 
   // Emit leading keyword. Since we printed a leading keyword make sure we
   // don't print the tag as part of the name too.
-  if (!Policy.SuppressTagKeyword) {
+  if (Policy.SuppressTagKeyword <
+      llvm::to_underlying(
+          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
     OS << getKindName() << ' ';
     SuppressTagKeywordInName = true;
   }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 3ada671a48cfc..4f9e8b60d66a4 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1523,8 +1523,9 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
   bool PrintedKindDecoration = false;
   if (T->isCanonicalUnqualified()) {
-    if (Policy.SuppressTagKeyword ==
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None) &&
+    if (Policy.SuppressTagKeyword <
+            llvm::to_underlying(
+                PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames) &&
         !D->getTypedefNameForAnonDecl()) {
       PrintedKindDecoration = true;
       OS << D->getKindName();
@@ -1553,10 +1554,9 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
     clang::PrintingPolicy Copy(Policy);
 
     // Suppress the redundant tag keyword if we just printed one.
-    if (PrintedKindDecoration) {
-      Copy.SuppressTagKeywordInAnonymousTagNames = true;
-      Copy.SuppressTagKeyword = true;
-    }
+    if (PrintedKindDecoration)
+      Copy.SuppressTagKeyword =
+          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All);
 
     D->printName(OS, Copy);
   }

>From e51a03b2b29ebc2b53beb5643f97d3d3eccc313d Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 5 Dec 2025 16:49:08 +0800
Subject: [PATCH 11/16] fixup! remove redundant headers

---
 clang/lib/AST/Decl.cpp                        | 1 -
 clang/lib/AST/TypePrinter.cpp                 | 1 -
 clang/lib/ASTMatchers/ASTMatchersInternal.cpp | 1 -
 3 files changed, 3 deletions(-)

diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1e5345594a4ef..1edbe58769849 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -35,7 +35,6 @@
 #include "clang/AST/Stmt.h"
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/Type.h"
-#include "clang/AST/TypeBase.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/Basic/IdentifierTable.h"
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 4f9e8b60d66a4..0b2b1c0df0d84 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -23,7 +23,6 @@
 #include "clang/AST/TemplateBase.h"
 #include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
-#include "clang/AST/TypeBase.h"
 #include "clang/Basic/AddressSpaces.h"
 #include "clang/Basic/AttrKinds.h"
 #include "clang/Basic/ExceptionSpecificationType.h"
diff --git a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
index 965f766170957..31496f992d34b 100644
--- a/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
+++ b/clang/lib/ASTMatchers/ASTMatchersInternal.cpp
@@ -18,7 +18,6 @@
 #include "clang/AST/ExprConcepts.h"
 #include "clang/AST/ParentMapContext.h"
 #include "clang/AST/PrettyPrinter.h"
-#include "clang/AST/TypeBase.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Lex/Lexer.h"

>From f7d07a2cf532f135b8f27e6b60a61aecac730a0b Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Mon, 8 Dec 2025 19:40:56 +0800
Subject: [PATCH 12/16] fixup! Set SuppressTagKeywordMode::InAnonNames on Hover

---
 clang-tools-extra/clangd/Hover.cpp                | 10 +++++++---
 clang-tools-extra/clangd/unittests/HoverTests.cpp |  2 +-
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index f745a680908fe..82d0cb0f018ee 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -176,22 +176,26 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   // tag for extra clarity. This isn't very idiomatic, so don't attempt it for
   // complex cases, including pointers/references, template specializations,
   // etc.
+  PrintingPolicy Copy(PP);
   if (!QT.isNull() && !QT.hasQualifiers() &&
       PP.SuppressTagKeyword >=
           llvm::to_underlying(
               PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
-        TT && TT->isCanonicalUnqualified())
+        TT && TT->isCanonicalUnqualified()) {
+      Copy.SuppressTagKeyword =
+          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All);
       OS << TT->getDecl()->getKindName() << " ";
+    }
   }
-  QT.print(OS, PP);
+  QT.print(OS, Copy);
 
   const Config &Cfg = Config::current();
   if (!QT.isNull() && Cfg.Hover.ShowAKA) {
     bool ShouldAKA = false;
     QualType DesugaredTy = clang::desugarForDiagnostic(ASTCtx, QT, ShouldAKA);
     if (ShouldAKA)
-      Result.AKA = DesugaredTy.getAsString(PP);
+      Result.AKA = DesugaredTy.getAsString(Copy);
   }
   return Result;
 }
diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp
index 00fa14b32dd6c..eb858ff616e90 100644
--- a/clang-tools-extra/clangd/unittests/HoverTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp
@@ -2103,7 +2103,7 @@ TEST(Hover, All) {
             HI.NamespaceScope = "";
             // FIXME: This should be `(anon enum)::`
             HI.LocalScope = "";
-            HI.Type = "enum (unnamed enum)";
+            HI.Type = "enum (unnamed)";
             HI.Definition = "ONE";
             HI.Value = "0";
           }},

>From 2e811c8a84be02d7c28ac466afe6568b392c0a11 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 9 Dec 2025 14:55:18 +0000
Subject: [PATCH 13/16] Revert "fixup! turn
 SuppressTagKeywordInAnonymousTagNames into an SuppressTagKeyword enum case"

This reverts commit db33841a523f11c1999a40c922f039d6fd01ad52.
---
 clang-tools-extra/clangd/Hover.cpp      |  2 +-
 clang/include/clang/AST/PrettyPrinter.h | 11 ++++-------
 clang/lib/AST/Decl.cpp                  | 15 ++++-----------
 clang/lib/AST/TypePrinter.cpp           | 12 ++++++------
 4 files changed, 15 insertions(+), 25 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 82d0cb0f018ee..1a7a545bd5bc0 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -178,7 +178,7 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   // etc.
   PrintingPolicy Copy(PP);
   if (!QT.isNull() && !QT.hasQualifiers() &&
-      PP.SuppressTagKeyword >=
+      PP.SuppressTagKeyword ==
           llvm::to_underlying(
               PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 060a086ae4cad..806fd207fc789 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -57,12 +57,7 @@ class PrintingCallbacks {
 /// It is very frequently copied.
 struct PrintingPolicy {
   enum class SuppressInlineNamespaceMode : uint8_t { None, Redundant, All };
-  enum class SuppressTagKeywordMode : uint8_t {
-    None,
-    InAnonNames,
-    InElaboratedNames,
-    All
-  };
+  enum class SuppressTagKeywordMode : uint8_t { None, InElaboratedNames };
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
@@ -70,6 +65,7 @@ struct PrintingPolicy {
         SuppressTagKeyword(llvm::to_underlying(
             LO.CPlusPlus ? SuppressTagKeywordMode::InElaboratedNames
                          : SuppressTagKeywordMode::None)),
+        SuppressTagKeywordInAnonymousTagNames(false),
         IncludeTagDefinition(false), SuppressScope(false),
         SuppressUnwrittenScope(false),
         SuppressInlineNamespace(
@@ -132,7 +128,8 @@ struct PrintingPolicy {
   /// struct Geometry::Point;
   /// \endcode
   LLVM_PREFERRED_TYPE(SuppressTagKeywordMode)
-  unsigned SuppressTagKeyword : 2;
+  unsigned SuppressTagKeyword : 1;
+  unsigned SuppressTagKeywordInAnonymousTagNames : 1;
 
   /// When true, include the body of a tag definition.
   ///
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1edbe58769849..1728d06ce3306 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1798,8 +1798,8 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
       //
       // I.e., suppress tag locations, suppress leading keyword, *don't*
       // suppress tag in name
-      Copy.SuppressTagKeyword = llvm::to_underlying(
-          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+      Copy.SuppressTagKeyword = true;
+      Copy.SuppressTagKeywordInAnonymousTagNames = false;
       Copy.AnonymousTagLocations = false;
       RD->printName(OS, Copy);
     } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
@@ -4968,18 +4968,11 @@ void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS,
     return;
   }
 
-  bool SuppressTagKeywordInName =
-      (Policy.SuppressTagKeyword ==
-       llvm::to_underlying(
-           PrintingPolicy::SuppressTagKeywordMode::InAnonNames)) ||
-      (Policy.SuppressTagKeyword ==
-       llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All));
+  bool SuppressTagKeywordInName = Policy.SuppressTagKeywordInAnonymousTagNames;
 
   // Emit leading keyword. Since we printed a leading keyword make sure we
   // don't print the tag as part of the name too.
-  if (Policy.SuppressTagKeyword <
-      llvm::to_underlying(
-          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
+  if (!Policy.SuppressTagKeyword) {
     OS << getKindName() << ' ';
     SuppressTagKeywordInName = true;
   }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 0b2b1c0df0d84..3a272810443c3 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1522,9 +1522,8 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
   bool PrintedKindDecoration = false;
   if (T->isCanonicalUnqualified()) {
-    if (Policy.SuppressTagKeyword <
-            llvm::to_underlying(
-                PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames) &&
+    if (Policy.SuppressTagKeyword ==
+            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None) &&
         !D->getTypedefNameForAnonDecl()) {
       PrintedKindDecoration = true;
       OS << D->getKindName();
@@ -1553,9 +1552,10 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
     clang::PrintingPolicy Copy(Policy);
 
     // Suppress the redundant tag keyword if we just printed one.
-    if (PrintedKindDecoration)
-      Copy.SuppressTagKeyword =
-          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All);
+    if (PrintedKindDecoration) {
+      Copy.SuppressTagKeywordInAnonymousTagNames = true;
+      Copy.SuppressTagKeyword = true;
+    }
 
     D->printName(OS, Copy);
   }

>From 6371c5c95c89dcab718e003e7a471271f29f948f Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 9 Dec 2025 14:56:24 +0000
Subject: [PATCH 14/16] Revert "[clang][TypePrinter][NFC] Turn
 SuppressTagKeyword into an enum"

This reverts commit 700ea0da8f51d3fcaff8640e5b08eb58473c6579.
---
 .../performance/MoveConstArgCheck.cpp         |  3 +-
 .../StaticAccessedThroughInstanceCheck.cpp    |  3 +-
 .../clang-tidy/utils/Matchers.cpp             |  3 +-
 clang-tools-extra/clangd/AST.cpp              |  3 +-
 clang-tools-extra/clangd/Hover.cpp            |  8 +-
 clang/include/clang/AST/PrettyPrinter.h       | 10 +-
 clang/lib/AST/Expr.cpp                        |  5 +-
 clang/lib/AST/InferAlloc.cpp                  |  3 +-
 clang/lib/AST/NestedNameSpecifier.cpp         |  3 +-
 clang/lib/AST/TypePrinter.cpp                 | 14 +--
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         |  3 +-
 clang/lib/Index/USRGeneration.cpp             |  3 +-
 clang/tools/libclang/CIndex.cpp               | 11 +--
 clang/unittests/AST/DeclPrinterTest.cpp       | 91 ++++++++-----------
 clang/unittests/AST/TypePrinterTest.cpp       | 11 +--
 .../Clang/ClangExpressionParser.cpp           |  3 +-
 .../TypeSystem/Clang/TypeSystemClang.cpp      |  6 +-
 17 files changed, 67 insertions(+), 116 deletions(-)

diff --git a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
index 5aa25e44d8735..4d26c39fcbd18 100644
--- a/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
+++ b/clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp
@@ -187,8 +187,7 @@ void MoveConstArgCheck::check(const MatchFinder::MatchResult &Result) {
 
       QualType NoRefType = (*InvocationParmType)->getPointeeType();
       PrintingPolicy PolicyWithSuppressedTag(getLangOpts());
-      PolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
-          PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+      PolicyWithSuppressedTag.SuppressTagKeyword = true;
       PolicyWithSuppressedTag.SuppressUnwrittenScope = true;
       std::string ExpectParmTypeName =
           NoRefType.getAsString(PolicyWithSuppressedTag);
diff --git a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
index 6acbb9bf12fa6..7ef8ef3d947f3 100644
--- a/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/StaticAccessedThroughInstanceCheck.cpp
@@ -72,8 +72,7 @@ void StaticAccessedThroughInstanceCheck::check(
 
   const ASTContext *AstContext = Result.Context;
   PrintingPolicy PrintingPolicyWithSuppressedTag(AstContext->getLangOpts());
-  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
   PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
 
   PrintingPolicyWithSuppressedTag.PrintAsCanonical =
diff --git a/clang-tools-extra/clang-tidy/utils/Matchers.cpp b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
index 6d6ca0b36335e..b1591fb8e3619 100644
--- a/clang-tools-extra/clang-tidy/utils/Matchers.cpp
+++ b/clang-tools-extra/clang-tidy/utils/Matchers.cpp
@@ -35,8 +35,7 @@ bool MatchesAnyListedTypeNameMatcher::matches(
   PrintingPolicyWithSuppressedTag.PrintAsCanonical = CanonicalTypes;
   PrintingPolicyWithSuppressedTag.FullyQualifiedName = true;
   PrintingPolicyWithSuppressedTag.SuppressScope = false;
-  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  PrintingPolicyWithSuppressedTag.SuppressTagKeyword = true;
   PrintingPolicyWithSuppressedTag.SuppressUnwrittenScope = true;
   std::string TypeName =
       Node.getUnqualifiedType().getAsString(PrintingPolicyWithSuppressedTag);
diff --git a/clang-tools-extra/clangd/AST.cpp b/clang-tools-extra/clangd/AST.cpp
index a4677efe63b7a..0dcff2eae05e7 100644
--- a/clang-tools-extra/clangd/AST.cpp
+++ b/clang-tools-extra/clangd/AST.cpp
@@ -419,8 +419,7 @@ std::string printType(const QualType QT, const DeclContext &CurContext,
   std::string Result;
   llvm::raw_string_ostream OS(Result);
   PrintingPolicy PP(CurContext.getParentASTContext().getPrintingPolicy());
-  PP.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  PP.SuppressTagKeyword = true;
   PP.SuppressUnwrittenScope = true;
   PP.FullyQualifiedName = FullyQualify;
 
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 1a7a545bd5bc0..8c7d397a9e756 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -177,14 +177,10 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   // complex cases, including pointers/references, template specializations,
   // etc.
   PrintingPolicy Copy(PP);
-  if (!QT.isNull() && !QT.hasQualifiers() &&
-      PP.SuppressTagKeyword ==
-          llvm::to_underlying(
-              PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames)) {
+  if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
         TT && TT->isCanonicalUnqualified()) {
-      Copy.SuppressTagKeyword =
-          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::All);
+      Copy.SuppressTagKeywordInAnonymousTagNames = true;
       OS << TT->getDecl()->getKindName() << " ";
     }
   }
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index 806fd207fc789..fb679e50a2d68 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -57,14 +57,11 @@ class PrintingCallbacks {
 /// It is very frequently copied.
 struct PrintingPolicy {
   enum class SuppressInlineNamespaceMode : uint8_t { None, Redundant, All };
-  enum class SuppressTagKeywordMode : uint8_t { None, InElaboratedNames };
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
       : Indentation(2), SuppressSpecifiers(false),
-        SuppressTagKeyword(llvm::to_underlying(
-            LO.CPlusPlus ? SuppressTagKeywordMode::InElaboratedNames
-                         : SuppressTagKeywordMode::None)),
+        SuppressTagKeyword(LO.CPlusPlus),
         SuppressTagKeywordInAnonymousTagNames(false),
         IncludeTagDefinition(false), SuppressScope(false),
         SuppressUnwrittenScope(false),
@@ -93,8 +90,7 @@ struct PrintingPolicy {
   /// construct). This should not be used if a real LangOptions object is
   /// available.
   void adjustForCPlusPlus() {
-    SuppressTagKeyword =
-        llvm::to_underlying(SuppressTagKeywordMode::InElaboratedNames);
+    SuppressTagKeyword = true;
     Bool = true;
     UseVoidForZeroParams = false;
   }
@@ -127,7 +123,7 @@ struct PrintingPolicy {
   /// \code
   /// struct Geometry::Point;
   /// \endcode
-  LLVM_PREFERRED_TYPE(SuppressTagKeywordMode)
+  LLVM_PREFERRED_TYPE(bool)
   unsigned SuppressTagKeyword : 1;
   unsigned SuppressTagKeywordInAnonymousTagNames : 1;
 
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 426733785850a..ca7f3e16a9276 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -759,10 +759,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
     PrettyCallbacks PrettyCB(Context.getLangOpts());
     Policy.Callbacks = &PrettyCB;
     if (IK == PredefinedIdentKind::Function && ForceElaboratedPrinting)
-      Policy.SuppressTagKeyword = llvm::to_underlying(
-          LO.MSVCCompat
-              ? PrintingPolicy::SuppressTagKeywordMode::None
-              : PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+      Policy.SuppressTagKeyword = !LO.MSVCCompat;
     std::string Proto;
     llvm::raw_string_ostream POut(Proto);
 
diff --git a/clang/lib/AST/InferAlloc.cpp b/clang/lib/AST/InferAlloc.cpp
index b161fab6ca3f5..e439ed4dbb386 100644
--- a/clang/lib/AST/InferAlloc.cpp
+++ b/clang/lib/AST/InferAlloc.cpp
@@ -184,8 +184,7 @@ infer_alloc::getAllocTokenMetadata(QualType T, const ASTContext &Ctx) {
 
   // Get unique type name.
   PrintingPolicy Policy(Ctx.getLangOpts());
-  Policy.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  Policy.SuppressTagKeyword = true;
   Policy.FullyQualifiedName = true;
   llvm::raw_svector_ostream TypeNameOS(ATMD.TypeName);
   T.getCanonicalType().print(TypeNameOS, Policy);
diff --git a/clang/lib/AST/NestedNameSpecifier.cpp b/clang/lib/AST/NestedNameSpecifier.cpp
index 2a227f31026d8..c6af91f5c0083 100644
--- a/clang/lib/AST/NestedNameSpecifier.cpp
+++ b/clang/lib/AST/NestedNameSpecifier.cpp
@@ -111,8 +111,7 @@ void NestedNameSpecifier::print(raw_ostream &OS, const PrintingPolicy &Policy,
     break;
   case Kind::Type: {
     PrintingPolicy InnerPolicy(Policy);
-    InnerPolicy.SuppressTagKeyword = llvm::to_underlying(
-        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+    InnerPolicy.SuppressTagKeyword = true;
     QualType(getAsType(), 0).print(OS, InnerPolicy);
     break;
   }
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index 3a272810443c3..d1b359605187a 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -92,21 +92,19 @@ class DefaultTemplateArgsPolicyRAII {
 
 class ElaboratedTypePolicyRAII {
   PrintingPolicy &Policy;
-  PrintingPolicy::SuppressTagKeywordMode SuppressTagKeyword;
+  bool SuppressTagKeyword;
   bool SuppressScope;
 
 public:
   explicit ElaboratedTypePolicyRAII(PrintingPolicy &Policy) : Policy(Policy) {
-    SuppressTagKeyword = static_cast<PrintingPolicy::SuppressTagKeywordMode>(
-        Policy.SuppressTagKeyword);
+    SuppressTagKeyword = Policy.SuppressTagKeyword;
     SuppressScope = Policy.SuppressScope;
-    Policy.SuppressTagKeyword = llvm::to_underlying(
-        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+    Policy.SuppressTagKeyword = true;
     Policy.SuppressScope = true;
   }
 
   ~ElaboratedTypePolicyRAII() {
-    Policy.SuppressTagKeyword = llvm::to_underlying(SuppressTagKeyword);
+    Policy.SuppressTagKeyword = SuppressTagKeyword;
     Policy.SuppressScope = SuppressScope;
   }
 };
@@ -1522,9 +1520,7 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
   bool PrintedKindDecoration = false;
   if (T->isCanonicalUnqualified()) {
-    if (Policy.SuppressTagKeyword ==
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None) &&
-        !D->getTypedefNameForAnonDecl()) {
+    if (!Policy.SuppressTagKeyword && !D->getTypedefNameForAnonDecl()) {
       PrintedKindDecoration = true;
       OS << D->getKindName();
       OS << ' ';
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 3cdcad7dfa75d..24b106b4bcee7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -101,8 +101,7 @@ std::string CIRGenTypes::getRecordTypeName(const clang::RecordDecl *recordDecl,
       llvm::to_underlying(PrintingPolicy::SuppressInlineNamespaceMode::None);
   policy.AlwaysIncludeTypeForTemplateArgument = true;
   policy.PrintAsCanonical = true;
-  policy.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  policy.SuppressTagKeyword = true;
 
   if (recordDecl->getIdentifier())
     QualType(astContext.getCanonicalTagType(recordDecl))
diff --git a/clang/lib/Index/USRGeneration.cpp b/clang/lib/Index/USRGeneration.cpp
index d7c5a813e660d..08835ea786997 100644
--- a/clang/lib/Index/USRGeneration.cpp
+++ b/clang/lib/Index/USRGeneration.cpp
@@ -656,8 +656,7 @@ static void printQualifier(llvm::raw_ostream &Out, const LangOptions &LangOpts,
                            NestedNameSpecifier NNS) {
   // FIXME: Encode the qualifier, don't just print it.
   PrintingPolicy PO(LangOpts);
-  PO.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  PO.SuppressTagKeyword = true;
   PO.SuppressUnwrittenScope = true;
   PO.ConstantArraySizeAsWritten = false;
   PO.AnonymousTagLocations = false;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 6b17c02b21ffa..32e84248c1b27 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5342,8 +5342,7 @@ CXString clang_getCursorSpelling(CXCursor C) {
 
       PrintingPolicy Policy = Ctx.getPrintingPolicy();
       Policy.FullyQualifiedName = true;
-      Policy.SuppressTagKeyword =
-          llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+      Policy.SuppressTagKeyword = false;
       return cxstring::createDup(T.getAsString(Policy));
     }
     case CXCursor_TemplateRef: {
@@ -5643,9 +5642,7 @@ clang_PrintingPolicy_getProperty(CXPrintingPolicy Policy,
   case CXPrintingPolicy_SuppressSpecifiers:
     return P->SuppressSpecifiers;
   case CXPrintingPolicy_SuppressTagKeyword:
-    return P->SuppressTagKeyword ==
-           llvm::to_underlying(
-               PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+    return P->SuppressTagKeyword;
   case CXPrintingPolicy_IncludeTagDefinition:
     return P->IncludeTagDefinition;
   case CXPrintingPolicy_SuppressScope:
@@ -5713,9 +5710,7 @@ void clang_PrintingPolicy_setProperty(CXPrintingPolicy Policy,
     P->SuppressSpecifiers = Value;
     return;
   case CXPrintingPolicy_SuppressTagKeyword:
-    P->SuppressTagKeyword = llvm::to_underlying(
-        Value ? PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames
-              : PrintingPolicy::SuppressTagKeywordMode::None);
+    P->SuppressTagKeyword = Value;
     return;
   case CXPrintingPolicy_IncludeTagDefinition:
     P->IncludeTagDefinition = Value;
diff --git a/clang/unittests/AST/DeclPrinterTest.cpp b/clang/unittests/AST/DeclPrinterTest.cpp
index 4649994bf4b5b..a412a9813b470 100644
--- a/clang/unittests/AST/DeclPrinterTest.cpp
+++ b/clang/unittests/AST/DeclPrinterTest.cpp
@@ -356,44 +356,40 @@ TEST(DeclPrinter, TestCXXRecordDecl11) {
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl12) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches(
-      "struct S { int x; };"
-      "namespace NS { class C {};}"
-      "void foo() {using namespace NS; C c;}",
-      "foo",
-      "void foo() {\nusing namespace NS;\n"
-      "C c;\n}\n",
-      [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-        Policy.SuppressScope = true;
-        Policy.TerseOutput = false;
-      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
+                                      "namespace NS { class C {};}"
+                                      "void foo() {using namespace NS; C c;}",
+                                      "foo",
+                                      "void foo() {\nusing namespace NS;\n"
+                                      "C c;\n}\n",
+                                      [](PrintingPolicy &Policy) {
+                                        Policy.SuppressTagKeyword = false;
+                                        Policy.SuppressScope = true;
+                                        Policy.TerseOutput = false;
+                                      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl13) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches(
-      "struct S { int x; };"
-      "S s1;"
-      "S foo() {return s1;}",
-      "foo", "S foo() {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-        Policy.SuppressScope = true;
-        Policy.TerseOutput = false;
-      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
+                                      "S s1;"
+                                      "S foo() {return s1;}",
+                                      "foo", "S foo() {\nreturn s1;\n}\n",
+                                      [](PrintingPolicy &Policy) {
+                                        Policy.SuppressTagKeyword = false;
+                                        Policy.SuppressScope = true;
+                                        Policy.TerseOutput = false;
+                                      }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl14) {
-  ASSERT_TRUE(PrintedDeclCXX98Matches(
-      "struct S { int x; };"
-      "S foo(S s1) {return s1;}",
-      "foo", "S foo(S s1) {\nreturn s1;\n}\n", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-        Policy.SuppressScope = true;
-        Policy.TerseOutput = false;
-      }));
+  ASSERT_TRUE(PrintedDeclCXX98Matches("struct S { int x; };"
+                                      "S foo(S s1) {return s1;}",
+                                      "foo", "S foo(S s1) {\nreturn s1;\n}\n",
+                                      [](PrintingPolicy &Policy) {
+                                        Policy.SuppressTagKeyword = false;
+                                        Policy.SuppressScope = true;
+                                        Policy.TerseOutput = false;
+                                      }));
 }
 TEST(DeclPrinter, TestCXXRecordDecl15) {
   ASSERT_TRUE(PrintedDeclCXX98Matches(
@@ -404,8 +400,7 @@ TEST(DeclPrinter, TestCXXRecordDecl15) {
       "S foo(S s1, NS::C c1) {\nusing namespace NS;\n"
       "C c;\nreturn s1;\n}\n",
       [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
+        Policy.SuppressTagKeyword = false;
         Policy.SuppressScope = true;
         Policy.TerseOutput = false;
       }));
@@ -1390,10 +1385,8 @@ TEST(DeclPrinter, TestCXXRecordDecl17) {
       "template<typename T> struct Z {};"
       "struct X {};"
       "Z<X> A;",
-      "A", "Z<X> A", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-      }));
+      "A", "Z<X> A",
+      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl18) {
@@ -1404,10 +1397,8 @@ TEST(DeclPrinter, TestCXXRecordDecl18) {
       "template <typename T1, int>"
       "struct Y{};"
       "Y<Z<X>, 2> B;",
-      "B", "Y<Z<X>, 2> B", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-      }));
+      "B", "Y<Z<X>, 2> B",
+      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl19) {
@@ -1418,10 +1409,8 @@ TEST(DeclPrinter, TestCXXRecordDecl19) {
       "template <typename T1, int>"
       "struct Y{};"
       "Y<Z<X>, 2> B;",
-      "B", "Y<Z<X>, 2> B", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword = llvm::to_underlying(
-            PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
-      }));
+      "B", "Y<Z<X>, 2> B",
+      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl20) {
@@ -1441,10 +1430,7 @@ TEST(DeclPrinter, TestCXXRecordDecl20) {
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);",
       "nestedInstance",
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)",
-      [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-      }));
+      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = false; }));
 }
 
 TEST(DeclPrinter, TestCXXRecordDecl21) {
@@ -1464,10 +1450,7 @@ TEST(DeclPrinter, TestCXXRecordDecl21) {
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100);",
       "nestedInstance",
       "Outer<Inner<int, 10>, 5>::NestedStruct nestedInstance(100)",
-      [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword = llvm::to_underlying(
-            PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
-      }));
+      [](PrintingPolicy &Policy) { Policy.SuppressTagKeyword = true; }));
 }
 
 TEST(DeclPrinter, TestFunctionParamUglified) {
diff --git a/clang/unittests/AST/TypePrinterTest.cpp b/clang/unittests/AST/TypePrinterTest.cpp
index 1afa2741ce750..de4cfa4074eba 100644
--- a/clang/unittests/AST/TypePrinterTest.cpp
+++ b/clang/unittests/AST/TypePrinterTest.cpp
@@ -161,12 +161,11 @@ TEST(TypePrinter, TemplateArgumentsSubstitution) {
        }
   )cpp";
   auto Matcher = typedefNameDecl(hasName("A"), hasType(qualType().bind("id")));
-  ASSERT_TRUE(PrintedTypeMatches(
-      Code, {}, Matcher, "X<int>", [](PrintingPolicy &Policy) {
-        Policy.SuppressTagKeyword =
-            llvm::to_underlying(PrintingPolicy::SuppressTagKeywordMode::None);
-        Policy.SuppressScope = true;
-      }));
+  ASSERT_TRUE(PrintedTypeMatches(Code, {}, Matcher, "X<int>",
+                                 [](PrintingPolicy &Policy) {
+                                   Policy.SuppressTagKeyword = false;
+                                   Policy.SuppressScope = true;
+                                 }));
 }
 
 TEST(TypePrinter, TemplateArgumentsSubstitution_Expressions) {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
index 8199846c8ff5a..bae3c44e333b6 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp
@@ -1000,8 +1000,7 @@ class CodeComplete : public CodeCompleteConsumer {
     // Ensure that the printing policy is producing a description that is as
     // short as possible.
     m_desc_policy.SuppressScope = true;
-    m_desc_policy.SuppressTagKeyword = llvm::to_underlying(
-        PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+    m_desc_policy.SuppressTagKeyword = true;
     m_desc_policy.FullyQualifiedName = false;
     m_desc_policy.TerseOutput = true;
     m_desc_policy.IncludeNewlines = false;
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 5caf89d4c24f3..2cb4a46130c84 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -2146,8 +2146,7 @@ TypeSystemClang::GetDeclarationName(llvm::StringRef name,
 
 PrintingPolicy TypeSystemClang::GetTypePrintingPolicy() {
   clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
-  printing_policy.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  printing_policy.SuppressTagKeyword = true;
   // Inline namespaces are important for some type formatters (e.g., libc++
   // and libstdc++ are differentiated by their inline namespaces).
   printing_policy.SuppressInlineNamespace =
@@ -3869,8 +3868,7 @@ TypeSystemClang::GetDisplayTypeName(lldb::opaque_compiler_type_t type) {
 
   clang::QualType qual_type(GetQualType(type));
   clang::PrintingPolicy printing_policy(getASTContext().getPrintingPolicy());
-  printing_policy.SuppressTagKeyword = llvm::to_underlying(
-      PrintingPolicy::SuppressTagKeywordMode::InElaboratedNames);
+  printing_policy.SuppressTagKeyword = true;
   printing_policy.SuppressScope = false;
   printing_policy.SuppressUnwrittenScope = true;
   // FIXME: should we suppress "All" inline namespaces?

>From 73d41d4bd8505dc3f86ef12c850d37063cba99d9 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 9 Dec 2025 15:04:48 +0000
Subject: [PATCH 15/16] fixup! document SuppressTagKeywordInAnonymousTagNames

---
 clang/include/clang/AST/PrettyPrinter.h | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index fb679e50a2d68..b2645f75ca57b 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -125,6 +125,14 @@ struct PrintingPolicy {
   /// \endcode
   LLVM_PREFERRED_TYPE(bool)
   unsigned SuppressTagKeyword : 1;
+
+  /// Whether type printing should skip printing the tag keyword
+  /// of anonymous entities. E.g.,
+  ///
+  /// * \c (anonymous) as opopsed to (anonymous struct)
+  /// * \c (unnamed) as opposed to (unnamed enum)
+  ///
+  LLVM_PREFERRED_TYPE(bool)
   unsigned SuppressTagKeywordInAnonymousTagNames : 1;
 
   /// When true, include the body of a tag definition.

>From 3111eeef69383d5ec066ea49847cef0629575a0c Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Tue, 9 Dec 2025 15:15:09 +0000
Subject: [PATCH 16/16] fixup! rename to SuppressTagKeywordInAnonNames

---
 clang-tools-extra/clangd/Hover.cpp      | 2 +-
 clang/include/clang/AST/PrettyPrinter.h | 5 ++---
 clang/lib/AST/Decl.cpp                  | 4 ++--
 clang/lib/AST/TypePrinter.cpp           | 2 +-
 4 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 8c7d397a9e756..bcf72255423bc 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -180,7 +180,7 @@ HoverInfo::PrintedType printType(QualType QT, ASTContext &ASTCtx,
   if (!QT.isNull() && !QT.hasQualifiers() && PP.SuppressTagKeyword) {
     if (auto *TT = llvm::dyn_cast<TagType>(QT.getTypePtr());
         TT && TT->isCanonicalUnqualified()) {
-      Copy.SuppressTagKeywordInAnonymousTagNames = true;
+      Copy.SuppressTagKeywordInAnonNames = true;
       OS << TT->getDecl()->getKindName() << " ";
     }
   }
diff --git a/clang/include/clang/AST/PrettyPrinter.h b/clang/include/clang/AST/PrettyPrinter.h
index b2645f75ca57b..2ede8da209748 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -61,8 +61,7 @@ struct PrintingPolicy {
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
       : Indentation(2), SuppressSpecifiers(false),
-        SuppressTagKeyword(LO.CPlusPlus),
-        SuppressTagKeywordInAnonymousTagNames(false),
+        SuppressTagKeyword(LO.CPlusPlus), SuppressTagKeywordInAnonNames(false),
         IncludeTagDefinition(false), SuppressScope(false),
         SuppressUnwrittenScope(false),
         SuppressInlineNamespace(
@@ -133,7 +132,7 @@ struct PrintingPolicy {
   /// * \c (unnamed) as opposed to (unnamed enum)
   ///
   LLVM_PREFERRED_TYPE(bool)
-  unsigned SuppressTagKeywordInAnonymousTagNames : 1;
+  unsigned SuppressTagKeywordInAnonNames : 1;
 
   /// When true, include the body of a tag definition.
   ///
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index 1728d06ce3306..8fbc35ff0c9e4 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1799,7 +1799,7 @@ void NamedDecl::printNestedNameSpecifier(raw_ostream &OS,
       // I.e., suppress tag locations, suppress leading keyword, *don't*
       // suppress tag in name
       Copy.SuppressTagKeyword = true;
-      Copy.SuppressTagKeywordInAnonymousTagNames = false;
+      Copy.SuppressTagKeywordInAnonNames = false;
       Copy.AnonymousTagLocations = false;
       RD->printName(OS, Copy);
     } else if (const auto *FD = dyn_cast<FunctionDecl>(DC)) {
@@ -4968,7 +4968,7 @@ void TagDecl::printAnonymousTagDecl(llvm::raw_ostream &OS,
     return;
   }
 
-  bool SuppressTagKeywordInName = Policy.SuppressTagKeywordInAnonymousTagNames;
+  bool SuppressTagKeywordInName = Policy.SuppressTagKeywordInAnonNames;
 
   // Emit leading keyword. Since we printed a leading keyword make sure we
   // don't print the tag as part of the name too.
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index d1b359605187a..dad34c85e9573 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -1549,7 +1549,7 @@ void TypePrinter::printTagType(const TagType *T, raw_ostream &OS) {
 
     // Suppress the redundant tag keyword if we just printed one.
     if (PrintedKindDecoration) {
-      Copy.SuppressTagKeywordInAnonymousTagNames = true;
+      Copy.SuppressTagKeywordInAnonNames = true;
       Copy.SuppressTagKeyword = true;
     }
 



More information about the lldb-commits mailing list