Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 97 additions & 3 deletions clang/docs/ClangFormatStyleOptions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6327,12 +6327,106 @@ the configuration (without a prefix: ``Auto``).

**SpaceInEmptyBlock** (``Boolean``) :versionbadge:`clang-format 10` :ref:`¶ <SpaceInEmptyBlock>`
If ``true``, spaces will be inserted into ``{}``.
This option is **deprecated**. The previous behavior is preserved by using
``SpaceInEmptyBraces`` with ``Custom`` and by setting ``Block`` in
``SpaceInEmptyBracesOptions`` to ``true``.

.. _SpaceInEmptyBraces:

**SpaceInEmptyBraces** (``SpaceInEmptyBracesStyle``) :versionbadge:`clang-format 20` :ref:`¶ <SpaceInEmptyBraces>`
Defines in which cases spaces will be inserted in empty braces.

Possible values:

* ``SIEBO_Never`` (in configuration: ``Never``)
Never put a space in empty braces.

.. code-block:: c++

void f() {}
T x{};
while (true) {}
struct U1 {};
union U2 {};
class U3 {};
enum U4 {};

* ``SIEBO_Always`` (in configuration: ``Always``)
Always put a space in empty braces.

* ``SIEBO_Custom`` (in configuration: ``Custom``)
Configure each individual space in empty braces in
`SpacesInEmptyBracesOptions`.



.. _SpaceInEmptyBracesOptions:

**SpaceInEmptyBracesOptions** (``SpaceInEmptyBracesCustom``) :versionbadge:`clang-format 20` :ref:`¶ <SpaceInEmptyBracesOptions>`
Control of individual spaces in empty braces.

If ``SpaceInEmptyBraces`` is set to ``Custom``, use this to specify
how each individual space in empty braces case should be handled.
Otherwise, this is ignored.

.. code-block:: yaml

# Example of usage:
SpaceInEmptyBraces: Custom
SpaceInEmptyBracesOptions:
Function: true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can these be Never/Always/Leave

Record: false
InitList: true
Block: false

Nested configuration flags:

Precise control over the spacing in empty braces.

.. code-block:: c++

true: false:
void f() { } vs. void f() {}
while (true) { } while (true) {}
# Should be declared this way:
SpaceInEmptyBraces: Custom
SpaceInEmptyBracesOptions:
Function: true
Record: false
InitList: true
Block: false

* ``bool Function`` Put a space in empty braces of function definition.

.. code-block:: c++

true: false:
void f() { } vs. void f() {}

* ``bool Record`` Put a space in empty braces of record/struct definition.

.. code-block:: c++

true: false:
struct U1 { }; vs. struct U1 {};
union U2 { }; union U2 {};
class U3 { }; class U3 {};
enum U4 { }; enum U4 {};

* ``bool InitList`` Put a space in empty braces of initializer list.

.. code-block:: c++

true: false:
T x{ }; vs. T x{};

* ``bool Block`` Put a space in empty braces of other blocks, including functions and
record, compatible with ``SpaceInEmptyBlock``.

.. code-block:: c++

true: false:
void f() { } vs. void f() {}
enum Unit { }; enum Unit {};
while (true) { } while (true) {}


.. _SpaceInEmptyParentheses:

Expand Down
114 changes: 107 additions & 7 deletions clang/include/clang/Format/Format.h
Original file line number Diff line number Diff line change
Expand Up @@ -4668,13 +4668,11 @@ struct FormatStyle {
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**. The previous behavior is preserved by using
/// ``SpaceInEmptyBraces`` with ``Custom`` and by setting ``Block`` in
/// ``SpaceInEmptyBracesOptions`` to ``true``.
/// \version 10
bool SpaceInEmptyBlock;
// bool SpaceInEmptyBlock;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry I don't understand are you removing this?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was reviewing this PR and running into some issues related to https://reviews.llvm.org/D68415. I felt that we had to bite the bullet and add a new boolean option like the author did initially.

Copy link
Contributor

@owenca owenca Jan 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we might be able to support the following enumerated values:

  • Always (WebKit default)
  • Block (which would deprecate SpaceInEmptyBlock)
  • Leave (to be implemented in this patch or a follow-up patch)
  • Never (LLVM default)


/// If ``true``, spaces may be inserted into ``()``.
/// This option is **deprecated**. See ``InEmptyParentheses`` of
Expand Down Expand Up @@ -4913,6 +4911,107 @@ struct FormatStyle {
/// \version 17
SpacesInParensCustom SpacesInParensOptions;

/// Different ways to put a space in empty braces.
enum SpaceInEmptyBracesStyle : int8_t {
/// Never put a space in empty braces.
/// \code
/// void f() {}
/// T x{};
/// while (true) {}
/// struct U1 {};
/// union U2 {};
/// class U3 {};
/// enum U4 {};
/// \endcode
SIEBO_Never,
/// Always put a space in empty braces.
SIEBO_Always,
/// Configure each individual space in empty braces in
/// `SpacesInEmptyBracesOptions`.
SIEBO_Custom,
};

/// Defines in which cases spaces will be inserted in empty braces.
/// \version 20
SpaceInEmptyBracesStyle SpaceInEmptyBraces;

/// Precise control over the spacing in empty braces.
/// \code
/// # Should be declared this way:
/// SpaceInEmptyBraces: Custom
/// SpaceInEmptyBracesOptions:
/// Function: true
/// Record: false
/// InitList: true
/// Block: false
/// \endcode
struct SpaceInEmptyBracesCustom {
/// Put a space in empty braces of function definition.
/// \code
/// true: false:
/// void f() { } vs. void f() {}
/// \endcode
bool Function;
/// Put a space in empty braces of record/struct definition.
/// \code
/// true: false:
/// struct U1 { }; vs. struct U1 {};
/// union U2 { }; union U2 {};
/// class U3 { }; class U3 {};
/// enum U4 { }; enum U4 {};
/// \endcode
bool Record;
/// Put a space in empty braces of initializer list.
/// \code
/// true: false:
/// T x{ }; vs. T x{};
/// \endcode
bool InitList;
/// Put a space in empty braces of other blocks, including functions and
/// record, compatible with ``SpaceInEmptyBlock``.
/// \code
/// true: false:
/// void f() { } vs. void f() {}
/// enum Unit { }; enum Unit {};
/// while (true) { } while (true) {}
/// \endcode
bool Block;

SpaceInEmptyBracesCustom()
: Function(false), Record(false), InitList(false), Block(false) {}

SpaceInEmptyBracesCustom(bool Function, bool Record, bool InitList,
bool Block)
: Function(Function), Record(Record), InitList(InitList), Block(Block) {
}

bool operator==(const SpaceInEmptyBracesCustom &R) const {
return Function == R.Function && Record == R.Record &&
InitList == R.InitList && Block == R.Block;
}

bool operator!=(const SpaceInEmptyBracesCustom &R) const {
return !(*this == R);
}
};

/// Control of individual spaces in empty braces.
///
/// If ``SpaceInEmptyBraces`` is set to ``Custom``, use this to specify
/// how each individual space in empty braces case should be handled.
/// Otherwise, this is ignored.
/// \code{.yaml}
/// # Example of usage:
/// SpaceInEmptyBraces: Custom
/// SpaceInEmptyBracesOptions:
/// Function: true
/// Record: false
/// InitList: true
/// Block: false
/// \endcode
/// \version 20
SpaceInEmptyBracesCustom SpaceInEmptyBracesOptions;

/// If ``true``, spaces will be inserted after ``[`` and before ``]``.
/// Lambdas without arguments or unspecified size array declarations will not
/// be affected.
Expand Down Expand Up @@ -5339,7 +5438,8 @@ struct FormatStyle {
SpaceBeforeRangeBasedForLoopColon ==
R.SpaceBeforeRangeBasedForLoopColon &&
SpaceBeforeSquareBrackets == R.SpaceBeforeSquareBrackets &&
SpaceInEmptyBlock == R.SpaceInEmptyBlock &&
SpaceInEmptyBraces == R.SpaceInEmptyBraces &&
SpaceInEmptyBracesOptions == R.SpaceInEmptyBracesOptions &&
SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments &&
SpacesInAngles == R.SpacesInAngles &&
SpacesInContainerLiterals == R.SpacesInContainerLiterals &&
Expand Down
39 changes: 36 additions & 3 deletions clang/lib/Format/Format.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,24 @@ template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
}
};

template <> struct MappingTraits<FormatStyle::SpaceInEmptyBracesCustom> {
static void mapping(IO &IO, FormatStyle::SpaceInEmptyBracesCustom &Space) {
IO.mapOptional("Function", Space.Function);
IO.mapOptional("Record", Space.Record);
IO.mapOptional("InitList", Space.InitList);
IO.mapOptional("Block", Space.Block);
}
};

template <>
struct ScalarEnumerationTraits<FormatStyle::SpaceInEmptyBracesStyle> {
static void enumeration(IO &IO, FormatStyle::SpaceInEmptyBracesStyle &Value) {
IO.enumCase(Value, "Never", FormatStyle::SIEBO_Never);
IO.enumCase(Value, "Always", FormatStyle::SIEBO_Always);
IO.enumCase(Value, "Custom", FormatStyle::SIEBO_Custom);
}
};

template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
Expand Down Expand Up @@ -905,6 +923,7 @@ template <> struct MappingTraits<FormatStyle> {
bool UseCRLF = false;

bool SpaceInEmptyParentheses = false;
bool SpaceInEmptyBlock = false;
bool SpacesInConditionalStatement = false;
bool SpacesInCStyleCastParentheses = false;
bool SpacesInParentheses = false;
Expand Down Expand Up @@ -934,6 +953,7 @@ template <> struct MappingTraits<FormatStyle> {
IO.mapOptional("SpaceAfterControlStatementKeyword",
Style.SpaceBeforeParens);
IO.mapOptional("SpaceInEmptyParentheses", SpaceInEmptyParentheses);
IO.mapOptional("SpaceInEmptyBlock", SpaceInEmptyBlock);
IO.mapOptional("SpacesInConditionalStatement",
SpacesInConditionalStatement);
IO.mapOptional("SpacesInCStyleCastParentheses",
Expand Down Expand Up @@ -1154,14 +1174,16 @@ template <> struct MappingTraits<FormatStyle> {
Style.SpaceBeforeRangeBasedForLoopColon);
IO.mapOptional("SpaceBeforeSquareBrackets",
Style.SpaceBeforeSquareBrackets);
IO.mapOptional("SpaceInEmptyBlock", Style.SpaceInEmptyBlock);
IO.mapOptional("SpacesBeforeTrailingComments",
Style.SpacesBeforeTrailingComments);
IO.mapOptional("SpacesInAngles", Style.SpacesInAngles);
IO.mapOptional("SpacesInContainerLiterals",
Style.SpacesInContainerLiterals);
IO.mapOptional("SpacesInLineCommentPrefix",
Style.SpacesInLineCommentPrefix);
IO.mapOptional("SpaceInEmptyBraces", Style.SpaceInEmptyBraces);
IO.mapOptional("SpaceInEmptyBracesOptions",
Style.SpaceInEmptyBracesOptions);
IO.mapOptional("SpacesInParens", Style.SpacesInParens);
IO.mapOptional("SpacesInParensOptions", Style.SpacesInParensOptions);
IO.mapOptional("SpacesInSquareBrackets", Style.SpacesInSquareBrackets);
Expand Down Expand Up @@ -1260,6 +1282,15 @@ template <> struct MappingTraits<FormatStyle> {
}
Style.SpacesInParens = FormatStyle::SIPO_Custom;
}

if (Style.SpaceInEmptyBraces != FormatStyle::SIEBO_Custom &&
SpaceInEmptyBlock) {
Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Custom;
Style.SpaceInEmptyBracesOptions.Function = true;
Style.SpaceInEmptyBracesOptions.Record = true;
Style.SpaceInEmptyBracesOptions.InitList = false;
Style.SpaceInEmptyBracesOptions.Block = true;
}
}
};

Expand Down Expand Up @@ -1632,7 +1663,7 @@ FormatStyle getLLVMStyle(FormatStyle::LanguageKind Language) {
LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
LLVMStyle.SpaceBeforeRangeBasedForLoopColon = true;
LLVMStyle.SpaceBeforeSquareBrackets = false;
LLVMStyle.SpaceInEmptyBlock = false;
LLVMStyle.SpaceInEmptyBraces = FormatStyle::SIEBO_Never;
LLVMStyle.SpacesBeforeTrailingComments = 1;
LLVMStyle.SpacesInAngles = FormatStyle::SIAS_Never;
LLVMStyle.SpacesInContainerLiterals = true;
Expand Down Expand Up @@ -1934,7 +1965,9 @@ FormatStyle getWebKitStyle() {
Style.ObjCSpaceAfterProperty = true;
Style.PointerAlignment = FormatStyle::PAS_Left;
Style.SpaceBeforeCpp11BracedList = true;
Style.SpaceInEmptyBlock = true;
Style.SpaceInEmptyBraces = FormatStyle::SIEBO_Always;
Style.SpacesInParensOptions.InEmptyParentheses = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we confirm this matches their published style guide because we are about to change defaults

Copy link
Contributor Author

@khei4 khei4 Jun 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this matches, but it might be miss-leading to specify only Block and Initlist, (although they are same with all braces). check-webkit-style script seems like to check whatever empty braces have a space inside of it.

        self.assert_lint('    { }', '')
        self.assert_lint('    {}', 'Missing space inside { }.  [whitespace/braces] [5]')
        self.assert_lint('    {   }', 'Too many spaces inside { }.  [whitespace/braces] [5]')

So adding SIEBO_Always and using it might be better. To double check, I will ask in WebKit slack also. Thanks!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO we need to go by the published WebKit coding style, not the script.

Copy link
Contributor Author

@khei4 khei4 Jun 14, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@owenca
Thank you. I found there are no entries about empty braces. I will consult on the WebKit mailing list about the inconsistency between Code Style Guideline and check-webkit-style script. I think it’s good to separate the WebKit Style fixes and empty braces options addition on this patch. Although I can’t still find how much this kind of inconsistency exist, I will file an issue if it’s necessary. :)

Style.SpacesInParensOptions.Other = false;
return Style;
}

Expand Down
26 changes: 24 additions & 2 deletions clang/lib/Format/TokenAnnotator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4464,9 +4464,31 @@ 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) &&

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) &&
Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Never)) {
return Style.SpacesInParensOptions.InEmptyParentheses;
}
// Other braces for records are handled in tryMergeSimpleBlock on
// UnwrappedLineFormatter.cpp.
if (Left.is(tok::l_brace) && Right.is(tok::r_brace) &&
Right.MatchingParen == &Left && Line.Children.empty()) {
return Style.SpaceInEmptyBlock;
if (Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Never)
return false;
if (Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Always)
return true;
if (Style.SpaceInEmptyBraces == FormatStyle::SIEBO_Custom) {
if (Left.is(BK_BracedInit) && Right.is(BK_BracedInit))
return Style.SpaceInEmptyBracesOptions.InitList;
if (Left.is(TT_EnumLBrace) && Right.is(TT_EnumRBrace)) {
return Style.SpaceInEmptyBracesOptions.Record ||
Style.SpaceInEmptyBracesOptions.Block;
}
if (Left.is(BK_Block))
return Style.SpaceInEmptyBracesOptions.Block;
}
}
if (Style.SpacesInParens == FormatStyle::SIPO_Custom) {
if ((Left.is(tok::l_paren) && Right.is(tok::r_paren)) ||
Expand Down
Loading
Loading