https://github.com/owenca updated https://github.com/llvm/llvm-project/pull/153765
>From f870bbcc5501318a61fd0dfabf3de79e1414aa55 Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Fri, 15 Aug 2025 01:34:30 -0700 Subject: [PATCH] [clang-format] Add SpaceInEmptyBraces option Also set it to SIEB_Always for WebKit style. Closes #85525. Closes #93635. --- clang/docs/ClangFormatStyleOptions.rst | 48 ++++++++++++++++++--- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Format/Format.h | 47 ++++++++++++++++---- clang/lib/Format/Format.cpp | 24 +++++++++-- clang/lib/Format/TokenAnnotator.cpp | 22 +++++----- clang/lib/Format/UnwrappedLineFormatter.cpp | 3 +- clang/unittests/Format/ConfigParseTest.cpp | 12 +++++- clang/unittests/Format/FormatTest.cpp | 28 +++++++++++- 8 files changed, 155 insertions(+), 30 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 02986a94a656c..f12a84eb54155 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6483,13 +6483,51 @@ the configuration (without a prefix: ``Auto``). .. _SpaceInEmptyBlock: **SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>` - If ``true``, spaces will be inserted into ``{}``. + This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``. + +.. _SpaceInEmptyBraces: + +**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 22` :ref:`¶ <SpaceInEmptyBraces>` + Specifies when to insert a space in empty braces. + + .. note:: + + This option doesn't apply to initializer braces if + ``Cpp11BracedListStyle`` is set to ``true``. + + Possible values: + + * ``SIEB_Always`` (in configuration: ``Always``) + Always insert a space in empty braces. + + .. code-block:: c++ + + void f() { } + class Unit { }; + auto a = [] { }; + int x{ }; + + * ``SIEB_Block`` (in configuration: ``Block``) + Only insert a space in empty blocks. + + .. code-block:: c++ + + void f() { } + class Unit { }; + auto a = [] { }; + int x{}; + + * ``SIEB_Never`` (in configuration: ``Never``) + Never insert a space in empty braces. + + .. code-block:: c++ + + void f() {} + class Unit {}; + auto a = [] {}; + int x{}; - .. code-block:: c++ - true: false: - void f() { } vs. void f() {} - while (true) { } while (true) {} .. _SpaceInEmptyParentheses: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index fe6a48117df29..789d59af3a8d1 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -274,6 +274,7 @@ AST Matchers clang-format ------------ +- Add ``SpaceInEmptyBraces`` option and set it to ``Always`` for WebKit style. libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 31582a40de866..5dfdb23594610 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4813,14 +4813,45 @@ struct FormatStyle { /// \version 7 bool SpaceBeforeRangeBasedForLoopColon; - /// If ``true``, spaces will be inserted into ``{}``. - /// \code - /// true: false: - /// void f() { } vs. void f() {} - /// while (true) { } while (true) {} - /// \endcode + /// This option is **deprecated**. See ``Block`` of ``SpaceInEmptyBraces``. /// \version 10 - bool SpaceInEmptyBlock; + // bool SpaceInEmptyBlock; + + /// Style of when to insert a space in empty braces. + enum SpaceInEmptyBracesStyle : int8_t { + /// Always insert a space in empty braces. + /// \code + /// void f() { } + /// class Unit { }; + /// auto a = [] { }; + /// int x{ }; + /// \endcode + SIEB_Always, + /// Only insert a space in empty blocks. + /// \code + /// void f() { } + /// class Unit { }; + /// auto a = [] { }; + /// int x{}; + /// \endcode + SIEB_Block, + /// Never insert a space in empty braces. + /// \code + /// void f() {} + /// class Unit {}; + /// auto a = [] {}; + /// int x{}; + /// \endcode + SIEB_Never + }; + + /// Specifies when to insert a space in empty braces. + /// \note + /// This option doesn't apply to initializer braces if + /// ``Cpp11BracedListStyle`` is set to ``true``. + /// \endnote + /// \version 22 + SpaceInEmptyBracesStyle SpaceInEmptyBraces; /// If ``true``, spaces may be inserted into ``()``. /// This option is **deprecated**. See ``InEmptyParentheses`` of @@ -5494,7 +5525,7 @@ struct FormatStyle { SpaceBeforeRangeBasedForLoopColon == R.SpaceBeforeRangeBasedForLoopColon && SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets && - SpaceInEmptyBlock == R.SpaceInEmptyBlock && + SpaceInEmptyBraces == R.SpaceInEmptyBraces && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && SpacesInAngles == R.SpacesInAngles && SpacesInContainerLiterals == R.SpacesInContainerLiterals && diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 063780721423f..e3b22cdabaccd 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -763,6 +763,15 @@ struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> { } }; +template <> +struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> { + static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) { + IO.enumCase(Value, "Always", FormatStyle::SIEB_Always); + IO.enumCase(Value, "Block", FormatStyle::SIEB_Block); + IO.enumCase(Value, "Never", FormatStyle::SIEB_Never); + } +}; + template <> struct ScalarEnumerationTraits<FormatStyle::SpacesInAnglesStyle> { static void enumeration(IO &IO, FormatStyle::SpacesInAnglesStyle &Value) { IO.enumCase(Value, "Never", FormatStyle::SIAS_Never); @@ -931,6 +940,7 @@ template <> struct MappingTraits<FormatStyle> { bool DeriveLineEnding = true; bool UseCRLF = false; + bool SpaceInEmptyBlock = false; bool SpaceInEmptyParentheses = false; bool SpacesInConditionalStatement = false; bool SpacesInCStyleCastParentheses = false; @@ -960,6 +970,7 @@ template <> struct MappingTraits<FormatStyle> { IO.mapOptional("PointerBindsToType", Style.PointerAlignment); IO.mapOptional("SpaceAfterControlStatementKeyword", Style.SpaceBeforeParens); + IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock); IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses); IO.mapOptional("SpacesInConditionalStatement", SpacesInConditionalStatement); @@ -1193,7 +1204,7 @@ template <> struct MappingTraits<FormatStyle> { Style.SpaceBeforeRangeBasedForLoopColon); IO.mapOptional("SpaceBeforeSquareBrackets", Style.SpaceBeforeSquareBrackets); - IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock); + IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces); IO.mapOptional("SpacesBeforeTrailingComments", Style.SpacesBeforeTrailingComments); IO.mapOptional("SpacesInAngles", Style.SpacesInAngles); @@ -1276,6 +1287,13 @@ template <> struct MappingTraits<FormatStyle> { Style.LineEnding = FormatStyle::LE_DeriveCRLF; } + // If SpaceInEmptyBlock was specified but SpaceInEmptyBraces was not, + // initialize the latter from the former for backward compatibility. + if (SpaceInEmptyBlock && + Style.SpaceInEmptyBraces == FormatStyle::SIEB_Never) { + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block; + } + if (Style.SpacesInParens != FormatStyle::SIPO_Custom && (SpacesInParentheses || SpaceInEmptyParentheses || SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) { @@ -1677,7 +1695,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) { LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true; LLVMStyle.SpaceBeforeSquareBrackets = false; - LLVMStyle.SpaceInEmptyBlock = false; + LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEB_Never; LLVMStyle.SpacesBeforeTrailingComments = 1; LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never; LLVMStyle.SpacesInContainerLiterals = true; @@ -1984,7 +2002,7 @@ FormatStyle getWebKitStyle() { Style.ObjCSpaceAfterProperty = true; Style.PointerAlignment = FormatStyle::PAS_Left; Style.SpaceBeforeCpp11BracedList = true; - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Always; return Style; } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 4801d27b1395a..41d75682f783a 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4513,16 +4513,9 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, return Left.is(tok::hash); if (Left.isOneOf(tok::hashhash, tok::hash)) return Right.is(tok::hash); - if (Left.is(BK_Block) && Right.is(tok::r_brace) && - Right.MatchingParen == &Left && Line.Children.empty()) { - return Style.SpaceInEmptyBlock; - } if (Style.SpacesInParens == FormatStyle::SIPO_Custom) { - if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) || - (Left.is(tok::l_brace) && Left.isNot(BK_Block) && - Right.is(tok::r_brace) && Right.isNot(BK_Block))) { + if (Left.is(tok::l_paren) && Right.is(tok::r_paren)) return Style.SpacesInParensOptions.InEmptyParentheses; - } if (Style.SpacesInParensOptions.ExceptDoubleParentheses && Left.is(tok::r_paren) && Right.is(tok::r_paren)) { auto *InnerLParen = Left.MatchingParen; @@ -4800,8 +4793,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, Right.is(TT_ArraySubscriptLSquare))) { return false; } - if (Left.is(tok::l_brace) && Right.is(tok::r_brace)) - return !Left.Children.empty(); // No spaces in "{}". if ((Left.is(tok::l_brace) && Left.isNot(BK_Block)) || (Right.is(tok::r_brace) && Right.MatchingParen && Right.MatchingParen->isNot(BK_Block))) { @@ -4983,6 +4974,17 @@ bool TokenAnnotator::spaceRequiredBefore(const AnnotatedLine &Line, if (Left.is(tok::star) && Right.is(tok::comment)) return true; + if (Left.is(tok::l_brace) && Right.is(tok::r_brace) && + Left.Children.empty()) { + if (Left.is(BK_Block)) + return Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never; + if (Style.Cpp11BracedListStyle) { + return Style.SpacesInParens == FormatStyle::SIPO_Custom && + Style.SpacesInParensOptions.InEmptyParentheses; + } + return Style.SpaceInEmptyBraces == FormatStyle::SIEB_Always; + } + const auto *BeforeLeft = Left.Previous; if (IsCpp) { diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp index 0adf7ee9ed543..c938ff3965f9e 100644 --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -864,7 +864,8 @@ class LineJoiner { if (ShouldMerge()) { // We merge empty blocks even if the line exceeds the column limit. Tok->SpacesRequiredBefore = - (Style.SpaceInEmptyBlock || Line.Last->is(tok::comment)) ? 1 : 0; + Style.SpaceInEmptyBraces != FormatStyle::SIEB_Never || + Line.Last->is(tok::comment); Tok->CanBreakBefore = true; return 1; } else if (Limit != 0 && !Line.startsWithNamespace() && diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index 9de3cca71630d..7c993c0f8fd33 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -200,7 +200,6 @@ TEST(ConfigParseTest, ParsesConfigurationBools) { CHECK_PARSE_BOOL(RemoveSemicolon); CHECK_PARSE_BOOL(SkipMacroDefinitionBody); CHECK_PARSE_BOOL(SpacesInSquareBrackets); - CHECK_PARSE_BOOL(SpaceInEmptyBlock); CHECK_PARSE_BOOL(SpacesInContainerLiterals); CHECK_PARSE_BOOL(SpaceAfterCStyleCast); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); @@ -688,6 +687,17 @@ TEST(ConfigParseTest, ParsesConfiguration) { SpaceBeforeParens, FormatStyle::SBPO_ControlStatementsExceptControlMacros); + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Never; + CHECK_PARSE("SpaceInEmptyBraces: Always", SpaceInEmptyBraces, + FormatStyle::SIEB_Always); + CHECK_PARSE("SpaceInEmptyBraces: Block", SpaceInEmptyBraces, + FormatStyle::SIEB_Block); + CHECK_PARSE("SpaceInEmptyBraces: Never", SpaceInEmptyBraces, + FormatStyle::SIEB_Never); + // For backward compatibility: + CHECK_PARSE("SpaceInEmptyBlock: true", SpaceInEmptyBraces, + FormatStyle::SIEB_Block); + // For backward compatibility: Style.SpacesInParens = FormatStyle::SIPO_Never; Style.SpacesInParensOptions = {}; diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 96cc650f52a5d..15906e2e99d4a 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -7055,7 +7055,7 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { verifyFormat("enum E {};"); verifyFormat("enum E {}"); FormatStyle Style = getLLVMStyle(); - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block; verifyFormat("void f() { }", "void f() {}", Style); Style.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Empty; verifyFormat("{ }", Style); @@ -7083,7 +7083,7 @@ TEST_F(FormatTest, PutEmptyBlocksIntoOneLine) { Style); Style = getLLVMStyle(FormatStyle::LK_CSharp); - Style.SpaceInEmptyBlock = true; + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block; verifyFormat("Event += () => { };", Style); } @@ -25584,6 +25584,30 @@ TEST_F(FormatTest, SpacesInConditionalStatement) { verifyFormat("MYIF( a )\n return;\nelse\n return;", Spaces); } +TEST_F(FormatTest, SpaceInEmptyBraces) { + constexpr StringRef Code("void f() {}\n" + "class Unit {};\n" + "auto a = [] {};\n" + "int x{};"); + verifyFormat(Code); + + auto Style = getWebKitStyle(); + EXPECT_EQ(Style.SpaceInEmptyBraces, FormatStyle::SIEB_Always); + + verifyFormat("void f() { }\n" + "class Unit { };\n" + "auto a = [] { };\n" + "int x { };", + Code, Style); + + Style.SpaceInEmptyBraces = FormatStyle::SIEB_Block; + verifyFormat("void f() { }\n" + "class Unit { };\n" + "auto a = [] { };\n" + "int x {};", + Code, Style); +} + TEST_F(FormatTest, AlternativeOperators) { // Test case for ensuring alternate operators are not // combined with their right most neighbour. _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits