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
