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 <[email protected]> Date: Sat, 9 May 2026 16:38:28 +0800 Subject: [PATCH 1/4] 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 <[email protected]> Date: Sun, 10 May 2026 16:37:41 +0800 Subject: [PATCH 2/4] 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); >From 5dd22530fb6b1e74a597209c9f1d400263d74976 Mon Sep 17 00:00:00 2001 From: Aaron Saw Min Sern <[email protected]> Date: Sun, 10 May 2026 16:40:07 +0800 Subject: [PATCH 3/4] remove redundant assertion when parsing brace --- clang/lib/Format/TokenAnnotator.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 61f0d800180b0..b9d2f4bcc56ea 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1217,7 +1217,6 @@ class AnnotatingParser { assert(!Scopes.empty()); Scopes.back() = getScopeType(OpeningBrace); if (CurrentToken->is(tok::r_brace)) { - assert(Scopes.back() == getScopeType(OpeningBrace)); Scopes.pop_back(); assert(OpeningBrace.Optional == CurrentToken->Optional); OpeningBrace.MatchingParen = CurrentToken; >From 397a34412373edb3d8b5e6662ee9d83b011908ae Mon Sep 17 00:00:00 2001 From: Aaron Saw Min Sern <[email protected]> Date: Mon, 11 May 2026 00:04:17 +0800 Subject: [PATCH 4/4] adjust the scope according to type modification when parsing brace --- clang/lib/Format/TokenAnnotator.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index b9d2f4bcc56ea..4da724be2bde4 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -1215,8 +1215,8 @@ class AnnotatingParser { unsigned CommaCount = 0; while (CurrentToken) { assert(!Scopes.empty()); - Scopes.back() = getScopeType(OpeningBrace); if (CurrentToken->is(tok::r_brace)) { + assert(Scopes.back() == getScopeType(OpeningBrace)); Scopes.pop_back(); assert(OpeningBrace.Optional == CurrentToken->Optional); OpeningBrace.MatchingParen = CurrentToken; @@ -1241,6 +1241,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); @@ -1249,16 +1250,20 @@ 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()) + if (Style.isJavaScript()) { OpeningBrace.overwriteFixedType(TT_DictLiteral); - else + Scopes.back() = getScopeType(OpeningBrace); + } else { IsBracedListComma = OpeningBrace.is(BK_BracedInit); + } ++CommaCount; } if (!consumeToken()) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
