Author: Endre Fülöp
Date: 2026-01-19T15:42:17+01:00
New Revision: d1e02cd31ebc5b1908da76fdc6bf751bb9ea4a34

URL: 
https://github.com/llvm/llvm-project/commit/d1e02cd31ebc5b1908da76fdc6bf751bb9ea4a34
DIFF: 
https://github.com/llvm/llvm-project/commit/d1e02cd31ebc5b1908da76fdc6bf751bb9ea4a34.diff

LOG: [clang-tidy] Improve readability-enum-initial-value diagnostic message 
(#176485)

Enhance the readability-enum-initial-value checker to list which
enumerators
are not initialized in notes. This makes it easier for users to identify
which
specific enumerators need explicit initialization.

Added: 
    

Modified: 
    clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
    clang-tools-extra/docs/ReleaseNotes.rst
    clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
    clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
    
clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp

Removed: 
    


################################################################################
diff  --git 
a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
index 049ad759b834c..d99143c875729 100644
--- a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
@@ -165,22 +165,36 @@ void EnumInitialValueCheck::registerMatchers(MatchFinder 
*Finder) {
 
 void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) {
   if (const auto *Enum = Result.Nodes.getNodeAs<EnumDecl>("inconsistent")) {
-    const DiagnosticBuilder Diag =
-        diag(
-            Enum->getBeginLoc(),
-            "initial values in enum '%0' are not consistent, consider explicit 
"
-            "initialization of all, none or only the first enumerator")
-        << getName(Enum);
-    for (const EnumConstantDecl *ECD : Enum->enumerators())
+    // Emit warning first (DiagnosticBuilder emits on destruction), then notes.
+    // Notes must follow the primary diagnostic or they may be dropped.
+    {
+      const DiagnosticBuilder Diag =
+          diag(Enum->getBeginLoc(), "initial values in enum '%0' are not "
+                                    "consistent, consider explicit "
+                                    "initialization of all, none or only the "
+                                    "first enumerator")
+          << getName(Enum);
+
+      for (const EnumConstantDecl *ECD : Enum->enumerators()) {
+        if (ECD->getInitExpr() == nullptr) {
+          const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+              ECD->getLocation(), 0, *Result.SourceManager, getLangOpts());
+          if (EndLoc.isMacroID())
+            continue;
+          llvm::SmallString<8> Str{" = "};
+          ECD->getInitVal().toString(Str);
+          Diag << FixItHint::CreateInsertion(EndLoc, Str);
+        }
+      }
+    }
+
+    for (const EnumConstantDecl *ECD : Enum->enumerators()) {
       if (ECD->getInitExpr() == nullptr) {
-        const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
-            ECD->getLocation(), 0, *Result.SourceManager, getLangOpts());
-        if (EndLoc.isMacroID())
-          continue;
-        llvm::SmallString<8> Str{" = "};
-        ECD->getInitVal().toString(Str);
-        Diag << FixItHint::CreateInsertion(EndLoc, Str);
+        diag(ECD->getLocation(), "uninitialized enumerator '%0' defined here",
+             DiagnosticIDs::Note)
+            << ECD->getName();
       }
+    }
     return;
   }
 

diff  --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 94a11b1acb73a..68293fcdfafe2 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,6 +113,11 @@ Changes in existing checks
   <clang-tidy/checks/performance/move-const-arg>` check by avoiding false
   positives on trivially copyable types with a non-public copy constructor.
 
+- Improved :doc:`readability-enum-initial-value
+  <clang-tidy/checks/readability/enum-initial-value>` check: the warning 
message
+  now uses separate note diagnostics for each uninitialized enumerator, making
+  it easier to see which specific enumerators need explicit initialization.
+
 Removed checks
 ^^^^^^^^^^^^^^
 

diff  --git 
a/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst 
b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
index b27e10d5c1336..f59c433c51d0b 100644
--- 
a/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
+++ 
b/clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
@@ -36,19 +36,25 @@ The following three cases are accepted:
     c2 = 2,
   };
 
-  enum D {    // Invalid, d1 is not explicitly initialized!
+  enum D {    // warning: initial values in enum 'D' are not consistent,
+              //          consider explicit initialization of all, none or only
+              //          the first enumerator
     d0 = 0,
-    d1,
+    d1,       // note: uninitialized enumerator 'd1' defined here
     d2 = 2,
   };
 
-  enum E {    // Invalid, e1, e3, and e5 are not explicitly initialized.
+  enum E {    // warning: initial values in enum 'E' are not consistent,
+              //          consider explicit initialization of all, none or only
+              //          the first enumerator
     e0 = 0,
-    e1,
+    e1,       // note: uninitialized enumerator 'e1' defined here
     e2 = 2,
-    e3,       // Dangerous, as the numeric values of e3 and e5 are both 3, and 
this is not explicitly visible in the code!
+    e3,       // note: uninitialized enumerator 'e3' defined here
+              // Dangerous, as the numeric values of e3 and e5 are both 3,
+              // and this is not explicitly visible in the code!
     e4 = 2,
-    e5,
+    e5,       // note: uninitialized enumerator 'e5' defined here
   };
 
 This check corresponds to the CERT C Coding Standard recommendation `INT09-C. 
Ensure enumeration constants map to unique values

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c 
b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
index 54108585f030f..fcf5b20ea4ee2 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
@@ -6,10 +6,12 @@
 // RUN:     }}'
 
 enum EError {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EError' 
are not consistent
-  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EError' are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EError' 
are not consistent, consider explicit initialization of all, none or only the 
first enumerator
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EError' are not consistent, consider explicit initialization of all, none or 
only the first enumerator
   EError_a = 1,
   EError_b,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 'EError_b' 
defined here
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:3: note: uninitialized enumerator 
'EError_b' defined here
   // CHECK-FIXES: EError_b = 2,
   EError_c = 3,
 };
@@ -34,10 +36,14 @@ enum EAll {
 
 #define ENUMERATOR_1 EMacro1_b
 enum EMacro1 {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro1' 
are not consistent
-  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EMacro1' are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro1' 
are not consistent, consider explicit initialization of all, none or only the 
first enumerator
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EMacro1' are not consistent, consider explicit initialization of all, none or 
only the first enumerator
   EMacro1_a = 1,
   ENUMERATOR_1,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 
'EMacro1_b' defined here
+  // CHECK-MESSAGES: note: expanded from macro 'ENUMERATOR_1'
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-3]]:3: note: uninitialized enumerator 
'EMacro1_b' defined here
+  // CHECK-MESSAGES-ENABLE: note: expanded from macro 'ENUMERATOR_1'
   // CHECK-FIXES: ENUMERATOR_1 = 2,
   EMacro1_c = 3,
 };
@@ -45,20 +51,24 @@ enum EMacro1 {
 
 #define ENUMERATOR_2 EMacro2_b = 2
 enum EMacro2 {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro2' 
are not consistent
-  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EMacro2' are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EMacro2' 
are not consistent, consider explicit initialization of all, none or only the 
first enumerator
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'EMacro2' are not consistent, consider explicit initialization of all, none or 
only the first enumerator
   EMacro2_a = 1,
   ENUMERATOR_2,
   EMacro2_c,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 
'EMacro2_c' defined here
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:3: note: uninitialized enumerator 
'EMacro2_c' defined here
   // CHECK-FIXES: EMacro2_c = 3,
 };
 
 
 enum {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 
'<unnamed>' are not consistent
-  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'<unnamed>' are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 
'<unnamed>' are not consistent, consider explicit initialization of all, none 
or only the first enumerator
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'<unnamed>' are not consistent, consider explicit initialization of all, none 
or only the first enumerator
   EAnonymous_a = 1,
   EAnonymous_b,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 
'EAnonymous_b' defined here
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:3: note: uninitialized enumerator 
'EAnonymous_b' defined here
   // CHECK-FIXES: EAnonymous_b = 2,
   EAnonymous_c = 3,
 };
@@ -94,12 +104,16 @@ enum EnumSequentialInitialValue {
 enum WithFwdDeclInconsistent : int;
 
 enum WithFwdDeclInconsistent : int {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 
'WithFwdDeclInconsistent' are not consistent
-  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'WithFwdDeclInconsistent' are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 
'WithFwdDeclInconsistent' are not consistent, consider explicit initialization 
of all, none or only the first enumerator
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 
'WithFwdDeclInconsistent' are not consistent, consider explicit initialization 
of all, none or only the first enumerator
   EFI0,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 'EFI0' 
defined here
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:3: note: uninitialized enumerator 
'EFI0' defined here
   // CHECK-FIXES: EFI0 = 0,
   EFI1 = 1,
   EFI2,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 'EFI2' 
defined here
+  // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:3: note: uninitialized enumerator 
'EFI2' defined here
   // CHECK-FIXES: EFI2 = 2,
 };
 

diff  --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp 
b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp
index 9d324a39ee6a3..7a97534fd8e2b 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp
@@ -1,9 +1,10 @@
 // RUN: %check_clang_tidy %s readability-enum-initial-value %t
 
 enum class EError {
-  // CHECK-MESSAGES: :[[@LINE-1]]:1:  warning: initial values in enum 'EError' 
are not consistent
+  // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'EError' 
are not consistent, consider explicit initialization of all, none or only the 
first enumerator
   EError_a = 1,
   EError_b,
+  // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 'EError_b' 
defined here
   // CHECK-FIXES: EError_b = 2,
   EError_c = 3,
 };


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

Reply via email to