https://github.com/davidmenggx updated 
https://github.com/llvm/llvm-project/pull/213772

>From 29bc34f02cb9aff77419b64daf25ab80eb602842 Mon Sep 17 00:00:00 2001
From: David Meng <[email protected]>
Date: Mon, 3 Aug 2026 14:52:45 -0700
Subject: [PATCH 1/2] [clang-tidy] Add TypedefInheritAnonTagConfig to
 readability-identifier-naming

`typedef enum {} MyEnum;` is currently checked against TypedefCase even
though the identifier names the enum itself. With the new option enabled
(default false), such a typedef or type alias is checked against the
style configured for that tag kind instead. If none is configured, the
typedef style still applies.

Closes https://github.com/llvm/llvm-project/issues/213665
---
 .../readability/IdentifierNamingCheck.cpp     |  87 +++++++---
 .../readability/IdentifierNamingCheck.h       |  23 ++-
 clang-tools-extra/docs/ReleaseNotes.rst       |   7 +
 .../checks/readability/identifier-naming.rst  |  35 ++++
 ...r-naming-typedef-inherit-anon-tag-config.c |  25 +++
 ...naming-typedef-inherit-anon-tag-config.cpp | 159 ++++++++++++++++++
 6 files changed, 305 insertions(+), 31 deletions(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.c
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
index 42f3101592758..8efea89b4fc34 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.cpp
@@ -290,8 +290,10 @@ IdentifierNamingCheck::FileStyle 
IdentifierNamingCheck::getFileStyleFromOptions(
   const bool IgnoreMainLike = Options.get("IgnoreMainLikeFunctions", false);
   const bool CheckAnonFieldInParent =
       Options.get("CheckAnonFieldInParent", false);
+  const bool TypedefInheritAnonTagConfig =
+      Options.get("TypedefInheritAnonTagConfig", false);
   return {std::move(Styles), std::move(HNOption), IgnoreMainLike,
-          CheckAnonFieldInParent};
+          CheckAnonFieldInParent, TypedefInheritAnonTagConfig};
 }
 
 std::string IdentifierNamingCheck::HungarianNotation::getDeclTypeName(
@@ -858,6 +860,8 @@ void 
IdentifierNamingCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) {
                 MainFileStyle->isIgnoringMainLikeFunction());
   Options.store(Opts, "CheckAnonFieldInParent",
                 MainFileStyle->isCheckingAnonFieldInParentScope());
+  Options.store(Opts, "TypedefInheritAnonTagConfig",
+                MainFileStyle->isTypedefInheritingAnonTagConfig());
 }
 
 bool IdentifierNamingCheck::matchesStyle(
@@ -1116,13 +1120,27 @@ std::string IdentifierNamingCheck::fixupWithStyle(
 StyleKind IdentifierNamingCheck::findStyleKind(
     const NamedDecl *D,
     ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
-    bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope) const {
+    bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope,
+    bool TypedefInheritAnonTagConfig) const {
   assert(D && D->getIdentifier() && !D->getName().empty() && !D->isImplicit() 
&&
          "Decl must be an explicit identifier with a name.");
 
   if (isa<ObjCIvarDecl>(D) && NamingStyles[SK_ObjcIvar])
     return SK_ObjcIvar;
 
+  // A typedef that provides the only name of an otherwise unnamed tag, as in
+  // `typedef enum {} E;`, names the tag itself, so it can be checked against
+  // the style configured for that tag kind.
+  if (TypedefInheritAnonTagConfig && isa<TypedefDecl, TypeAliasDecl>(D)) {
+    const TagDecl *Tag =
+        cast<TypedefNameDecl>(D)->getUnderlyingType()->getAsTagDecl();
+    if (Tag && Tag->getTypedefNameForAnonDecl() == D) {
+      const StyleKind SK = findStyleKindForTag(Tag, NamingStyles);
+      if (SK != SK_Invalid)
+        return SK;
+    }
+  }
+
   if (isa<TypedefDecl>(D) && NamingStyles[SK_Typedef])
     return SK_Typedef;
 
@@ -1164,30 +1182,9 @@ StyleKind IdentifierNamingCheck::findStyleKind(
     if (Decl->isAnonymousStructOrUnion())
       return SK_Invalid;
 
-    if (const auto *Definition = Decl->getDefinition()) {
-      if (const auto *CxxRecordDecl = dyn_cast<CXXRecordDecl>(Definition)) {
-        if (CxxRecordDecl->isAbstract() && NamingStyles[SK_AbstractClass])
-          return SK_AbstractClass;
-      }
-
-      if (Definition->isStruct() && NamingStyles[SK_Struct])
-        return SK_Struct;
-
-      if (Definition->isStruct() && NamingStyles[SK_Class])
-        return SK_Class;
-
-      if (Definition->isClass() && NamingStyles[SK_Class])
-        return SK_Class;
-
-      if (Definition->isClass() && NamingStyles[SK_Struct])
-        return SK_Struct;
-
-      if (Definition->isUnion() && NamingStyles[SK_Union])
-        return SK_Union;
-
-      if (Definition->isEnum() && NamingStyles[SK_Enum])
-        return SK_Enum;
-    }
+    const StyleKind SK = findStyleKindForTag(Decl, NamingStyles);
+    if (SK != SK_Invalid)
+      return SK;
 
     return undefinedStyle(NamingStyles);
   }
@@ -1405,7 +1402,8 @@ IdentifierNamingCheck::getDeclFailureInfo(const NamedDecl 
*Decl,
       FileStyle.getStyles(), FileStyle.getHNOption(),
       findStyleKind(Decl, FileStyle.getStyles(),
                     FileStyle.isIgnoringMainLikeFunction(),
-                    FileStyle.isCheckingAnonFieldInParentScope()),
+                    FileStyle.isCheckingAnonFieldInParentScope(),
+                    FileStyle.isTypedefInheritingAnonTagConfig()),
       SM, IgnoreFailedSplit);
 }
 
@@ -1515,6 +1513,41 @@ StyleKind IdentifierNamingCheck::findStyleKindForField(
   return undefinedStyle(NamingStyles);
 }
 
+StyleKind IdentifierNamingCheck::findStyleKindForTag(
+    const TagDecl *Tag,
+    ArrayRef<std::optional<NamingStyle>> NamingStyles) const {
+  if (isa<EnumDecl>(Tag) && NamingStyles[SK_Enum])
+    return SK_Enum;
+
+  const auto *Record = dyn_cast<RecordDecl>(Tag);
+  if (!Record)
+    return SK_Invalid;
+
+  if (const auto *Definition = Record->getDefinition()) {
+    if (const auto *CxxRecordDecl = dyn_cast<CXXRecordDecl>(Definition)) {
+      if (CxxRecordDecl->isAbstract() && NamingStyles[SK_AbstractClass])
+        return SK_AbstractClass;
+    }
+
+    if (Definition->isStruct() && NamingStyles[SK_Struct])
+      return SK_Struct;
+
+    if (Definition->isStruct() && NamingStyles[SK_Class])
+      return SK_Class;
+
+    if (Definition->isClass() && NamingStyles[SK_Class])
+      return SK_Class;
+
+    if (Definition->isClass() && NamingStyles[SK_Struct])
+      return SK_Struct;
+
+    if (Definition->isUnion() && NamingStyles[SK_Union])
+      return SK_Union;
+  }
+
+  return SK_Invalid;
+}
+
 StyleKind IdentifierNamingCheck::findStyleKindForVar(
     const VarDecl *Var, QualType Type,
     ArrayRef<std::optional<NamingStyle>> NamingStyles) const {
diff --git a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h 
b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
index 0afc7e2246816..8f20acc6030cb 100644
--- a/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/IdentifierNamingCheck.h
@@ -125,13 +125,16 @@ class IdentifierNamingCheck final : public 
RenamerClangTidyCheck {
   };
 
   struct FileStyle {
-    FileStyle() : IsActive(false), IgnoreMainLikeFunctions(false) {}
+    FileStyle()
+        : IsActive(false), IgnoreMainLikeFunctions(false),
+          TypedefInheritAnonTagConfig(false) {}
     FileStyle(SmallVectorImpl<std::optional<NamingStyle>> &&Styles,
               HungarianNotationOption HNOption, bool IgnoreMainLike,
-              bool CheckAnonFieldInParent)
+              bool CheckAnonFieldInParent, bool TypedefInheritAnonTag)
         : Styles(std::move(Styles)), HNOption(std::move(HNOption)),
           IsActive(true), IgnoreMainLikeFunctions(IgnoreMainLike),
-          CheckAnonFieldInParentScope(CheckAnonFieldInParent) {}
+          CheckAnonFieldInParentScope(CheckAnonFieldInParent),
+          TypedefInheritAnonTagConfig(TypedefInheritAnonTag) {}
 
     ArrayRef<std::optional<NamingStyle>> getStyles() const {
       assert(IsActive);
@@ -150,12 +153,17 @@ class IdentifierNamingCheck final : public 
RenamerClangTidyCheck {
       return CheckAnonFieldInParentScope;
     }
 
+    bool isTypedefInheritingAnonTagConfig() const {
+      return TypedefInheritAnonTagConfig;
+    }
+
   private:
     SmallVector<std::optional<NamingStyle>, 0> Styles;
     HungarianNotationOption HNOption;
     bool IsActive;
     bool IgnoreMainLikeFunctions;
     bool CheckAnonFieldInParentScope;
+    bool TypedefInheritAnonTagConfig;
   };
 
   IdentifierNamingCheck::FileStyle
@@ -182,7 +190,8 @@ class IdentifierNamingCheck final : public 
RenamerClangTidyCheck {
   StyleKind findStyleKind(
       const NamedDecl *D,
       ArrayRef<std::optional<IdentifierNamingCheck::NamingStyle>> NamingStyles,
-      bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope) const;
+      bool IgnoreMainLikeFunctions, bool CheckAnonFieldInParentScope,
+      bool TypedefInheritAnonTagConfig) const;
 
   std::optional<RenamerClangTidyCheck::FailureInfo> getFailureInfo(
       StringRef Type, StringRef Name, const NamedDecl *ND,
@@ -216,6 +225,12 @@ class IdentifierNamingCheck final : public 
RenamerClangTidyCheck {
       const FieldDecl *Field, QualType Type,
       ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
 
+  /// Find the style kind configured for the kind of \p Tag, or \c SK_Invalid 
if
+  /// none is configured.
+  StyleKind
+  findStyleKindForTag(const TagDecl *Tag,
+                      ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
+
   StyleKind
   findStyleKindForVar(const VarDecl *Var, QualType Type,
                       ArrayRef<std::optional<NamingStyle>> NamingStyles) const;
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 05407c3319683..6a9946d1c9313 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -118,6 +118,13 @@ Changes in existing checks
   nested expressions involving different macros or a mix of macro and
   non-macro operands.
 
+- Improved :doc:`readability-identifier-naming
+  <clang-tidy/checks/readability/identifier-naming>` check by adding the
+  :option:`TypedefInheritAnonTagConfig` option, which checks a typedef or type
+  alias that provides the only name of an otherwise unnamed tag, such as
+  ``typedef enum {} MyEnum;``, against the style configured for that tag kind
+  instead of the typedef or type alias style.
+
 - Improved :doc:`readability-named-parameter
   <clang-tidy/checks/readability/named-parameter>` check by ignoring
   standard tag types (e.g. ``std::in_place_t``, ``std::allocator_arg_t``,
diff --git 
a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst 
b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
index c8f87dcba8c0a..e47939459dc77 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/identifier-naming.rst
@@ -85,6 +85,7 @@ The available options are summarized below:
  - :option:`CheckAnonFieldInParent`
  - :option:`GetConfigPerFile`
  - :option:`IgnoreMainLikeFunctions`
+ - :option:`TypedefInheritAnonTagConfig`
 
 **Specific options**
 
@@ -2732,6 +2733,40 @@ After:
 
     typedef int pre_myint_post;
 
+.. option:: TypedefInheritAnonTagConfig
+
+    When set to `true`, a typedef or type alias that provides the only name of
+    an otherwise unnamed tag, as in ``typedef enum {} MyEnum;``, is checked
+    against the naming style configured for the kind of that tag
+    (``AbstractClass``, ``Class``, ``Enum``, ``Struct`` or ``Union``, i.e.
+    :option:`EnumCase`, :option:`EnumPrefix`, :option:`EnumSuffix` and
+    :option:`EnumIgnoredRegexp` for an enum) rather than against the typedef
+    or type alias style. If no style is configured for that kind, the typedef
+    or type alias style still applies. Typedefs of named tags, of other
+    typedefs and of non-tag types are not affected. Default is `false`.
+
+For example using values of:
+
+   - TypedefInheritAnonTagConfig of `true`
+   - EnumCase of ``CamelCase``
+   - TypedefCase of ``lower_case``
+
+Identifies and/or transforms names as follows:
+
+Before:
+
+.. code-block:: c++
+
+    typedef enum { VAL } my_enum;        // The typedef names the enum.
+    typedef enum Kind { VAL2 } my_kind;  // Kind names the enum.
+
+After:
+
+.. code-block:: c++
+
+    typedef enum { VAL } MyEnum;
+    typedef enum Kind { VAL2 } my_kind;
+
 .. option:: TypeTemplateParameterCase
 
     When defined, the check will ensure type template parameter names conform 
to the
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.c
 
b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.c
new file mode 100644
index 0000000000000..5312e5dfd5f47
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.c
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy -std=c17 %s readability-identifier-naming %t -- \
+// RUN:   -config='{CheckOptions: { \
+// RUN:     readability-identifier-naming.TypedefInheritAnonTagConfig: true, \
+// RUN:     readability-identifier-naming.EnumCase: CamelCase, \
+// RUN:     readability-identifier-naming.StructCase: lower_case, \
+// RUN:     readability-identifier-naming.UnionCase: UPPER_CASE, \
+// RUN:     readability-identifier-naming.TypedefCase: camelBack, \
+// RUN:   }}'
+
+typedef enum { EV_ANON } my_enum;
+// CHECK-MESSAGES: :[[@LINE-1]]:26: warning: invalid case style for enum 
'my_enum' [readability-identifier-naming]
+// CHECK-FIXES: typedef enum { EV_ANON } MyEnum;
+
+typedef struct { int Field; } My_Struct;
+// CHECK-MESSAGES: :[[@LINE-1]]:31: warning: invalid case style for struct 
'My_Struct' [readability-identifier-naming]
+// CHECK-FIXES: typedef struct { int Field; } my_struct;
+
+typedef union { int I; float F; } my_union;
+// CHECK-MESSAGES: :[[@LINE-1]]:35: warning: invalid case style for union 
'my_union' [readability-identifier-naming]
+// CHECK-FIXES: typedef union { int I; float F; } MY_UNION;
+
+// The tag has a name of its own, so the typedef style still applies.
+typedef struct data { int Field; } my_data;
+// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: invalid case style for typedef 
'my_data' [readability-identifier-naming]
+// CHECK-FIXES: typedef struct data { int Field; } myData;
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.cpp
new file mode 100644
index 0000000000000..380b78d74c05b
--- /dev/null
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/identifier-naming-typedef-inherit-anon-tag-config.cpp
@@ -0,0 +1,159 @@
+// RUN: %check_clang_tidy -check-suffixes=TAGSTYLE,SHARED -std=c++17 %s \
+// RUN:   readability-identifier-naming %t -- \
+// RUN:   -config='{CheckOptions: { \
+// RUN:     readability-identifier-naming.TypedefInheritAnonTagConfig: true, \
+// RUN:     readability-identifier-naming.AbstractClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.ClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumIgnoredRegexp: "ignored_.*", \
+// RUN:     readability-identifier-naming.StructCase: lower_case, \
+// RUN:     readability-identifier-naming.UnionCase: UPPER_CASE, \
+// RUN:     readability-identifier-naming.TypeAliasCase: camelBack, \
+// RUN:     readability-identifier-naming.TypedefCase: camelBack, \
+// RUN:   }}'
+
+// Re-running the check on the fixed file must not produce any further
+// warning. Directly after the run it validates, because the runs below
+// overwrite %t.cpp.
+// RUN: clang-tidy %t.cpp -checks='-*,readability-identifier-naming' \
+// RUN:   -warnings-as-errors='-*,readability-identifier-naming' \
+// RUN:   -config='{CheckOptions: { \
+// RUN:     readability-identifier-naming.TypedefInheritAnonTagConfig: true, \
+// RUN:     readability-identifier-naming.AbstractClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.ClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumIgnoredRegexp: "ignored_.*", \
+// RUN:     readability-identifier-naming.StructCase: lower_case, \
+// RUN:     readability-identifier-naming.UnionCase: UPPER_CASE, \
+// RUN:     readability-identifier-naming.TypeAliasCase: camelBack, \
+// RUN:     readability-identifier-naming.TypedefCase: camelBack, \
+// RUN:   }}' -- -std=c++17
+
+// RUN: %check_clang_tidy -check-suffixes=TYPEDEFSTYLE,SHARED -std=c++17 %s \
+// RUN:   readability-identifier-naming %t -- \
+// RUN:   -config='{CheckOptions: { \
+// RUN:     readability-identifier-naming.AbstractClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.ClassCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumCase: CamelCase, \
+// RUN:     readability-identifier-naming.EnumIgnoredRegexp: "ignored_.*", \
+// RUN:     readability-identifier-naming.StructCase: lower_case, \
+// RUN:     readability-identifier-naming.UnionCase: UPPER_CASE, \
+// RUN:     readability-identifier-naming.TypeAliasCase: camelBack, \
+// RUN:     readability-identifier-naming.TypedefCase: camelBack, \
+// RUN:   }}'
+
+// RUN: %check_clang_tidy -check-suffixes=TYPEDEFSTYLE,SHARED -std=c++17 %s \
+// RUN:   readability-identifier-naming %t -- \
+// RUN:   -config='{CheckOptions: { \
+// RUN:     readability-identifier-naming.TypedefInheritAnonTagConfig: true, \
+// RUN:     readability-identifier-naming.TypeAliasCase: camelBack, \
+// RUN:     readability-identifier-naming.TypedefCase: camelBack, \
+// RUN:   }}'
+
+// The typedef is the only name of the tag it defines, so it can inherit the
+// style configured for that tag kind.
+
+typedef enum { EV_ANON } my_enum;
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:26: warning: invalid case style for 
enum 'my_enum' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:26: warning: invalid case style 
for typedef 'my_enum' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef enum { EV_ANON } MyEnum;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef enum { EV_ANON } myEnum;
+
+typedef struct { int Field; } My_Struct;
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:31: warning: invalid case style for 
struct 'My_Struct' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:31: warning: invalid case style 
for typedef 'My_Struct' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef struct { int Field; } my_struct;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef struct { int Field; } myStruct;
+
+typedef union { int I; float F; } my_union;
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:35: warning: invalid case style for 
union 'my_union' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:35: warning: invalid case style 
for typedef 'my_union' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef union { int I; float F; } MY_UNION;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef union { int I; float F; } myUnion;
+
+typedef class { int Field; } my_class;
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:30: warning: invalid case style for 
class 'my_class' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:30: warning: invalid case style 
for typedef 'my_class' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef class { int Field; } MyClass;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef class { int Field; } myClass;
+
+typedef class { public: virtual void f() = 0; } my_abstract;
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:49: warning: invalid case style for 
abstract class 'my_abstract' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:49: warning: invalid case style 
for typedef 'my_abstract' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef class { public: virtual void f() = 0; } 
MyAbstract;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef class { public: virtual void f() = 0; } 
myAbstract;
+
+using my_alias_enum = enum { EV_ALIAS };
+// CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:7: warning: invalid case style for 
enum 'my_alias_enum' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:7: warning: invalid case style 
for type alias 'my_alias_enum' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: using MyAliasEnum = enum { EV_ALIAS };
+// CHECK-FIXES-TYPEDEFSTYLE: using myAliasEnum = enum { EV_ALIAS };
+
+// The whole style of the tag kind is inherited, not just its case, so the
+// ignored regexp of the enum applies here.
+
+typedef enum { EV_IGNORED } ignored_enum_t;
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-1]]:29: warning: invalid case style 
for typedef 'ignored_enum_t' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef enum { EV_IGNORED } ignored_enum_t;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef enum { EV_IGNORED } ignoredEnumT;
+
+// The tag has a name of its own, so the typedef is just an alias for it and
+// keeps the typedef style.
+
+typedef enum Kind { EV_NAMED } my_kind;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:32: warning: invalid case style for 
typedef 'my_kind' [readability-identifier-naming]
+// CHECK-FIXES-SHARED: typedef enum Kind { EV_NAMED } myKind;
+
+using my_kind_alias = Kind;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:7: warning: invalid case style for type 
alias 'my_kind_alias' [readability-identifier-naming]
+// CHECK-FIXES-SHARED: using myKindAlias = Kind;
+
+typedef struct data { int Field; } my_data;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:36: warning: invalid case style for 
typedef 'my_data' [readability-identifier-naming]
+// CHECK-FIXES-SHARED: typedef struct data { int Field; } myData;
+
+// Of several declarators, the first one that denotes the tag type itself names
+// the tag. The others are ordinary typedefs.
+
+typedef enum { EV_MULTI } FirstEnum, second_enum;
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-1]]:27: warning: invalid case style 
for typedef 'FirstEnum' [readability-identifier-naming]
+// CHECK-MESSAGES-SHARED: :[[@LINE-2]]:38: warning: invalid case style for 
typedef 'second_enum' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef enum { EV_MULTI } FirstEnum, secondEnum;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef enum { EV_MULTI } firstEnum, secondEnum;
+
+typedef struct { int Field; } *first_ptr, second_struct;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:32: warning: invalid case style for 
typedef 'first_ptr' [readability-identifier-naming]
+// CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:43: warning: invalid case style 
for typedef 'second_struct' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef struct { int Field; } *firstPtr, 
second_struct;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef struct { int Field; } *firstPtr, 
secondStruct;
+
+// The typedef does not name a tag type at all.
+
+typedef struct { int Field; } *my_struct_ptr;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:32: warning: invalid case style for 
typedef 'my_struct_ptr' [readability-identifier-naming]
+// CHECK-FIXES-SHARED: typedef struct { int Field; } *myStructPtr;
+
+typedef int my_int;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:13: warning: invalid case style for 
typedef 'my_int' [readability-identifier-naming]
+// CHECK-FIXES-SHARED: typedef int myInt;
+
+// A typedef of a typedef does not name the tag either.
+
+typedef My_Struct my_struct_alias;
+// CHECK-MESSAGES-SHARED: :[[@LINE-1]]:19: warning: invalid case style for 
typedef 'my_struct_alias' [readability-identifier-naming]
+// CHECK-FIXES-TAGSTYLE: typedef my_struct myStructAlias;
+// CHECK-FIXES-TYPEDEFSTYLE: typedef myStruct myStructAlias;
+
+// The typedef names the tag in the template pattern as well as in its
+// instantiations, so it is reported only once.
+
+template <typename T>
+struct holder {
+  typedef enum { EV_TPL } inner_enum;
+  // CHECK-MESSAGES-TAGSTYLE: :[[@LINE-1]]:27: warning: invalid case style for 
enum 'inner_enum' [readability-identifier-naming]
+  // CHECK-MESSAGES-TYPEDEFSTYLE: :[[@LINE-2]]:27: warning: invalid case style 
for typedef 'inner_enum' [readability-identifier-naming]
+  // CHECK-FIXES-TAGSTYLE: typedef enum { EV_TPL } InnerEnum;
+  // CHECK-FIXES-TYPEDEFSTYLE: typedef enum { EV_TPL } innerEnum;
+};
+
+template struct holder<int>;

>From baf68647ca864f733b65e53843ab96232d542012 Mon Sep 17 00:00:00 2001
From: David Meng <[email protected]>
Date: Tue, 4 Aug 2026 08:50:04 -0700
Subject: [PATCH 2/2] Update clang-tools-extra/docs/ReleaseNotes.rst

Co-authored-by: EugeneZelenko <[email protected]>
---
 clang-tools-extra/docs/ReleaseNotes.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 6a9946d1c9313..422804542090f 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -120,7 +120,7 @@ Changes in existing checks
 
 - Improved :doc:`readability-identifier-naming
   <clang-tidy/checks/readability/identifier-naming>` check by adding the
-  :option:`TypedefInheritAnonTagConfig` option, which checks a typedef or type
+  `TypedefInheritAnonTagConfig` option, which checks a typedef or type
   alias that provides the only name of an otherwise unnamed tag, such as
   ``typedef enum {} MyEnum;``, against the style configured for that tag kind
   instead of the typedef or type alias style.

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to