[clang-tools-extra] d1e02cd - [clang-tidy] Improve readability-enum-initial-value diagnostic message (#176485)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 19 06:42:21 PST 2026
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,
};
More information about the cfe-commits
mailing list