https://github.com/bjosv updated https://github.com/llvm/llvm-project/pull/189459
From dc1369f688bf63d9ed5492014b7372449262db48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Mon, 30 Mar 2026 08:19:18 +0000 Subject: [PATCH 1/3] Add AllowExplicitReferencedInitialValues to readability-enum-initial-value MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add a new option that allows enumerators initialized by referencing another enumerator in the same enum (e.g., last = first). This implements the INT09-C-EX1 exception from the CERT C Coding Standard. The three AST matchers are converted from AST_MATCHER to AST_MATCHER_P to accept a bool AllowRefs parameter. The existing helper functions (isNoneEnumeratorsInitialized, isOnlyFirstEnumeratorInitialized, areAllEnumeratorsInitialized) are extended to skip self-referencing enumerators when AllowRefs is set. Signed-off-by: Björn Svensson <[email protected]> --- .../readability/EnumInitialValueCheck.cpp | 73 ++++++++++++++----- .../readability/EnumInitialValueCheck.h | 5 +- clang-tools-extra/docs/ReleaseNotes.rst | 3 + .../checks/readability/enum-initial-value.rst | 17 +++++ .../enum-initial-value-allow-refs-combined.c | 34 +++++++++ .../enum-initial-value-allow-refs.c | 50 +++++++++++++ .../enum-initial-value-allow-refs.cpp | 35 +++++++++ .../checkers/readability/enum-initial-value.c | 10 +++ .../readability/enum-initial-value.cpp | 9 +++ 9 files changed, 215 insertions(+), 21 deletions(-) create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs-combined.c create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.c create mode 100644 clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.cpp diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp index 4612d94f3663b..1a6bf28dbaf35 100644 --- a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp @@ -20,15 +20,39 @@ using namespace clang::ast_matchers; namespace clang::tidy::readability { -static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) { - return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { - return ECD->getInitExpr() == nullptr; +/// Check if \p ECD is initialized by referencing another enumerator in the +/// same enum (e.g., `last = first`). +static bool isSelfReference(const EnumConstantDecl *ECD) { + const Expr *Init = ECD->getInitExpr(); + if (!Init) + return false; + const auto *CE = dyn_cast<ConstantExpr>(Init); + if (!CE) + return false; + const auto *DRE = dyn_cast<DeclRefExpr>(CE->getSubExpr()); + if (!DRE) + return false; + const auto *RefECD = dyn_cast<EnumConstantDecl>(DRE->getDecl()); + return RefECD && RefECD->getDeclContext() == ECD->getDeclContext(); +} + +static bool isAllowedReference(const EnumConstantDecl *ECD, bool AllowRefs) { + return AllowRefs && isSelfReference(ECD); +} + +static bool isNoneEnumeratorsInitialized(const EnumDecl &Node, bool AllowRefs) { + return llvm::all_of(Node.enumerators(), [AllowRefs]( + const EnumConstantDecl *ECD) { + return isAllowedReference(ECD, AllowRefs) || ECD->getInitExpr() == nullptr; }); } -static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) { +static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node, + bool AllowRefs) { bool IsFirst = true; for (const EnumConstantDecl *ECD : Node.enumerators()) { + if (isAllowedReference(ECD, AllowRefs)) + continue; if ((IsFirst && ECD->getInitExpr() == nullptr) || (!IsFirst && ECD->getInitExpr() != nullptr)) return false; @@ -37,9 +61,10 @@ static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) { return !IsFirst; } -static bool areAllEnumeratorsInitialized(const EnumDecl &Node) { - return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) { - return ECD->getInitExpr() != nullptr; +static bool areAllEnumeratorsInitialized(const EnumDecl &Node, bool AllowRefs) { + return llvm::all_of(Node.enumerators(), [AllowRefs]( + const EnumConstantDecl *ECD) { + return isAllowedReference(ECD, AllowRefs) || ECD->getInitExpr() != nullptr; }); } @@ -79,18 +104,19 @@ AST_MATCHER(EnumDecl, isMacro) { return Loc.isMacroID(); } -AST_MATCHER(EnumDecl, hasConsistentInitialValues) { - return isNoneEnumeratorsInitialized(Node) || - isOnlyFirstEnumeratorInitialized(Node) || - areAllEnumeratorsInitialized(Node); +AST_MATCHER_P(EnumDecl, hasConsistentInitialValues, bool, AllowRefs) { + return isNoneEnumeratorsInitialized(Node, AllowRefs) || + isOnlyFirstEnumeratorInitialized(Node, AllowRefs) || + areAllEnumeratorsInitialized(Node, AllowRefs); } -AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) { +AST_MATCHER_P(EnumDecl, hasZeroInitialValueForFirstEnumerator, bool, + AllowRefs) { const EnumDecl::enumerator_range Enumerators = Node.enumerators(); if (Enumerators.empty()) return false; const EnumConstantDecl *ECD = *Enumerators.begin(); - return isOnlyFirstEnumeratorInitialized(Node) && + return isOnlyFirstEnumeratorInitialized(Node, AllowRefs) && isInitializedByLiteral(ECD) && ECD->getInitVal().isZero(); } @@ -101,7 +127,7 @@ AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) { /// bitmask, evident when enumerators are only initialized with (potentially /// negative) integer literals, are ignored. This is also the case when all /// enumerators are powers of two (e.g., 0, 1, 2). -AST_MATCHER(EnumDecl, hasSequentialInitialValues) { +AST_MATCHER_P(EnumDecl, hasSequentialInitialValues, bool, AllowRefs) { const EnumDecl::enumerator_range Enumerators = Node.enumerators(); if (Enumerators.empty()) return false; @@ -111,6 +137,8 @@ AST_MATCHER(EnumDecl, hasSequentialInitialValues) { return false; bool AllEnumeratorsArePowersOfTwo = true; for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) { + if (isAllowedReference(Enumerator, AllowRefs)) + continue; const llvm::APSInt NewValue = Enumerator->getInitVal(); if (NewValue != ++PrevValue) return false; @@ -137,28 +165,34 @@ EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name, AllowExplicitZeroFirstInitialValue( Options.get("AllowExplicitZeroFirstInitialValue", true)), AllowExplicitSequentialInitialValues( - Options.get("AllowExplicitSequentialInitialValues", true)) {} + Options.get("AllowExplicitSequentialInitialValues", true)), + AllowExplicitReferencedInitialValues( + Options.get("AllowExplicitReferencedInitialValues", false)) {} void EnumInitialValueCheck::storeOptions(ClangTidyOptions::OptionMap &Opts) { Options.store(Opts, "AllowExplicitZeroFirstInitialValue", AllowExplicitZeroFirstInitialValue); Options.store(Opts, "AllowExplicitSequentialInitialValues", AllowExplicitSequentialInitialValues); + Options.store(Opts, "AllowExplicitReferencedInitialValues", + AllowExplicitReferencedInitialValues); } void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) { + const bool AllowRefs = AllowExplicitReferencedInitialValues; Finder->addMatcher(enumDecl(isDefinition(), unless(isMacro()), - unless(hasConsistentInitialValues())) + unless(hasConsistentInitialValues(AllowRefs))) .bind("inconsistent"), this); if (!AllowExplicitZeroFirstInitialValue) Finder->addMatcher( - enumDecl(isDefinition(), hasZeroInitialValueForFirstEnumerator()) + enumDecl(isDefinition(), + hasZeroInitialValueForFirstEnumerator(AllowRefs)) .bind("zero_first"), this); if (!AllowExplicitSequentialInitialValues) Finder->addMatcher(enumDecl(isDefinition(), unless(isMacro()), - hasSequentialInitialValues()) + hasSequentialInitialValues(AllowRefs)) .bind("sequential"), this); } @@ -215,7 +249,8 @@ void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) { "sequential initial value in '%0' can be ignored") << getName(Enum); for (const EnumConstantDecl *ECD : llvm::drop_begin(Enum->enumerators())) - cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); + if (!isAllowedReference(ECD, AllowExplicitReferencedInitialValues)) + cleanInitialValue(Diag, ECD, *Result.SourceManager, getLangOpts()); return; } } diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h index d03e26b4468f4..e2b9e6d8703f9 100644 --- a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h +++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h @@ -13,8 +13,8 @@ namespace clang::tidy::readability { -/// Enforces consistent style for enumerators' initialization, covering three -/// styles: none, first only, or all initialized explicitly. +/// Enforces consistent style for enumerators' initialization, covering four +/// styles: none, first only, all initialized explicitly, or allow referenced. /// /// For the user-facing documentation see: /// https://clang.llvm.org/extra/clang-tidy/checks/readability/enum-initial-value.html @@ -31,6 +31,7 @@ class EnumInitialValueCheck : public ClangTidyCheck { private: const bool AllowExplicitZeroFirstInitialValue; const bool AllowExplicitSequentialInitialValues; + const bool AllowExplicitReferencedInitialValues; }; } // namespace clang::tidy::readability diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index b1fd95db9e395..0d17b0ee3dde9 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -421,6 +421,9 @@ Changes in existing checks <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. + Added :option:`AllowExplicitReferencedInitialValues` option to support the + `INT09-C-EX1` exception, allowing enumerators initialized by referencing + another enumerator in the same enum (e.g., ``last = first``). - Improved :doc:`readability-implicit-bool-conversion <clang-tidy/checks/readability/implicit-bool-conversion>` check: 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 f59c433c51d0b..94b78af70a5e1 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 @@ -92,3 +92,20 @@ Options g0 = 1, // Not allowed if AllowExplicitSequentialInitialValues is false. g1 = 2, g2 = 3, + }; + +.. option:: AllowExplicitReferencedInitialValues + + If set to `true`, enumerators initialized by referencing another enumerator + in the same enum are allowed, and the remaining enumerators are checked for + consistency. This implements the ``INT09-C-EX1`` exception from the CERT C + Coding Standard. + Default is `false`. + + .. code-block:: c++ + + enum H { + h0, + h1, + h2 = h1, // Allowed if AllowExplicitReferencedInitialValues is true. + }; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs-combined.c b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs-combined.c new file mode 100644 index 0000000000000..715229a9b78f9 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs-combined.c @@ -0,0 +1,34 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-enum-initial-value.AllowExplicitZeroFirstInitialValue: false, \ +// RUN: readability-enum-initial-value.AllowExplicitSequentialInitialValues: false, \ +// RUN: readability-enum-initial-value.AllowExplicitReferencedInitialValues: true, \ +// RUN: }}' + +// Error: zero-first + self-ref, should still warn about the zero. +enum EZeroRef { + EZeroRef_a = 0, + // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: zero initial value for the first enumerator in 'EZeroRef' can be disregarded + // CHECK-FIXES: EZeroRef_a , + EZeroRef_b, + EZeroRef_last = EZeroRef_b, +}; + +// Error: sequential + self-ref, should still warn but not suggest +// removing the self-ref. +enum ESeqRef { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: sequential initial value in 'ESeqRef' can be ignored + ESeqRef_a = 1, + ESeqRef_b = 2, + // CHECK-FIXES: ESeqRef_b , + ESeqRef_c = 3, + // CHECK-FIXES: ESeqRef_c , + ESeqRef_alias = ESeqRef_a, +}; + +// OK: none + self-ref, no warnings. +enum ENoneRef { + ENoneRef_a, + ENoneRef_b, + ENoneRef_last = ENoneRef_b, +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.c b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.c new file mode 100644 index 0000000000000..96017524b6059 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.c @@ -0,0 +1,50 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-enum-initial-value.AllowExplicitReferencedInitialValues: true, \ +// RUN: }}' + +// OK: none + self-ref. +enum ERef1 { + ERef1_a, + ERef1_b, + ERef1_last = ERef1_b, +}; + +// OK: first-only + self-ref. +enum ERef2 { + ERef2_a = 0, + ERef2_b, + ERef2_last = ERef2_b, +}; + +// OK: all + self-ref. +enum ERef3 { + ERef3_a = 0, + ERef3_b = 1, + ERef3_last = ERef3_b, +}; + +// Error: cross-enum reference is not a self-ref. +enum ERefOther { + ERefOther_a, + ERefOther_b, +}; +enum ERefCross { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'ERefCross' are not consistent + ERefCross_a, + // CHECK-FIXES: ERefCross_a = 0, + ERefCross_b, + // CHECK-FIXES: ERefCross_b = 1, + ERefCross_last = ERefOther_b, +}; + +// Error: inconsistent even after ignoring self-refs. +enum ERefBad { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'ERefBad' are not consistent + ERefBad_a = 1, + ERefBad_b, + // CHECK-MESSAGES: :[[@LINE-1]]:3: note: uninitialized enumerator 'ERefBad_b' defined here + // CHECK-FIXES: ERefBad_b = 2, + ERefBad_c = 5, + ERefBad_alias = ERefBad_a, +}; diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.cpp new file mode 100644 index 0000000000000..c0b48b4a78331 --- /dev/null +++ b/clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value-allow-refs.cpp @@ -0,0 +1,35 @@ +// RUN: %check_clang_tidy %s readability-enum-initial-value %t -- \ +// RUN: -config='{CheckOptions: { \ +// RUN: readability-enum-initial-value.AllowExplicitReferencedInitialValues: true, \ +// RUN: }}' + +// OK: none + self-ref. +enum class ERef { + ERef_a, + ERef_b, + ERef_last = ERef_b, +}; + +// OK: first-only + self-ref. +enum class ERefFirst { + ERefFirst_a = 1, + ERefFirst_b, + ERefFirst_alias = ERefFirst_a, +}; + +// OK: all + self-ref. +enum class ERefAll { + ERefAll_a = 0, + ERefAll_b = 1, + ERefAll_last = ERefAll_b, +}; + +// Error: literal duplicate (not a reference). +enum class ERefErr { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'ERefErr' are not consistent + ERefErr_a, + // CHECK-FIXES: ERefErr_a = 0, + ERefErr_b, + // CHECK-FIXES: ERefErr_b = 1, + ERef_last = 1, +}; 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 fcf5b20ea4ee2..6242d4c26fe26 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 @@ -34,6 +34,16 @@ enum EAll { EAll_c = 4, }; +enum ERef { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'ERef' are not consistent + // CHECK-MESSAGES-ENABLE: :[[@LINE-2]]:1: warning: initial values in enum 'ERef' are not consistent + ERef_a, + // CHECK-FIXES: ERef_a = 0, + ERef_b, + // CHECK-FIXES: ERef_b = 1, + ERef_last = ERef_b, +}; + #define ENUMERATOR_1 EMacro1_b enum EMacro1 { // 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 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 7a97534fd8e2b..3c9b24e54338e 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 @@ -26,3 +26,12 @@ enum class EAll { EAll_b = 2, EAll_c = 3, }; + +enum class ERef { + // CHECK-MESSAGES: :[[@LINE-1]]:1: warning: initial values in enum 'ERef' are not consistent + ERef_a, + // CHECK-FIXES: ERef_a = 0, + ERef_b, + // CHECK-FIXES: ERef_b = 1, + ERef_last = ERef_b, +}; From 0efaf2d751b51f48fce0cf4e1a27034ce3f058c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Mon, 30 Mar 2026 23:04:15 +0200 Subject: [PATCH 2/3] fixup: use single backtick in docs and list changes in ReleaseNotes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Svensson <[email protected]> --- clang-tools-extra/docs/ReleaseNotes.rst | 15 +++++++++------ .../checks/readability/enum-initial-value.rst | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index 0d17b0ee3dde9..c317aa26b9f6b 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -418,12 +418,15 @@ Changes in existing checks ``[[noreturn]]`` functions. - 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. - Added :option:`AllowExplicitReferencedInitialValues` option to support the - `INT09-C-EX1` exception, allowing enumerators initialized by referencing - another enumerator in the same enum (e.g., ``last = first``). + <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. + + - Added :option:`AllowExplicitReferencedInitialValues` option to support + the `INT09-C-EX1` exception, allowing enumerators initialized by + referencing another enumerator in the same enum (e.g., ``last = first``). - Improved :doc:`readability-implicit-bool-conversion <clang-tidy/checks/readability/implicit-bool-conversion>` check: 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 94b78af70a5e1..4d48201e0415d 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 @@ -98,7 +98,7 @@ Options If set to `true`, enumerators initialized by referencing another enumerator in the same enum are allowed, and the remaining enumerators are checked for - consistency. This implements the ``INT09-C-EX1`` exception from the CERT C + consistency. This implements the `INT09-C-EX1` exception from the CERT C Coding Standard. Default is `false`. From 980a1bd2dd27487f95bba76ee2d14f427e26c4a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Svensson?= <[email protected]> Date: Tue, 31 Mar 2026 09:48:35 +0200 Subject: [PATCH 3/3] fixup: update ReleaseNotes by removing tag and use 80-char fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Björn Svensson <[email protected]> --- clang-tools-extra/docs/ReleaseNotes.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst index c317aa26b9f6b..670d5d288944c 100644 --- a/clang-tools-extra/docs/ReleaseNotes.rst +++ b/clang-tools-extra/docs/ReleaseNotes.rst @@ -421,12 +421,12 @@ Changes in existing checks <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. + uninitialized enumerator, making it easier to see which specific enumerators + need explicit initialization. - - Added :option:`AllowExplicitReferencedInitialValues` option to support - the `INT09-C-EX1` exception, allowing enumerators initialized by - referencing another enumerator in the same enum (e.g., ``last = first``). + - Added `AllowExplicitReferencedInitialValues` option to support the + `INT09-C-EX1` exception, allowing enumerators initialized by referencing + another enumerator in the same enum (e.g., ``last = first``). - Improved :doc:`readability-implicit-bool-conversion <clang-tidy/checks/readability/implicit-bool-conversion>` check: _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
