https://github.com/gedare updated https://github.com/llvm/llvm-project/pull/77522
>From a2c2ad9cfdb2edcd2facaef00a7ff9e032d0111b Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Mon, 17 Jul 2023 18:24:30 -0600 Subject: [PATCH 1/3] 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. --- clang/docs/ClangFormatStyleOptions.rst | 28 +- clang/docs/ReleaseNotes.rst | 3 + clang/include/clang/Format/Format.h | 40 ++- clang/lib/Format/Format.cpp | 5 +- clang/lib/Format/TokenAnnotator.cpp | 70 +++-- clang/unittests/Format/ConfigParseTest.cpp | 21 +- clang/unittests/Format/FormatTest.cpp | 314 +++++++++++++++++++++ 7 files changed, 441 insertions(+), 40 deletions(-) diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 1a7d0e6a05e31..2b76f3c244b8a 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -6214,6 +6214,7 @@ the configuration (without a prefix: ``Auto``). # Example of usage: SpacesInParens: Custom SpacesInParensOptions: + ExceptDoubleParentheses: false InConditionalStatements: true InEmptyParentheses: true @@ -6226,9 +6227,23 @@ 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 + between the first two parentheses in situations where a pair of + parentheses have been used. + + .. 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...``). @@ -6242,8 +6257,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`` Put a space in parentheses only if the parentheses are empty i.e. '()' @@ -6261,8 +6277,12 @@ 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; + decltype( ( x ) ) decltype((x)) + x = ( (int32)y ) x = ((int32))y + y = ( (int ( * )( int ))foo )( x ); y = ((int (*)(int))foo)(x); + __attribute__( ( noreturn ) ) __attribute__((noreturn)) .. _SpacesInParentheses: diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 22b4dc172c840..6714f20b4f876 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -990,6 +990,9 @@ clang-format - Adds ``AllowShortCaseExpressionOnASingleLine`` option. - Adds ``AlignCaseArrows`` suboption to ``AlignConsecutiveShortCaseStatements``. - Adds ``LeftWithLastLine`` suboption to ``AlignEscapedNewlines``. +- 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 eb6647038403d..880581edbbd3f 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4650,10 +4650,23 @@ 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 + /// between the first two parentheses in situations where a pair of + /// parentheses have been used. + /// \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 @@ -4664,8 +4677,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; /// Put a space in parentheses only if the parentheses are empty i.e. '()' @@ -4681,23 +4695,30 @@ 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; + /// decltype( ( x ) ) decltype((x)) + /// x = ( (int32)y ) x = ((int32))y + /// y = ( (int ( * )( int ))foo )( x ); y = ((int (*)(int))foo)(x); + /// __attribute__( ( noreturn ) ) __attribute__((noreturn)) /// \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; } @@ -4715,6 +4736,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 c015e03fa15e7..8a8a3927ab5d5 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -721,6 +721,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); @@ -1175,8 +1176,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 26c0aa36bdcb6..8df00fdb3c1a1 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4346,19 +4346,6 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, Right.is(tok::r_brace) && Right.isNot(BK_Block))) { return Style.SpacesInParensOptions.InEmptyParentheses; } - if (Style.SpacesInParensOptions.InConditionalStatements) { - const FormatToken *LeftParen = nullptr; - if (Left.is(tok::l_paren)) - LeftParen = &Left; - else if (Right.is(tok::r_paren) && Right.MatchingParen) - LeftParen = Right.MatchingParen; - if (LeftParen) { - if (LeftParen->is(TT_ConditionLParen)) - return true; - if (LeftParen->Previous && isKeywordWithCondition(*LeftParen->Previous)) - return true; - } - } // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {} if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace, @@ -4385,11 +4372,60 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, } if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) { - return (Right.is(TT_CastRParen) || - (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) - ? Style.SpacesInParensOptions.InCStyleCasts - : Style.SpacesInParensOptions.Other; + const FormatToken *LeftParen = + Left.is(tok::l_paren) ? &Left : Right.MatchingParen; + const FormatToken *RightParen = + LeftParen ? LeftParen->MatchingParen : nullptr; + const auto IsAttributeParen = [](const FormatToken *Paren) { + return Paren && Paren->isOneOf(TT_AttributeLParen, TT_AttributeRParen); + }; + auto AddSpaceExceptInDoubleParens = [&]() { + const auto *RPrev = RightParen ? RightParen->Previous : nullptr; + const auto *LNext = LeftParen->Next; + const auto *LPrev = LeftParen->Previous; + if (!(RPrev && RPrev->is(tok::r_paren) && LNext && + LNext->is(tok::l_paren))) { + return true; + } + auto HasEqualBeforeNextParen = [&]() { + auto *Tok = LNext; + if (!Tok || !Tok->is(tok::l_paren)) + return false; + while ((Tok = Tok->Next) && !Tok->isOneOf(tok::l_paren, tok::r_paren)) + if (Tok->is(tok::equal)) + return true; + return false; + }; + const bool SuppressSpace = + IsAttributeParen(LeftParen) || + (LPrev && (LPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || + (HasEqualBeforeNextParen() && + (LPrev->isOneOf(tok::kw_if, tok::kw_while) || + LPrev->endsSequence(tok::kw_constexpr, tok::kw_if))))); + return !SuppressSpace; + }; + const auto AddSpace = [&](bool Option) { + if (Style.SpacesInParensOptions.ExceptDoubleParentheses && Option) + return AddSpaceExceptInDoubleParens(); + return Option; + }; + + if (LeftParen && (LeftParen->is(TT_ConditionLParen) || + (LeftParen->Previous && + isKeywordWithCondition(*LeftParen->Previous)))) { + return AddSpace(Style.SpacesInParensOptions.InConditionalStatements); + } + if (RightParen && RightParen->is(TT_CastRParen)) + return AddSpace(Style.SpacesInParensOptions.InCStyleCasts); + if (IsAttributeParen(LeftParen) || IsAttributeParen(RightParen)) + return AddSpace(Style.SpacesInParensOptions.Other); + if ((LeftParen && IsAttributeParen(LeftParen->Previous)) || + (RightParen && IsAttributeParen(RightParen->Next))) { + return AddSpace(Style.SpacesInParensOptions.Other); + } + return AddSpace(Style.SpacesInParensOptions.Other); } + if (Right.isOneOf(tok::semi, tok::comma)) return false; if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) { diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp index ff3ced38a1f31..9d622c54519b8 100644 --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -235,6 +235,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); @@ -621,20 +622,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 59f1ff6a4b296..664a6e7b4b9a9 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17108,6 +17108,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();\n", + 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 = {}; @@ -17142,6 +17159,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();\n", + 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 = {}; @@ -17154,6 +17188,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; @@ -17186,6 +17221,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( );\n", + 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; @@ -17293,6 +17345,268 @@ 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; + 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); + + 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); + + Spaces.SpacesInParensOptions.Other = false; + 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); + + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.InCStyleCasts = true; + verifyFormat("x = ( int32 )y;", Spaces); + verifyFormat("y = (( int (*)(int) )foo)(x);", Spaces); + + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + verifyFormat("x = ( int32 )y;", Spaces); + verifyFormat("y = (( int (*)(int) )foo)(x);", Spaces); + + Spaces.SpacesInParensOptions.InCStyleCasts = false; + verifyFormat("x = (int32)y;", Spaces); + verifyFormat("y = ((int (*)(int))foo)(x);", Spaces); + + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.InConditionalStatements = true; + verifyFormat("while ( (bool)1 )\n" + " continue;", + Spaces); + verifyFormat("while ( (i = j) )\n" + " continue;", + Spaces); + verifyFormat("for ( ;; )\n" + " continue;", + Spaces); + verifyFormat("if ( true )\n" + " f();\n" + "else if ( true )\n" + " f();", + 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("switch ( x ) {\n" + "default:\n" + " break;\n" + "}", + Spaces); + verifyFormat("if ( (x - y) && (a ^ b) )\n" + " f();\n", + 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); + verifyFormat("if ( ({ a; }) )\n" + " b;", + Spaces); + + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + verifyFormat("while ( (bool)1 )\n" + " continue;", + Spaces); + verifyFormat("while ((i = j))\n" + " continue;", + Spaces); + verifyFormat("for ( ;; )\n" + " continue;", + Spaces); + verifyFormat("if ( true )\n" + " f();\n" + "else if ( true )\n" + " f();", + 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("switch ( x ) {\n" + "default:\n" + " break;\n" + "}", + Spaces); + verifyFormat("if ( (x - y) && (a ^ b) )\n" + " f();\n", + 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); + + Spaces.SpacesInParensOptions.InConditionalStatements = false; + verifyFormat("while ((bool)1)\n" + " continue;", + Spaces); + verifyFormat("while ((i = j))\n" + " continue;", + Spaces); + verifyFormat("for (;;)\n" + " continue;", + Spaces); + verifyFormat("if (true)\n" + " f();\n" + "else if (true)\n" + " f();", + 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("switch (x) {\n" + "default:\n" + " break;\n" + "}", + Spaces); + verifyFormat("if ((x - y) && (a ^ b))\n" + " f();\n", + 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); + + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.Other = true; + 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("decltype( ( foo->bar ) ) baz;", Spaces); + verifyFormat("if (( i = j ))\n" + " do_something( i );", + Spaces); + verifyFormat("if constexpr (( a = b ))\n" + " c;", + Spaces); + + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + 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("decltype(( foo->bar )) baz;", Spaces); + verifyFormat("if (( i = j ))\n" + " do_something( i );", + Spaces); + verifyFormat("if constexpr (( a = b ))\n" + " c;", + Spaces); + + Spaces.SpacesInParensOptions.Other = false; + 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("decltype((foo->bar)) baz;", Spaces); + verifyFormat("if ((i = j))\n" + " do_something(i);", + Spaces); + verifyFormat("if constexpr ((a = b))\n" + " c;", + Spaces); + + Spaces.SpacesInParens = FormatStyle::SIPO_Custom; + Spaces.SpacesInParensOptions = {}; + Spaces.SpacesInParensOptions.Other = true; + Spaces.SpacesInParensOptions.InConditionalStatements = true; + verifyFormat("if ( ( i = j ) )\n" + " do_something( i );", + Spaces); + verifyFormat("if constexpr ( ( a = b ) )\n" + " c;", + Spaces); + verifyFormat("while ( ( i = j ) )\n" + " continue;", + Spaces); + verifyFormat("do {\n" + " do_something( (int)i );\n" + "} while ( ( i = i + 1 ) );", + Spaces); + + Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; + verifyFormat("if (( i = j ))\n" + " do_something( i );", + Spaces); + verifyFormat("if constexpr (( a = b ))\n" + " c;", + Spaces); + verifyFormat("while (( i = j ))\n" + " continue;", + Spaces); + verifyFormat("do {\n" + " do_something( (int)i );\n" + "} while (( i = i + 1 ));", + Spaces); } TEST_F(FormatTest, ConfigurableSpacesInSquareBrackets) { >From 0cf7ffab47df7f22f102f4e08eb12806ee6c229f Mon Sep 17 00:00:00 2001 From: Owen Pan <owenpi...@gmail.com> Date: Mon, 27 May 2024 15:14:38 -0700 Subject: [PATCH 2/3] Improve the logic. --- clang/lib/Format/TokenAnnotator.cpp | 79 ++++++++++------------------- 1 file changed, 26 insertions(+), 53 deletions(-) diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 8df00fdb3c1a1..5defe368f0218 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4346,6 +4346,28 @@ 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)) + LeftParen = &Left; + else if (Right.is(tok::r_paren) && Right.MatchingParen) + LeftParen = Right.MatchingParen; + if (LeftParen) { + if (LeftParen->is(TT_ConditionLParen)) + return true; + if (LeftParen->Previous && isKeywordWithCondition(*LeftParen->Previous)) + return true; + } + } // trailing return type 'auto': []() -> auto {}, auto foo() -> auto {} if (Left.is(tok::kw_auto) && Right.isOneOf(TT_LambdaLBrace, TT_FunctionLBrace, @@ -4372,60 +4394,11 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, } if (Left.is(tok::l_paren) || Right.is(tok::r_paren)) { - const FormatToken *LeftParen = - Left.is(tok::l_paren) ? &Left : Right.MatchingParen; - const FormatToken *RightParen = - LeftParen ? LeftParen->MatchingParen : nullptr; - const auto IsAttributeParen = [](const FormatToken *Paren) { - return Paren && Paren->isOneOf(TT_AttributeLParen, TT_AttributeRParen); - }; - auto AddSpaceExceptInDoubleParens = [&]() { - const auto *RPrev = RightParen ? RightParen->Previous : nullptr; - const auto *LNext = LeftParen->Next; - const auto *LPrev = LeftParen->Previous; - if (!(RPrev && RPrev->is(tok::r_paren) && LNext && - LNext->is(tok::l_paren))) { - return true; - } - auto HasEqualBeforeNextParen = [&]() { - auto *Tok = LNext; - if (!Tok || !Tok->is(tok::l_paren)) - return false; - while ((Tok = Tok->Next) && !Tok->isOneOf(tok::l_paren, tok::r_paren)) - if (Tok->is(tok::equal)) - return true; - return false; - }; - const bool SuppressSpace = - IsAttributeParen(LeftParen) || - (LPrev && (LPrev->isOneOf(tok::kw___attribute, tok::kw_decltype) || - (HasEqualBeforeNextParen() && - (LPrev->isOneOf(tok::kw_if, tok::kw_while) || - LPrev->endsSequence(tok::kw_constexpr, tok::kw_if))))); - return !SuppressSpace; - }; - const auto AddSpace = [&](bool Option) { - if (Style.SpacesInParensOptions.ExceptDoubleParentheses && Option) - return AddSpaceExceptInDoubleParens(); - return Option; - }; - - if (LeftParen && (LeftParen->is(TT_ConditionLParen) || - (LeftParen->Previous && - isKeywordWithCondition(*LeftParen->Previous)))) { - return AddSpace(Style.SpacesInParensOptions.InConditionalStatements); - } - if (RightParen && RightParen->is(TT_CastRParen)) - return AddSpace(Style.SpacesInParensOptions.InCStyleCasts); - if (IsAttributeParen(LeftParen) || IsAttributeParen(RightParen)) - return AddSpace(Style.SpacesInParensOptions.Other); - if ((LeftParen && IsAttributeParen(LeftParen->Previous)) || - (RightParen && IsAttributeParen(RightParen->Next))) { - return AddSpace(Style.SpacesInParensOptions.Other); - } - return AddSpace(Style.SpacesInParensOptions.Other); + return (Right.is(TT_CastRParen) || + (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) + ? Style.SpacesInParensOptions.InCStyleCasts + : Style.SpacesInParensOptions.Other; } - if (Right.isOneOf(tok::semi, tok::comma)) return false; if (Right.is(tok::less) && Line.Type == LT_ObjCDecl) { >From b76bafa448278c41eda4fffbdf72762af622f58e Mon Sep 17 00:00:00 2001 From: Gedare Bloom <ged...@rtems.org> Date: Fri, 31 May 2024 12:32:43 -0600 Subject: [PATCH 3/3] FormatTest: fix and add test cases for ExceptDoubleParentheses --- clang/unittests/Format/FormatTest.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 664a6e7b4b9a9..dbb06358afd0f 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -17358,6 +17358,8 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { 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); Spaces.SpacesInParensOptions.ExceptDoubleParentheses = true; verifyFormat("SomeType *__attribute__(( attr )) *a = NULL;", Spaces); @@ -17367,6 +17369,8 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { 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); Spaces.SpacesInParensOptions.Other = false; verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces); @@ -17542,10 +17546,10 @@ TEST_F(FormatTest, ConfigurableSpacesInParens) { verifyFormat("decltype( ( foo() ) ) a = foo();", Spaces); verifyFormat("decltype( ( bar( 10 ) ) ) a = bar( 11 );", Spaces); verifyFormat("decltype( ( foo->bar ) ) baz;", Spaces); - verifyFormat("if (( i = j ))\n" + verifyFormat("if ( ( i = j ) )\n" " do_something( i );", Spaces); - verifyFormat("if constexpr (( a = b ))\n" + verifyFormat("if constexpr ( ( a = b ) )\n" " c;", Spaces); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits