[clang] 54f040f - [clang-format] Add SpacesInParensOption for filtering repeated parens (#77522)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 2 00:00:18 PDT 2024
Author: Gedare Bloom
Date: 2024-07-02T00:00:14-07:00
New Revision: 54f040fff301a629f2ed032863408ed119789b0e
URL: https://github.com/llvm/llvm-project/commit/54f040fff301a629f2ed032863408ed119789b0e
DIFF: https://github.com/llvm/llvm-project/commit/54f040fff301a629f2ed032863408ed119789b0e.diff
LOG: [clang-format] Add SpacesInParensOption for filtering repeated parens (#77522)
The __attribute((specifier-list)) currently is formatted based on the
SpacesInParensOptions.Other (previously, SpacesInParentheses). This
change allows finer control over addition of spaces between the
consecutive parens, and between the inner parens and the list of
attribute specifiers.
Differential Revision: https://reviews.llvm.org/D155529
This is migrated from Phabricator, see more discussion there.
---------
Co-authored-by: Owen Pan <owenpiano at gmail.com>
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/ConfigParseTest.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 080cba90c4a8b..6c2e6da594847 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -6242,6 +6242,7 @@ the configuration (without a prefix: ``Auto``).
# Example of usage:
SpacesInParens: Custom
SpacesInParensOptions:
+ ExceptDoubleParentheses: false
InConditionalStatements: true
InEmptyParentheses: true
@@ -6254,9 +6255,22 @@ the configuration (without a prefix: ``Auto``).
# Should be declared this way:
SpacesInParens: Custom
SpacesInParensOptions:
+ ExceptDoubleParentheses: false
InConditionalStatements: true
Other: true
+ * ``bool ExceptDoubleParentheses`` Override any of the following options to prevent addition of space
+ when both opening and closing parentheses use multiple parentheses.
+
+ .. code-block:: c++
+
+ true:
+ __attribute__(( noreturn ))
+ __decltype__(( x ))
+ if (( a = b ))
+ false:
+ Uses the applicable option.
+
* ``bool InConditionalStatements`` Put a space in parentheses only inside conditional statements
(``for/if/while/switch...``).
@@ -6270,8 +6284,9 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
- true: false:
- x = ( int32 )y vs. x = (int32)y
+ true: false:
+ x = ( int32 )y vs. x = (int32)y
+ y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);
* ``bool InEmptyParentheses`` Insert a space in empty parentheses, i.e. ``()``.
@@ -6289,8 +6304,8 @@ the configuration (without a prefix: ``Auto``).
.. code-block:: c++
- true: false:
- t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
+ true: false:
+ t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
.. _SpacesInParentheses:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 90c2469c1c89a..fd8d9ad34fb10 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -1130,6 +1130,9 @@ clang-format
- Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``.
- Adds ``KeepEmptyLines`` option to deprecate ``KeepEmptyLinesAtEOF``
and ``KeepEmptyLinesAtTheStartOfBlocks``.
+- Add ``ExceptDoubleParentheses`` sub-option for ``SpacesInParensOptions``
+ to override addition of spaces between multiple, non-redundant parentheses
+ similar to the rules used for ``RemoveParentheses``.
libclang
--------
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index efc2e450b723f..c454ab2bc0ce2 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -4679,10 +4679,22 @@ struct FormatStyle {
/// # Should be declared this way:
/// SpacesInParens: Custom
/// SpacesInParensOptions:
+ /// ExceptDoubleParentheses: false
/// InConditionalStatements: true
/// Other: true
/// \endcode
struct SpacesInParensCustom {
+ /// Override any of the following options to prevent addition of space
+ /// when both opening and closing parentheses use multiple parentheses.
+ /// \code
+ /// true:
+ /// __attribute__(( noreturn ))
+ /// __decltype__(( x ))
+ /// if (( a = b ))
+ /// \endcode
+ /// false:
+ /// Uses the applicable option.
+ bool ExceptDoubleParentheses;
/// Put a space in parentheses only inside conditional statements
/// (``for/if/while/switch...``).
/// \code
@@ -4693,8 +4705,9 @@ struct FormatStyle {
bool InConditionalStatements;
/// Put a space in C style casts.
/// \code
- /// true: false:
- /// x = ( int32 )y vs. x = (int32)y
+ /// true: false:
+ /// x = ( int32 )y vs. x = (int32)y
+ /// y = (( int (*)(int) )foo)(x); y = ((int (*)(int))foo)(x);
/// \endcode
bool InCStyleCasts;
/// Insert a space in empty parentheses, i.e. ``()``.
@@ -4710,23 +4723,26 @@ struct FormatStyle {
bool InEmptyParentheses;
/// Put a space in parentheses not covered by preceding options.
/// \code
- /// true: false:
- /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
+ /// true: false:
+ /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete;
/// \endcode
bool Other;
SpacesInParensCustom()
- : InConditionalStatements(false), InCStyleCasts(false),
- InEmptyParentheses(false), Other(false) {}
+ : ExceptDoubleParentheses(false), InConditionalStatements(false),
+ InCStyleCasts(false), InEmptyParentheses(false), Other(false) {}
- SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts,
+ SpacesInParensCustom(bool ExceptDoubleParentheses,
+ bool InConditionalStatements, bool InCStyleCasts,
bool InEmptyParentheses, bool Other)
- : InConditionalStatements(InConditionalStatements),
+ : ExceptDoubleParentheses(ExceptDoubleParentheses),
+ InConditionalStatements(InConditionalStatements),
InCStyleCasts(InCStyleCasts), InEmptyParentheses(InEmptyParentheses),
Other(Other) {}
bool operator==(const SpacesInParensCustom &R) const {
- return InConditionalStatements == R.InConditionalStatements &&
+ return ExceptDoubleParentheses == R.ExceptDoubleParentheses &&
+ InConditionalStatements == R.InConditionalStatements &&
InCStyleCasts == R.InCStyleCasts &&
InEmptyParentheses == R.InEmptyParentheses && Other == R.Other;
}
@@ -4744,6 +4760,7 @@ struct FormatStyle {
/// # Example of usage:
/// SpacesInParens: Custom
/// SpacesInParensOptions:
+ /// ExceptDoubleParentheses: false
/// InConditionalStatements: true
/// InEmptyParentheses: true
/// \endcode
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 259ef1dd00e3f..6a8883b77a730 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -729,6 +729,7 @@ template <> struct MappingTraits<FormatStyle::SpacesInLineComment> {
template <> struct MappingTraits<FormatStyle::SpacesInParensCustom> {
static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) {
+ IO.mapOptional("ExceptDoubleParentheses", Spaces.ExceptDoubleParentheses);
IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts);
IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements);
IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses);
@@ -1184,8 +1185,8 @@ template <> struct MappingTraits<FormatStyle> {
(SpacesInParentheses || SpaceInEmptyParentheses ||
SpacesInConditionalStatement || SpacesInCStyleCastParentheses)) {
if (SpacesInParentheses) {
- // set all options except InCStyleCasts and InEmptyParentheses
- // to true for backward compatibility.
+ // For backward compatibility.
+ Style.SpacesInParensOptions.ExceptDoubleParentheses = false;
Style.SpacesInParensOptions.InConditionalStatements = true;
Style.SpacesInParensOptions.InCStyleCasts =
SpacesInCStyleCastParentheses;
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 03082cd2742c8..0fd0214d16615 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -4361,6 +4361,15 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
Right.is(tok::r_brace) && Right.isNot(BK_Block))) {
return Style.SpacesInParensOptions.InEmptyParentheses;
}
+ if (Style.SpacesInParens == FormatStyle::SIPO_Custom &&
+ Style.SpacesInParensOptions.ExceptDoubleParentheses &&
+ Left.is(tok::r_paren) && Right.is(tok::r_paren)) {
+ auto *InnerLParen = Left.MatchingParen;
+ if (InnerLParen && InnerLParen->Previous == Right.MatchingParen) {
+ InnerLParen->SpacesRequiredBefore = 0;
+ return false;
+ }
+ }
if (Style.SpacesInParensOptions.InConditionalStatements) {
const FormatToken *LeftParen = nullptr;
if (Left.is(tok::l_paren))
diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp
index 2466677a3740d..cc044153b7c9b 100644
--- a/clang/unittests/Format/ConfigParseTest.cpp
+++ b/clang/unittests/Format/ConfigParseTest.cpp
@@ -240,6 +240,7 @@ TEST(ConfigParseTest, ParsesConfigurationBools) {
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterPlacementOperator);
CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses);
+ CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, ExceptDoubleParentheses);
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InCStyleCasts);
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements);
CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses);
@@ -626,20 +627,24 @@ TEST(ConfigParseTest, ParsesConfiguration) {
FormatStyle::SIPO_Custom);
Style.SpacesInParens = FormatStyle::SIPO_Never;
Style.SpacesInParensOptions = {};
- CHECK_PARSE("SpacesInParentheses: true", SpacesInParensOptions,
- FormatStyle::SpacesInParensCustom(true, false, false, true));
+ CHECK_PARSE(
+ "SpacesInParentheses: true", SpacesInParensOptions,
+ FormatStyle::SpacesInParensCustom(false, true, false, false, true));
Style.SpacesInParens = FormatStyle::SIPO_Never;
Style.SpacesInParensOptions = {};
- CHECK_PARSE("SpacesInConditionalStatement: true", SpacesInParensOptions,
- FormatStyle::SpacesInParensCustom(true, false, false, false));
+ CHECK_PARSE(
+ "SpacesInConditionalStatement: true", SpacesInParensOptions,
+ FormatStyle::SpacesInParensCustom(false, true, false, false, false));
Style.SpacesInParens = FormatStyle::SIPO_Never;
Style.SpacesInParensOptions = {};
- CHECK_PARSE("SpacesInCStyleCastParentheses: true", SpacesInParensOptions,
- FormatStyle::SpacesInParensCustom(false, true, false, false));
+ CHECK_PARSE(
+ "SpacesInCStyleCastParentheses: true", SpacesInParensOptions,
+ FormatStyle::SpacesInParensCustom(false, false, true, false, false));
Style.SpacesInParens = FormatStyle::SIPO_Never;
Style.SpacesInParensOptions = {};
- CHECK_PARSE("SpaceInEmptyParentheses: true", SpacesInParensOptions,
- FormatStyle::SpacesInParensCustom(false, false, true, false));
+ CHECK_PARSE(
+ "SpaceInEmptyParentheses: true", SpacesInParensOptions,
+ FormatStyle::SpacesInParensCustom(false, false, false, true, false));
Style.SpacesInParens = FormatStyle::SIPO_Never;
Style.SpacesInParensOptions = {};
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 5276e79d75981..283843ad7ab47 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -17129,6 +17129,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces);
verifyFormat("void __attribute__((naked)) foo(int bar)", Spaces);
verifyFormat("void f() __attribute__((asdf));", Spaces);
+ verifyFormat("x = (int32)y;", Spaces);
+ verifyFormat("y = ((int (*)(int))foo)(x);", Spaces);
+ verifyFormat("decltype(x) y = 42;", Spaces);
+ verifyFormat("decltype((x)) y = z;", Spaces);
+ verifyFormat("decltype((foo())) a = foo();", Spaces);
+ verifyFormat("decltype((bar(10))) a = bar(11);", Spaces);
+ verifyFormat("if ((x - y) && (a ^ b))\n"
+ " f();",
+ Spaces);
+ verifyFormat("for (int i = 0; i < 10; i = (i + 1))\n"
+ " foo(i);",
+ Spaces);
+ verifyFormat("switch (x / (y + z)) {\n"
+ "default:\n"
+ " break;\n"
+ "}",
+ Spaces);
Spaces.SpacesInParens = FormatStyle::SIPO_Custom;
Spaces.SpacesInParensOptions = {};
@@ -17163,6 +17180,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
verifyFormat("SomeType *__attribute__( ( attr ) ) *a = NULL;", Spaces);
verifyFormat("void __attribute__( ( naked ) ) foo( int bar )", Spaces);
verifyFormat("void f() __attribute__( ( asdf ) );", Spaces);
+ verifyFormat("x = (int32)y;", Spaces);
+ verifyFormat("y = ( (int ( * )( int ))foo )( x );", Spaces);
+ verifyFormat("decltype( x ) y = 42;", Spaces);
+ verifyFormat("decltype( ( x ) ) y = z;", Spaces);
+ verifyFormat("decltype( ( foo() ) ) a = foo();", Spaces);
+ verifyFormat("decltype( ( bar( 10 ) ) ) a = bar( 11 );", Spaces);
+ verifyFormat("if ( ( x - y ) && ( a ^ b ) )\n"
+ " f();",
+ Spaces);
+ verifyFormat("for ( int i = 0; i < 10; i = ( i + 1 ) )\n"
+ " foo( i );",
+ Spaces);
+ verifyFormat("switch ( x / ( y + z ) ) {\n"
+ "default:\n"
+ " break;\n"
+ "}",
+ Spaces);
Spaces.SpacesInParens = FormatStyle::SIPO_Custom;
Spaces.SpacesInParensOptions = {};
@@ -17175,6 +17209,7 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
verifyFormat("#define AA(X) sizeof((( X * )NULL)->a)", Spaces);
verifyFormat("my_int a = ( my_int )sizeof(int);", Spaces);
verifyFormat("#define x (( int )-1)", Spaces);
+ verifyFormat("y = (( int (*)(int) )foo)(x);", Spaces);
// Run the first set of tests again with:
Spaces.SpacesInParens = FormatStyle::SIPO_Custom;
@@ -17207,6 +17242,23 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces);
verifyFormat("void __attribute__((naked)) foo(int bar)", Spaces);
verifyFormat("void f( ) __attribute__((asdf));", Spaces);
+ verifyFormat("x = ( int32 )y;", Spaces);
+ verifyFormat("y = (( int (*)(int) )foo)(x);", Spaces);
+ verifyFormat("decltype(x) y = 42;", Spaces);
+ verifyFormat("decltype((x)) y = z;", Spaces);
+ verifyFormat("decltype((foo( ))) a = foo( );", Spaces);
+ verifyFormat("decltype((bar(10))) a = bar(11);", Spaces);
+ verifyFormat("if ((x - y) && (a ^ b))\n"
+ " f( );",
+ Spaces);
+ verifyFormat("for (int i = 0; i < 10; i = (i + 1))\n"
+ " foo(i);",
+ Spaces);
+ verifyFormat("switch (x / (y + z)) {\n"
+ "default:\n"
+ " break;\n"
+ "}",
+ Spaces);
// Run the first set of tests again with:
Spaces.SpaceAfterCStyleCast = true;
@@ -17314,6 +17366,63 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) {
verifyFormat("size_t idx = (a->foo)(a - 1);", Spaces);
verifyFormat("size_t idx = (*foo)(a - 1);", Spaces);
verifyFormat("size_t idx = (*(foo))(a - 1);", Spaces);
+
+ // Check ExceptDoubleParentheses spaces
+ Spaces.IndentWidth = 2;
+ Spaces.SpacesInParens = FormatStyle::SIPO_Custom;
+ Spaces.SpacesInParensOptions = {};
+ Spaces.SpacesInParensOptions.Other = true;
+ Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true;
+ verifyFormat("SomeType *__attribute__(( attr )) *a = NULL;", Spaces);
+ verifyFormat("void __attribute__(( naked )) foo( int bar )", Spaces);
+ verifyFormat("void f() __attribute__(( asdf ));", Spaces);
+ verifyFormat("__attribute__(( __aligned__( x ) )) z;", Spaces);
+ verifyFormat("int x __attribute__(( aligned( 16 ) )) = 0;", Spaces);
+ verifyFormat("class __declspec( dllimport ) X {};", Spaces);
+ verifyFormat("class __declspec(( dllimport )) X {};", Spaces);
+ verifyFormat("int x = ( ( a - 1 ) * 3 );", Spaces);
+ verifyFormat("int x = ( 3 * ( a - 1 ) );", Spaces);
+ verifyFormat("decltype( x ) y = 42;", Spaces);
+ verifyFormat("decltype(( bar( 10 ) )) a = bar( 11 );", Spaces);
+ verifyFormat("if (( i = j ))\n"
+ " do_something( i );",
+ Spaces);
+
+ Spaces.SpacesInParens = FormatStyle::SIPO_Custom;
+ Spaces.SpacesInParensOptions = {};
+ Spaces.SpacesInParensOptions.InConditionalStatements = true;
+ Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true;
+ verifyFormat("while ( (bool)1 )\n"
+ " continue;",
+ Spaces);
+ verifyFormat("while ((i = j))\n"
+ " continue;",
+ Spaces);
+ verifyFormat("do {\n"
+ " do_something((int)i);\n"
+ "} while ( something() );",
+ Spaces);
+ verifyFormat("do {\n"
+ " do_something((int)i);\n"
+ "} while ((i = i + 1));",
+ Spaces);
+ verifyFormat("if ( (x - y) && (a ^ b) )\n"
+ " f();",
+ Spaces);
+ verifyFormat("if ((i = j))\n"
+ " do_something(i);",
+ Spaces);
+ verifyFormat("for ( int i = 0; i < 10; i = (i + 1) )\n"
+ " foo(i);",
+ Spaces);
+ verifyFormat("switch ( x / (y + z) ) {\n"
+ "default:\n"
+ " break;\n"
+ "}",
+ Spaces);
+ verifyFormat("if constexpr ((a = b))\n"
+ " c;",
+ Spaces);
}
TEST_F(FormatTest, ConfigurableSpacesInSquareBrackets) {
More information about the cfe-commits
mailing list