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

Reply via email to