Skip to content

Commit 4a74892

Browse files
committed
Add SpaceInParensOption ExceptDoubleParentheses
This change allows finer control over addition of spaces between a pair of consecutive opening parentheses with a pair of closing parentheses.
1 parent 67da89c commit 4a74892

File tree

7 files changed

+441
-40
lines changed

7 files changed

+441
-40
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6214,6 +6214,7 @@ the configuration (without a prefix: ``Auto``).
62146214
# Example of usage:
62156215
SpacesInParens: Custom
62166216
SpacesInParensOptions:
6217+
ExceptDoubleParentheses: false
62176218
InConditionalStatements: true
62186219
InEmptyParentheses: true
62196220
@@ -6226,9 +6227,23 @@ the configuration (without a prefix: ``Auto``).
62266227
# Should be declared this way:
62276228
SpacesInParens: Custom
62286229
SpacesInParensOptions:
6230+
ExceptDoubleParentheses: false
62296231
InConditionalStatements: true
62306232
Other: true
62316233

6234+
* ``bool ExceptDoubleParentheses`` Override any of the following options to prevent addition of space
6235+
between the first two parentheses in situations where a pair of
6236+
parentheses have been used.
6237+
6238+
.. code-block:: c++
6239+
6240+
true:
6241+
__attribute__(( noreturn ))
6242+
__decltype__(( x ))
6243+
if (( a = b ))
6244+
false:
6245+
Uses the applicable option.
6246+
62326247
* ``bool InConditionalStatements`` Put a space in parentheses only inside conditional statements
62336248
(``for/if/while/switch...``).
62346249

@@ -6242,8 +6257,9 @@ the configuration (without a prefix: ``Auto``).
62426257

62436258
.. code-block:: c++
62446259

6245-
true: false:
6246-
x = ( int32 )y vs. x = (int32)y
6260+
true: false:
6261+
x = ( int32 )y vs. x = (int32)y
6262+
y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);
62476263

62486264
* ``bool InEmptyParentheses`` Insert a space in empty parentheses, i.e. ``()``.
62496265

@@ -6261,8 +6277,12 @@ the configuration (without a prefix: ``Auto``).
62616277

62626278
.. code-block:: c++
62636279

6264-
true: false:
6265-
t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
6280+
true: false:
6281+
t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
6282+
decltype( ( x ) ) decltype((x))
6283+
x = ( (int32)y ) x = ((int32))y
6284+
y = ( (int ( * )( int ))foo )( x ); y = ((int (*)(int))foo)(x);
6285+
__attribute__( ( noreturn ) ) __attribute__((noreturn))
62666286

62676287

62686288
.. _SpacesInParentheses:

clang/docs/ReleaseNotes.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1079,6 +1079,9 @@ clang-format
10791079
- Adds ``AllowShortCaseExpressionOnASingleLine`` option.
10801080
- Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``.
10811081
- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``.
1082+
- Add ``ExceptDoubleParentheses`` sub-option for ``SpacesInParensOptions``
1083+
to override addition of spaces between multiple, non-redundant parentheses
1084+
similar to the rules used for ``RemoveParentheses``.
10821085

10831086
libclang
10841087
--------

clang/include/clang/Format/Format.h

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4650,10 +4650,23 @@ struct FormatStyle {
46504650
/// # Should be declared this way:
46514651
/// SpacesInParens: Custom
46524652
/// SpacesInParensOptions:
4653+
/// ExceptDoubleParentheses: false
46534654
/// InConditionalStatements: true
46544655
/// Other: true
46554656
/// \endcode
46564657
struct SpacesInParensCustom {
4658+
/// Override any of the following options to prevent addition of space
4659+
/// between the first two parentheses in situations where a pair of
4660+
/// parentheses have been used.
4661+
/// \code
4662+
/// true:
4663+
/// __attribute__(( noreturn ))
4664+
/// __decltype__(( x ))
4665+
/// if (( a = b ))
4666+
/// \endcode
4667+
/// false:
4668+
/// Uses the applicable option.
4669+
bool ExceptDoubleParentheses;
46574670
/// Put a space in parentheses only inside conditional statements
46584671
/// (``for/if/while/switch...``).
46594672
/// \code
@@ -4664,8 +4677,9 @@ struct FormatStyle {
46644677
bool InConditionalStatements;
46654678
/// Put a space in C style casts.
46664679
/// \code
4667-
/// true: false:
4668-
/// x = ( int32 )y vs. x = (int32)y
4680+
/// true: false:
4681+
/// x = ( int32 )y vs. x = (int32)y
4682+
/// y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);
46694683
/// \endcode
46704684
bool InCStyleCasts;
46714685
/// Insert a space in empty parentheses, i.e. ``()``.
@@ -4681,23 +4695,30 @@ struct FormatStyle {
46814695
bool InEmptyParentheses;
46824696
/// Put a space in parentheses not covered by preceding options.
46834697
/// \code
4684-
/// true: false:
4685-
/// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
4698+
/// true: false:
4699+
/// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
4700+
/// decltype( ( x ) ) decltype((x))
4701+
/// x = ( (int32)y ) x = ((int32))y
4702+
/// y = ( (int ( * )( int ))foo )( x ); y = ((int (*)(int))foo)(x);
4703+
/// __attribute__( ( noreturn ) ) __attribute__((noreturn))
46864704
/// \endcode
46874705
bool Other;
46884706

46894707
SpacesInParensCustom()
4690-
: InConditionalStatements(false), InCStyleCasts(false),
4691-
InEmptyParentheses(false), Other(false) {}
4708+
: ExceptDoubleParentheses(false), InConditionalStatements(false),
4709+
InCStyleCasts(false), InEmptyParentheses(false), Other(false) {}
46924710

4693-
SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts,
4711+
SpacesInParensCustom(bool ExceptDoubleParentheses,
4712+
bool InConditionalStatements, bool InCStyleCasts,
46944713
bool InEmptyParentheses, bool Other)
4695-
: InConditionalStatements(InConditionalStatements),
4714+
: ExceptDoubleParentheses(ExceptDoubleParentheses),
4715+
InConditionalStatements(InConditionalStatements),
46964716
InCStyleCasts(InCStyleCasts), InEmptyParentheses(InEmptyParentheses),
46974717
Other(Other) {}
46984718

46994719
bool operator==(const SpacesInParensCustom &R) const {
4700-
return InConditionalStatements == R.InConditionalStatements &&
4720+
return ExceptDoubleParentheses == R.ExceptDoubleParentheses &&
4721+
InConditionalStatements == R.InConditionalStatements &&
47014722
InCStyleCasts == R.InCStyleCasts &&
47024723
InEmptyParentheses == R.InEmptyParentheses && Other == R.Other;
47034724
}
@@ -4715,6 +4736,7 @@ struct FormatStyle {
47154736
/// # Example of usage:
47164737
/// SpacesInParens: Custom
47174738
/// SpacesInParensOptions:
4739+
/// ExceptDoubleParentheses: false
47184740
/// InConditionalStatements: true
47194741
/// InEmptyParentheses: true
47204742
/// \endcode

clang/lib/Format/Format.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
721721

722722
template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
723723
static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
724+
IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
724725
IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
725726
IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
726727
IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
@@ -1175,8 +1176,8 @@ template <> struct MappingTraits<FormatStyle> {
11751176
(SpacesInParentheses || SpaceInEmptyParentheses ||
11761177
SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
11771178
if (SpacesInParentheses) {
1178-
// set all options except InCStyleCasts and InEmptyParentheses
1179-
// to true for backward compatibility.
1179+
// for backward compatibility.
1180+
Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
11801181
Style.SpacesInParensOptions.InConditionalStatements = true;
11811182
Style.SpacesInParensOptions.InCStyleCasts =
11821183
SpacesInCStyleCastParentheses;

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4346,19 +4346,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
43464346
Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
43474347
return Style.SpacesInParensOptions.InEmptyParentheses;
43484348
}
4349-
if (Style.SpacesInParensOptions.InConditionalStatements) {
4350-
const FormatToken *LeftParen = nullptr;
4351-
if (Left.is(tok::l_paren))
4352-
LeftParen = &Left;
4353-
else if (Right.is(tok::r_paren) && Right.MatchingParen)
4354-
LeftParen = Right.MatchingParen;
4355-
if (LeftParen) {
4356-
if (LeftParen->is(TT_ConditionLParen))
4357-
return true;
4358-
if (LeftParen->Previous && isKeywordWithCondition(*LeftParen->Previous))
4359-
return true;
4360-
}
4361-
}
43624349

43634350
// trailing return type 'auto': []() -> auto {}, auto foo() -> auto {}
43644351
if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace,
@@ -4385,11 +4372,60 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
43854372
}
43864373

43874374
if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) {
4388-
return (Right.is(TT_CastRParen) ||
4389-
(Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen)))
4390-
? Style.SpacesInParensOptions.InCStyleCasts
4391-
: Style.SpacesInParensOptions.Other;
4375+
const FormatToken *LeftParen =
4376+
Left.is(tok::l_paren) ? &Left : Right.MatchingParen;
4377+
const FormatToken *RightParen =
4378+
LeftParen ? LeftParen->MatchingParen : nullptr;
4379+
const auto IsAttributeParen = [](const FormatToken *Paren) {
4380+
return Paren && Paren->isOneOf(TT_AttributeLParen, TT_AttributeRParen);
4381+
};
4382+
auto AddSpaceExceptInDoubleParens = [&]() {
4383+
const auto *RPrev = RightParen ? RightParen->Previous : nullptr;
4384+
const auto *LNext = LeftParen->Next;
4385+
const auto *LPrev = LeftParen->Previous;
4386+
if (!(RPrev && RPrev->is(tok::r_paren) && LNext &&
4387+
LNext->is(tok::l_paren))) {
4388+
return true;
4389+
}
4390+
auto HasEqualBeforeNextParen = [&]() {
4391+
auto *Tok = LNext;
4392+
if (!Tok || !Tok->is(tok::l_paren))
4393+
return false;
4394+
while ((Tok = Tok->Next) && !Tok->isOneOf(tok::l_paren, tok::r_paren))
4395+
if (Tok->is(tok::equal))
4396+
return true;
4397+
return false;
4398+
};
4399+
const bool SuppressSpace =
4400+
IsAttributeParen(LeftParen) ||
4401+
(LPrev && (LPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) ||
4402+
(HasEqualBeforeNextParen() &&
4403+
(LPrev->isOneOf(tok::kw_if, tok::kw_while) ||
4404+
LPrev->endsSequence(tok::kw_constexpr, tok::kw_if)))));
4405+
return !SuppressSpace;
4406+
};
4407+
const auto AddSpace = [&](bool Option) {
4408+
if (Style.SpacesInParensOptions.ExceptDoubleParentheses && Option)
4409+
return AddSpaceExceptInDoubleParens();
4410+
return Option;
4411+
};
4412+
4413+
if (LeftParen && (LeftParen->is(TT_ConditionLParen) ||
4414+
(LeftParen->Previous &&
4415+
isKeywordWithCondition(*LeftParen->Previous)))) {
4416+
return AddSpace(Style.SpacesInParensOptions.InConditionalStatements);
4417+
}
4418+
if (RightParen && RightParen->is(TT_CastRParen))
4419+
return AddSpace(Style.SpacesInParensOptions.InCStyleCasts);
4420+
if (IsAttributeParen(LeftParen) || IsAttributeParen(RightParen))
4421+
return AddSpace(Style.SpacesInParensOptions.Other);
4422+
if ((LeftParen && IsAttributeParen(LeftParen->Previous)) ||
4423+
(RightParen && IsAttributeParen(RightParen->Next))) {
4424+
return AddSpace(Style.SpacesInParensOptions.Other);
4425+
}
4426+
return AddSpace(Style.SpacesInParensOptions.Other);
43924427
}
4428+
43934429
if (Right.isOneOf(tok::semi, tok::comma))
43944430
return false;
43954431
if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) {

clang/unittests/Format/ConfigParseTest.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
236236
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator);
237237
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterPlacementOperator);
238238
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses);
239+
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, ExceptDoubleParentheses);
239240
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InCStyleCasts);
240241
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements);
241242
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses);
@@ -622,20 +623,24 @@ TEST(ConfigParseTest, ParsesConfiguration) {
622623
FormatStyle::SIPO_Custom);
623624
Style.SpacesInParens = FormatStyle::SIPO_Never;
624625
Style.SpacesInParensOptions = {};
625-
CHECK_PARSE("SpacesInParentheses: true", SpacesInParensOptions,
626-
FormatStyle::SpacesInParensCustom(true, false, false, true));
626+
CHECK_PARSE(
627+
"SpacesInParentheses: true", SpacesInParensOptions,
628+
FormatStyle::SpacesInParensCustom(false, true, false, false, true));
627629
Style.SpacesInParens = FormatStyle::SIPO_Never;
628630
Style.SpacesInParensOptions = {};
629-
CHECK_PARSE("SpacesInConditionalStatement: true", SpacesInParensOptions,
630-
FormatStyle::SpacesInParensCustom(true, false, false, false));
631+
CHECK_PARSE(
632+
"SpacesInConditionalStatement: true", SpacesInParensOptions,
633+
FormatStyle::SpacesInParensCustom(false, true, false, false, false));
631634
Style.SpacesInParens = FormatStyle::SIPO_Never;
632635
Style.SpacesInParensOptions = {};
633-
CHECK_PARSE("SpacesInCStyleCastParentheses: true", SpacesInParensOptions,
634-
FormatStyle::SpacesInParensCustom(false, true, false, false));
636+
CHECK_PARSE(
637+
"SpacesInCStyleCastParentheses: true", SpacesInParensOptions,
638+
FormatStyle::SpacesInParensCustom(false, false, true, false, false));
635639
Style.SpacesInParens = FormatStyle::SIPO_Never;
636640
Style.SpacesInParensOptions = {};
637-
CHECK_PARSE("SpaceInEmptyParentheses: true", SpacesInParensOptions,
638-
FormatStyle::SpacesInParensCustom(false, false, true, false));
641+
CHECK_PARSE(
642+
"SpaceInEmptyParentheses: true", SpacesInParensOptions,
643+
FormatStyle::SpacesInParensCustom(false, false, false, true, false));
639644
Style.SpacesInParens = FormatStyle::SIPO_Never;
640645
Style.SpacesInParensOptions = {};
641646

0 commit comments

Comments
 (0)