[clang] [clang-format] Add AlignConsecutiveEnums (PR #194154)
via cfe-commits
cfe-commits at lists.llvm.org
Sun May 10 01:38:28 PDT 2026
https://github.com/aaronsms updated https://github.com/llvm/llvm-project/pull/194154
>From 6d55f8117324298b3fcb50881ce4fe045471f95b Mon Sep 17 00:00:00 2001
From: Aaron Saw Min Sern <aaron at aaronsms.com>
Date: Sat, 9 May 2026 16:38:28 +0800
Subject: [PATCH 1/2] add option to only align enum assignments for
AlignConsecutiveAssignments
---
clang/docs/ClangFormatStyleOptions.rst | 77 ++++++++++++++++++++++
clang/docs/ReleaseNotes.rst | 2 +
clang/include/clang/Format/Format.h | 11 ++++
clang/lib/Format/Format.cpp | 16 +++--
clang/lib/Format/FormatToken.h | 1 +
clang/lib/Format/TokenAnnotator.cpp | 17 ++++-
clang/lib/Format/TokenAnnotator.h | 2 +
clang/lib/Format/WhitespaceManager.cpp | 13 +++-
clang/unittests/Format/AlignmentTest.cpp | 23 ++++++-
clang/unittests/Format/ConfigParseTest.cpp | 72 ++++++++++----------
10 files changed, 189 insertions(+), 45 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index fe8dfa406bc32..55f5fbf8560f3 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -402,6 +402,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -560,6 +571,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -718,6 +740,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -877,6 +910,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -1155,6 +1199,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -1311,6 +1366,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
@@ -1467,6 +1533,17 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ aligned.
+
+ .. code-block:: c++
+
+ enum ValueKind {
+ VK_Argument = 1,
+ VK_BasicBlock = 2,
+ VK_Segment = 8,
+ };
+
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
put all assignment operators to the right of the left hand side.
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c5c8c1fa12e7a..7f36408d1a55f 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -697,6 +697,8 @@ clang-format
- Extend ``BreakBinaryOperations`` to accept a structured configuration with
per-operator break rules and minimum chain length gating via ``PerOperator``.
- Add ``AllowShortRecordOnASingleLine`` option and set it to ``EmptyAndAttached`` for LLVM style.
+- Add ``EnumAssignments`` option to ``AlignConsecutiveAssignments`` for aligning
+ enum assignments without affecting other assignments.
libclang
--------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index f89323c71713b..80589e8bbfa5e 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -236,6 +236,16 @@ struct FormatStyle {
/// int (*f)();
/// \endcode
bool AlignFunctionPointers;
+ /// Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
+ /// aligned.
+ /// \code
+ /// enum ValueKind {
+ /// VK_Argument = 1,
+ /// VK_BasicBlock = 2,
+ /// VK_Segment = 8,
+ /// };
+ /// \endcode
+ bool EnumAssignments;
/// Only for ``AlignConsecutiveAssignments``. Whether short assignment
/// operators are left-padded to the same length as long ones in order to
/// put all assignment operators to the right of the left hand side.
@@ -259,6 +269,7 @@ struct FormatStyle {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCompound == R.AlignCompound &&
+ EnumAssignments == R.EnumAssignments &&
AlignFunctionDeclarations == R.AlignFunctionDeclarations &&
AlignFunctionPointers == R.AlignFunctionPointers &&
PadOperators == R.PadOperators;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 8d447177a18a7..249fa1f950f9a 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -62,25 +62,29 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
+ /*AlignFunctionPointers=*/false,
+ /*EnumAssignments=*/true, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLines",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
+ /*AlignFunctionPointers=*/false,
+ /*EnumAssignments=*/true, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
+ /*AlignFunctionPointers=*/false,
+ /*EnumAssignments=*/true, /*PadOperators=*/true}));
IO.enumCase(Value, "AcrossEmptyLinesAndComments",
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/true, /*AcrossEmptyLines=*/true,
/*AcrossComments=*/true, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
+ /*AlignFunctionPointers=*/false,
+ /*EnumAssignments=*/true, /*PadOperators=*/true}));
// For backward compatibility.
IO.enumCase(Value, "true",
@@ -88,7 +92,8 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
{/*Enabled=*/true, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true}));
+ /*AlignFunctionPointers=*/false,
+ /*EnumAssignments=*/true, /*PadOperators=*/true}));
IO.enumCase(Value, "false", FormatStyle::AlignConsecutiveStyle{});
}
@@ -100,6 +105,7 @@ template <> struct MappingTraits<FormatStyle::AlignConsecutiveStyle> {
IO.mapOptional("AlignFunctionDeclarations",
Value.AlignFunctionDeclarations);
IO.mapOptional("AlignFunctionPointers", Value.AlignFunctionPointers);
+ IO.mapOptional("EnumAssignments", Value.EnumAssignments);
IO.mapOptional("PadOperators", Value.PadOperators);
}
};
diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h
index 68d94b087136d..1d8f0f1cfe412 100644
--- a/clang/lib/Format/FormatToken.h
+++ b/clang/lib/Format/FormatToken.h
@@ -76,6 +76,7 @@ namespace format {
TYPE(DoWhile) \
TYPE(ElseLBrace) \
TYPE(ElseRBrace) \
+ TYPE(EnumEqual) \
TYPE(EnumLBrace) \
TYPE(EnumRBrace) \
TYPE(EnumUnderlyingTypeColon) \
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 898759cb8ea1b..7a555e05ec08b 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -139,6 +139,8 @@ class AnnotatingParser {
case TT_StructLBrace:
case TT_UnionLBrace:
return ST_Class;
+ case TT_EnumLBrace:
+ return ST_Enum;
case TT_CompoundRequirementLBrace:
return ST_CompoundRequirement;
default:
@@ -1232,6 +1234,7 @@ class AnnotatingParser {
return false;
updateParameterCount(&OpeningBrace, CurrentToken);
if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
+ assert(!Scopes.empty());
FormatToken *Previous = CurrentToken->getPreviousNonComment();
if (Previous->is(TT_JsTypeOptionalQuestion))
Previous = Previous->getPreviousNonComment();
@@ -1239,6 +1242,7 @@ class AnnotatingParser {
(!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
Style.isProto()) {
OpeningBrace.setType(TT_DictLiteral);
+ Scopes.back() = getScopeType(OpeningBrace);
if (Previous->Tok.getIdentifierInfo() ||
Previous->is(tok::string_literal)) {
Previous->setType(TT_SelectorName);
@@ -1247,16 +1251,21 @@ class AnnotatingParser {
if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&
!Style.isTableGen()) {
OpeningBrace.setType(TT_DictLiteral);
+ Scopes.back() = getScopeType(OpeningBrace);
} else if (Style.isJavaScript()) {
OpeningBrace.overwriteFixedType(TT_DictLiteral);
+ Scopes.back() = getScopeType(OpeningBrace);
}
}
bool IsBracedListComma = false;
if (CurrentToken->is(tok::comma)) {
- if (Style.isJavaScript())
+ assert(!Scopes.empty());
+ if (Style.isJavaScript()) {
OpeningBrace.overwriteFixedType(TT_DictLiteral);
- else
+ Scopes.back() = getScopeType(OpeningBrace);
+ } else {
IsBracedListComma = OpeningBrace.is(BK_BracedInit);
+ }
++CommaCount;
}
if (!consumeToken())
@@ -1835,6 +1844,10 @@ class AnnotatingParser {
// In TableGen, there must be a value after "=";
if (Style.isTableGen() && !parseTableGenValue())
return false;
+ if ((CurrentToken && CurrentToken->is(tok::numeric_constant)) &&
+ (!Scopes.empty() && Scopes.back() == ST_Enum)) {
+ Tok->setFinalizedType(TT_EnumEqual);
+ }
break;
default:
break;
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 597dd890ee990..33c7df9d0f949 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -40,6 +40,8 @@ enum LineType {
enum ScopeType {
// Contained in class declaration/definition.
ST_Class,
+ // Contained in enum declaration/definition.
+ ST_Enum,
// Contained in compound requirement.
ST_CompoundRequirement,
// Contained in other blocks (function, lambda, loop, if/else, child, etc).
diff --git a/clang/lib/Format/WhitespaceManager.cpp b/clang/lib/Format/WhitespaceManager.cpp
index 74aa8a2795150..4a72abbfa9ec3 100644
--- a/clang/lib/Format/WhitespaceManager.cpp
+++ b/clang/lib/Format/WhitespaceManager.cpp
@@ -813,8 +813,10 @@ void WhitespaceManager::alignConsecutiveMacros() {
}
void WhitespaceManager::alignConsecutiveAssignments() {
- if (!Style.AlignConsecutiveAssignments.Enabled)
+ if (!Style.AlignConsecutiveAssignments.Enabled &&
+ !Style.AlignConsecutiveAssignments.EnumAssignments) {
return;
+ }
AlignTokens(
Style,
@@ -827,6 +829,15 @@ void WhitespaceManager::alignConsecutiveAssignments() {
if (&C != &Changes.back() && (&C + 1)->NewlinesBefore > 0)
return false;
+ // Align enum '=' when EnumAssignments is enabled.
+ if (Style.AlignConsecutiveAssignments.EnumAssignments &&
+ C.Tok->is(TT_EnumEqual)) {
+ return true;
+ }
+
+ if (!Style.AlignConsecutiveAssignments.Enabled)
+ return false;
+
// Do not align operator= overloads.
FormatToken *Previous = C.Tok->getPreviousNonComment();
if (Previous && Previous->is(tok::kw_operator))
diff --git a/clang/unittests/Format/AlignmentTest.cpp b/clang/unittests/Format/AlignmentTest.cpp
index 2f49c5c7875a4..6109fc276319c 100644
--- a/clang/unittests/Format/AlignmentTest.cpp
+++ b/clang/unittests/Format/AlignmentTest.cpp
@@ -1135,6 +1135,25 @@ TEST_F(AlignmentTest, ConsecutiveAssignmentsAcrossEmptyLinesAndComments) {
Alignment);
}
+TEST_F(AlignmentTest, ConsecutiveEnumAssignments) {
+ FormatStyle Alignment = getLLVMStyle();
+ Alignment.AlignConsecutiveAssignments.EnumAssignments = true;
+ verifyFormat("enum ValueKind {\n"
+ " VK_Argument = 1,\n"
+ " VK_BasicBlock = 2,\n"
+ " VK_Segment = 8,\n"
+ "};",
+ Alignment);
+ Alignment.AlignConsecutiveAssignments.Enabled = true;
+ Alignment.AlignConsecutiveAssignments.EnumAssignments = false;
+ verifyFormat("enum ValueKind {\n"
+ " VK_Argument = 1,\n"
+ " VK_BasicBlock = 2,\n"
+ " VK_Segment = 8,\n"
+ "};",
+ Alignment);
+}
+
TEST_F(AlignmentTest, ConsecutiveCompoundAssignments) {
FormatStyle Alignment = getLLVMStyle();
Alignment.AlignConsecutiveAssignments.Enabled = true;
@@ -2363,14 +2382,14 @@ TEST_F(AlignmentTest, AlignWithLineBreaks) {
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/false,
/*AlignFunctionPointers=*/false,
- /*PadOperators=*/true}));
+ /*EnumAssignments=*/false, /*PadOperators=*/true}));
EXPECT_EQ(Style.AlignConsecutiveDeclarations,
FormatStyle::AlignConsecutiveStyle(
{/*Enabled=*/false, /*AcrossEmptyLines=*/false,
/*AcrossComments=*/false, /*AlignCompound=*/false,
/*AlignFunctionDeclarations=*/true,
/*AlignFunctionPointers=*/false,
- /*PadOperators=*/false}));
+ /*EnumAssignments=*/false, /*PadOperators=*/false}));
verifyFormat("void foo() {\n"
" int myVar = 5;\n"
" double x = 3.14;\n"
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 498e44b190ef2..9c1b870796454 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -338,44 +338,44 @@ TEST(ConfigParseTest, ParsesConfiguration) {
do { \
Style.FIELD.Enabled = true; \
CHECK_PARSE(#FIELD ": None", FIELD, FormatStyle::AlignConsecutiveStyle{}); \
- CHECK_PARSE( \
- #FIELD ": Consecutive", FIELD, \
- FormatStyle::AlignConsecutiveStyle( \
- {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
- /*AcrossComments=*/false, /*AlignCompound=*/false, \
- /*AlignFunctionDeclarations=*/true, \
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \
- CHECK_PARSE( \
- #FIELD ": AcrossEmptyLines", FIELD, \
- FormatStyle::AlignConsecutiveStyle( \
- {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \
- /*AcrossComments=*/false, /*AlignCompound=*/false, \
- /*AlignFunctionDeclarations=*/true, \
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \
- CHECK_PARSE( \
- #FIELD ": AcrossComments", FIELD, \
- FormatStyle::AlignConsecutiveStyle( \
- {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
- /*AcrossComments=*/true, /*AlignCompound=*/false, \
- /*AlignFunctionDeclarations=*/true, \
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \
- CHECK_PARSE( \
- #FIELD ": AcrossEmptyLinesAndComments", FIELD, \
- FormatStyle::AlignConsecutiveStyle( \
- {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \
- /*AcrossComments=*/true, /*AlignCompound=*/false, \
- /*AlignFunctionDeclarations=*/true, \
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \
+ CHECK_PARSE(#FIELD ": Consecutive", FIELD, \
+ FormatStyle::AlignConsecutiveStyle( \
+ {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
+ /*AcrossComments=*/false, /*AlignCompound=*/false, \
+ /*AlignFunctionDeclarations=*/true, \
+ /*AlignFunctionPointers=*/false, \
+ /*EnumAssignments =*/true, /*PadOperators=*/true})); \
+ CHECK_PARSE(#FIELD ": AcrossEmptyLines", FIELD, \
+ FormatStyle::AlignConsecutiveStyle( \
+ {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \
+ /*AcrossComments=*/false, /*AlignCompound=*/false, \
+ /*AlignFunctionDeclarations=*/true, \
+ /*AlignFunctionPointers=*/false, \
+ /*EnumAssignments =*/true, /*PadOperators=*/true})); \
+ CHECK_PARSE(#FIELD ": AcrossComments", FIELD, \
+ FormatStyle::AlignConsecutiveStyle( \
+ {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
+ /*AcrossComments=*/true, /*AlignCompound=*/false, \
+ /*AlignFunctionDeclarations=*/true, \
+ /*AlignFunctionPointers=*/false, \
+ /*EnumAssignments =*/true, /*PadOperators=*/true})); \
+ CHECK_PARSE(#FIELD ": AcrossEmptyLinesAndComments", FIELD, \
+ FormatStyle::AlignConsecutiveStyle( \
+ {/*Enabled=*/true, /*AcrossEmptyLines=*/true, \
+ /*AcrossComments=*/true, /*AlignCompound=*/false, \
+ /*AlignFunctionDeclarations=*/true, \
+ /*AlignFunctionPointers=*/false, \
+ /*EnumAssignments =*/true, /*PadOperators=*/true})); \
/* For backwards compability, false / true should still parse */ \
CHECK_PARSE(#FIELD ": false", FIELD, \
FormatStyle::AlignConsecutiveStyle{}); \
- CHECK_PARSE( \
- #FIELD ": true", FIELD, \
- FormatStyle::AlignConsecutiveStyle( \
- {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
- /*AcrossComments=*/false, /*AlignCompound=*/false, \
- /*AlignFunctionDeclarations=*/true, \
- /*AlignFunctionPointers=*/false, /*PadOperators=*/true})); \
+ CHECK_PARSE(#FIELD ": true", FIELD, \
+ FormatStyle::AlignConsecutiveStyle( \
+ {/*Enabled=*/true, /*AcrossEmptyLines=*/false, \
+ /*AcrossComments=*/false, /*AlignCompound=*/false, \
+ /*AlignFunctionDeclarations=*/true, \
+ /*AlignFunctionPointers=*/false, \
+ /*EnumAssignments =*/true, /*PadOperators=*/true})); \
\
CHECK_PARSE_NESTED_BOOL(FIELD, Enabled); \
CHECK_PARSE_NESTED_BOOL(FIELD, AcrossEmptyLines); \
@@ -383,8 +383,10 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE_NESTED_BOOL(FIELD, AlignCompound); \
CHECK_PARSE_NESTED_BOOL(FIELD, AlignFunctionDeclarations); \
CHECK_PARSE_NESTED_BOOL(FIELD, AlignFunctionPointers); \
+ CHECK_PARSE_NESTED_BOOL(FIELD, EnumAssignments); \
CHECK_PARSE_NESTED_BOOL(FIELD, PadOperators); \
} while (false)
+ // @todo
CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveAssignments);
CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveBitFields);
>From 90ef0107640261bf2bf1a5350b5a4b1e0e675474 Mon Sep 17 00:00:00 2001
From: Aaron Saw Min Sern <aaron at aaronsms.com>
Date: Sun, 10 May 2026 16:37:41 +0800
Subject: [PATCH 2/2] annotate enum assignments with RHS besides numeric
constant
---
clang/docs/ClangFormatStyleOptions.rst | 98 +++++++---------------
clang/include/clang/Format/Format.h | 15 ++--
clang/lib/Format/TokenAnnotator.cpp | 20 ++---
clang/unittests/Format/ConfigParseTest.cpp | 1 -
4 files changed, 39 insertions(+), 95 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 55f5fbf8560f3..6c237f0065f18 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -402,16 +402,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -571,16 +565,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -740,16 +728,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -910,16 +892,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -1199,16 +1175,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -1366,16 +1336,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
@@ -1533,16 +1497,10 @@ the configuration (without a prefix: ``Auto``).
int *p;
int (*f)();
- * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- aligned.
-
- .. code-block:: c++
-
- enum ValueKind {
- VK_Argument = 1,
- VK_BasicBlock = 2,
- VK_Segment = 8,
- };
+ * ``bool EnumAssignments`` Only for ``AlignConsecutiveAssignments``.
+ Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ setting this to ``true`` forces alignment for enum assignments only.
+ If ``Enabled`` is ``true``, enum assignments are always aligned.
* ``bool PadOperators`` Only for ``AlignConsecutiveAssignments``. Whether short assignment
operators are left-padded to the same length as long ones in order to
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index 80589e8bbfa5e..605a33e4fb406 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -236,15 +236,10 @@ struct FormatStyle {
/// int (*f)();
/// \endcode
bool AlignFunctionPointers;
- /// Only for ``AlignConsecutiveAssignments``. Whether enum assignments are
- /// aligned.
- /// \code
- /// enum ValueKind {
- /// VK_Argument = 1,
- /// VK_BasicBlock = 2,
- /// VK_Segment = 8,
- /// };
- /// \endcode
+ /// Only for ``AlignConsecutiveAssignments``.
+ /// Whether enum assignments are aligned. If ``Enabled`` is ``false``,
+ /// setting this to ``true`` forces alignment for enum assignments only.
+ /// If ``Enabled`` is ``true``, enum assignments are always aligned.
bool EnumAssignments;
/// Only for ``AlignConsecutiveAssignments``. Whether short assignment
/// operators are left-padded to the same length as long ones in order to
@@ -269,9 +264,9 @@ struct FormatStyle {
return Enabled == R.Enabled && AcrossEmptyLines == R.AcrossEmptyLines &&
AcrossComments == R.AcrossComments &&
AlignCompound == R.AlignCompound &&
- EnumAssignments == R.EnumAssignments &&
AlignFunctionDeclarations == R.AlignFunctionDeclarations &&
AlignFunctionPointers == R.AlignFunctionPointers &&
+ EnumAssignments == R.EnumAssignments &&
PadOperators == R.PadOperators;
}
bool operator!=(const AlignConsecutiveStyle &R) const {
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 7a555e05ec08b..61f0d800180b0 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1214,8 +1214,9 @@ class AnnotatingParser {
unsigned CommaCount = 0;
while (CurrentToken) {
+ assert(!Scopes.empty());
+ Scopes.back() = getScopeType(OpeningBrace);
if (CurrentToken->is(tok::r_brace)) {
- assert(!Scopes.empty());
assert(Scopes.back() == getScopeType(OpeningBrace));
Scopes.pop_back();
assert(OpeningBrace.Optional == CurrentToken->Optional);
@@ -1234,7 +1235,6 @@ class AnnotatingParser {
return false;
updateParameterCount(&OpeningBrace, CurrentToken);
if (CurrentToken->isOneOf(tok::colon, tok::l_brace, tok::less)) {
- assert(!Scopes.empty());
FormatToken *Previous = CurrentToken->getPreviousNonComment();
if (Previous->is(TT_JsTypeOptionalQuestion))
Previous = Previous->getPreviousNonComment();
@@ -1242,7 +1242,6 @@ class AnnotatingParser {
(!Contexts.back().ColonIsDictLiteral || !IsCpp)) ||
Style.isProto()) {
OpeningBrace.setType(TT_DictLiteral);
- Scopes.back() = getScopeType(OpeningBrace);
if (Previous->Tok.getIdentifierInfo() ||
Previous->is(tok::string_literal)) {
Previous->setType(TT_SelectorName);
@@ -1251,21 +1250,16 @@ class AnnotatingParser {
if (CurrentToken->is(tok::colon) && OpeningBrace.is(TT_Unknown) &&
!Style.isTableGen()) {
OpeningBrace.setType(TT_DictLiteral);
- Scopes.back() = getScopeType(OpeningBrace);
} else if (Style.isJavaScript()) {
OpeningBrace.overwriteFixedType(TT_DictLiteral);
- Scopes.back() = getScopeType(OpeningBrace);
}
}
bool IsBracedListComma = false;
if (CurrentToken->is(tok::comma)) {
- assert(!Scopes.empty());
- if (Style.isJavaScript()) {
+ if (Style.isJavaScript())
OpeningBrace.overwriteFixedType(TT_DictLiteral);
- Scopes.back() = getScopeType(OpeningBrace);
- } else {
+ else
IsBracedListComma = OpeningBrace.is(BK_BracedInit);
- }
++CommaCount;
}
if (!consumeToken())
@@ -1844,10 +1838,8 @@ class AnnotatingParser {
// In TableGen, there must be a value after "=";
if (Style.isTableGen() && !parseTableGenValue())
return false;
- if ((CurrentToken && CurrentToken->is(tok::numeric_constant)) &&
- (!Scopes.empty() && Scopes.back() == ST_Enum)) {
+ if (!Scopes.empty() && Scopes.back() == ST_Enum)
Tok->setFinalizedType(TT_EnumEqual);
- }
break;
default:
break;
@@ -5718,7 +5710,7 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line,
return getTokenReferenceAlignment(Right) != FormatStyle::PAS_Left;
}
if ((Right.is(TT_BinaryOperator) && Left.isNot(tok::l_paren)) ||
- (Left.isOneOf(TT_BinaryOperator, TT_ConditionalExpr) &&
+ (Left.isOneOf(TT_BinaryOperator, TT_EnumEqual, TT_ConditionalExpr) &&
Right.isNot(tok::r_paren))) {
return true;
}
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 9c1b870796454..53994741a48f6 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -386,7 +386,6 @@ TEST(ConfigParseTest, ParsesConfiguration) {
CHECK_PARSE_NESTED_BOOL(FIELD, EnumAssignments); \
CHECK_PARSE_NESTED_BOOL(FIELD, PadOperators); \
} while (false)
- // @todo
CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveAssignments);
CHECK_ALIGN_CONSECUTIVE(AlignConsecutiveBitFields);
More information about the cfe-commits
mailing list