[clang-tools-extra] [clang-tidy] Improve readability-enum-initial-value diagnostic message (PR #176485)
Endre Fülöp via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 16 14:14:12 PST 2026
https://github.com/gamesh411 created https://github.com/llvm/llvm-project/pull/176485
Enhance the readability-enum-initial-value checker to list which enumerators
are not initialized in the warning message. This makes it easier for users to
identify which specific enumerators need explicit initialization.
>From 5bd02764a8dc94e6c2d1d743bcb43de04bdfca77 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= <endre.fulop at sigmatechnology.com>
Date: Fri, 16 Jan 2026 19:05:02 +0100
Subject: [PATCH] [clang-tidy] Improve readability-enum-initial-value
diagnostic message
Enhance the readability-enum-initial-value checker to list which
enumerators
are not initialized in the warning message. This makes it easier for
users to
identify which specific enumerators need explicit initialization.
---
.../readability/EnumInitialValueCheck.cpp | 30 +++++++++++++++----
clang-tools-extra/docs/ReleaseNotes.rst | 6 ++++
.../checks/readability/enum-initial-value.rst | 9 ++++--
.../checkers/readability/enum-initial-value.c | 20 ++++++-------
.../readability/enum-initial-value.cpp | 2 +-
5 files changed, 48 insertions(+), 19 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
index 049ad759b834c..364ac74ffeed7 100644
--- a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
@@ -15,6 +15,7 @@
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
using namespace clang::ast_matchers;
@@ -165,12 +166,29 @@ 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);
+ llvm::SmallVector<StringRef, 4> UninitializedNames;
+ for (const EnumConstantDecl *ECD : Enum->enumerators())
+ if (ECD->getInitExpr() == nullptr && ECD->getDeclName())
+ UninitializedNames.push_back(ECD->getName());
+
+ llvm::SmallString<256> Message;
+ Message = "initial values in enum '%0' are not consistent, "
+ "consider explicit initialization of all, none or "
+ "only the first enumerator";
+ if (!UninitializedNames.empty()) {
+ Message += " (uninitialized enumerators: ";
+ for (size_t I = 0; I < UninitializedNames.size(); ++I) {
+ if (I > 0)
+ Message += (I < UninitializedNames.size() - 1) ? ", " : " and ";
+ Message += "'";
+ Message += UninitializedNames[I];
+ Message += "'";
+ }
+ Message += ")";
+ }
+
+ const DiagnosticBuilder Diag = diag(Enum->getBeginLoc(), Message)
+ << getName(Enum);
for (const EnumConstantDecl *ECD : Enum->enumerators())
if (ECD->getInitExpr() == nullptr) {
const SourceLocation EndLoc = Lexer::getLocForEndOfToken(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 94a11b1acb73a..e9ba7309cfa7d 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -113,6 +113,12 @@ 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 lists which enumerators are not initialized, 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..65afe1c85b902 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,13 +36,18 @@ 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 (uninitialized enumerators: 'd1')
d0 = 0,
d1,
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 (uninitialized enumerators:
+ // 'e1', 'e3' and 'e5')
e0 = 0,
e1,
e2 = 2,
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..0d935d7ec919a 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,8 +6,8 @@
// 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 (uninitialized enumerators: 'EError_b')
+ // 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 (uninitialized enumerators: 'EError_b')
EError_a = 1,
EError_b,
// CHECK-FIXES: EError_b = 2,
@@ -34,8 +34,8 @@ 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 (uninitialized enumerators: 'EMacro1_b')
+ // 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 (uninitialized enumerators: 'EMacro1_b')
EMacro1_a = 1,
ENUMERATOR_1,
// CHECK-FIXES: ENUMERATOR_1 = 2,
@@ -45,8 +45,8 @@ 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 (uninitialized enumerators: 'EMacro2_c')
+ // 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 (uninitialized enumerators: 'EMacro2_c')
EMacro2_a = 1,
ENUMERATOR_2,
EMacro2_c,
@@ -55,8 +55,8 @@ enum EMacro2 {
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 (uninitialized enumerators: 'EAnonymous_b')
+ // 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 (uninitialized enumerators: 'EAnonymous_b')
EAnonymous_a = 1,
EAnonymous_b,
// CHECK-FIXES: EAnonymous_b = 2,
@@ -94,8 +94,8 @@ 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 (uninitialized enumerators: 'EFI0' and 'EFI2')
+ // 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 (uninitialized enumerators: 'EFI0' and 'EFI2')
EFI0,
// CHECK-FIXES: EFI0 = 0,
EFI1 = 1,
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..ee32cd2429e71 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,7 +1,7 @@
// 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 (uninitialized enumerators: 'EError_b')
EError_a = 1,
EError_b,
// CHECK-FIXES: EError_b = 2,
More information about the cfe-commits
mailing list