[clang] [clang-format] Add SpaceInEmptyBraces option (PR #153765)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 15 18:54:55 PDT 2025
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 <owenpiano at 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.
More information about the cfe-commits
mailing list