diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -5298,6 +5298,21 @@ InConditionalStatements: true Other: true + * ``bool InAttributeSpecifierLists`` Put a space in parentheses inside attribute specifier lists. + + .. code-block:: c++ + + true: false: + __attribute__(( noreturn )) vs. __attribute__((noreturn)) + + * ``bool InAttributeSpecifiers`` Put a space in parentheses around the outside of attribute specifier + lists. + + .. code-block:: c++ + + true: false: + __attribute__( (noreturn) ) vs. __attribute__((noreturn)) + * ``bool InConditionalStatements`` Put a space in parentheses only inside conditional statements (``for/if/while/switch...``). diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -4205,6 +4205,19 @@ /// Other: true /// \endcode struct SpacesInParensCustom { + /// Put a space in parentheses inside attribute specifier lists. + /// \code + /// true: false: + /// __attribute__(( noreturn )) vs. __attribute__((noreturn)) + /// \endcode + bool InAttributeSpecifierLists; + /// Put a space in parentheses around the outside of attribute specifier + /// lists. + /// \code + /// true: false: + /// __attribute__( (noreturn) ) vs. __attribute__((noreturn)) + /// \endcode + bool InAttributeSpecifiers; /// Put a space in parentheses only inside conditional statements /// (``for/if/while/switch...``). /// \code @@ -4238,11 +4251,14 @@ bool Other; SpacesInParensCustom() - : InConditionalStatements(false), InCStyleCasts(false), + : InAttributeSpecifierLists(false), InAttributeSpecifiers(false), + InConditionalStatements(false), InCStyleCasts(false), InEmptyParentheses(false), Other(false) {} bool operator==(const SpacesInParensCustom &R) const { - return InConditionalStatements == R.InConditionalStatements && + return InAttributeSpecifierLists == R.InAttributeSpecifierLists && + InAttributeSpecifiers == R.InAttributeSpecifiers && + InConditionalStatements == R.InConditionalStatements && InCStyleCasts == R.InCStyleCasts && InEmptyParentheses == R.InEmptyParentheses && Other == R.Other; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -713,6 +713,9 @@ template <> struct MappingTraits { static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { + IO.mapOptional("InAttributeSpecifierLists", + Spaces.InAttributeSpecifierLists); + IO.mapOptional("InAttributeSpecifiers", Spaces.InAttributeSpecifiers); IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements); IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses); diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -3810,10 +3810,20 @@ } 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; + if (Right.is(TT_CastRParen) || + (Left.MatchingParen && Left.MatchingParen->is(TT_CastRParen))) { + return Style.SpacesInParensOptions.InCStyleCasts; + } + if (Right.is(TT_AttributeParen) || + (Left.MatchingParen && Left.MatchingParen->is(TT_AttributeParen))) { + return Style.SpacesInParensOptions.InAttributeSpecifiers; + } + if ((Right.Next && Right.Next->is(TT_AttributeParen)) || + (Left.Previous && Left.Previous->MatchingParen && + Left.Previous->MatchingParen->is(TT_AttributeParen))) { + return Style.SpacesInParensOptions.InAttributeSpecifierLists; + } + return Style.SpacesInParensOptions.Other; } if (Right.isOneOf(tok::semi, tok::comma)) return false; diff --git a/clang/unittests/Format/ConfigParseTest.cpp b/clang/unittests/Format/ConfigParseTest.cpp --- a/clang/unittests/Format/ConfigParseTest.cpp +++ b/clang/unittests/Format/ConfigParseTest.cpp @@ -217,6 +217,8 @@ CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterIfMacros); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses); + CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InAttributeSpecifierLists); + CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InAttributeSpecifiers); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InCStyleCasts); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses); diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -16718,6 +16718,8 @@ Spaces.SpacesInParensOptions = {}; Spaces.SpacesInParensOptions.Other = true; Spaces.SpacesInParensOptions.InConditionalStatements = true; + Spaces.SpacesInParensOptions.InAttributeSpecifierLists = true; + Spaces.SpacesInParensOptions.InAttributeSpecifiers = true; verifyFormat("do_something( ::globalVar );", Spaces); verifyFormat("call( x, y, z );", Spaces); verifyFormat("call();", Spaces); @@ -16744,6 +16746,8 @@ " break;\n" "}", Spaces); + verifyFormat("SomeType *__attribute__( ( attr ) ) *a = NULL;", Spaces); + verifyFormat("void __attribute__( ( naked ) ) foo( int bar )", Spaces); Spaces.SpacesInParens = FormatStyle::SIPO_Custom; Spaces.SpacesInParensOptions = {}; @@ -16785,6 +16789,13 @@ " break;\n" "}", Spaces); + verifyFormat("SomeType *__attribute__((attr)) *a = NULL;", Spaces); + + Spaces.SpacesInParensOptions.InAttributeSpecifierLists = true; + verifyFormat("SomeType *__attribute__(( attr )) *a = NULL;", Spaces); + Spaces.SpacesInParensOptions.InAttributeSpecifierLists = false; + Spaces.SpacesInParensOptions.InAttributeSpecifiers = true; + verifyFormat("SomeType *__attribute__( (attr) ) *a = NULL;", Spaces); // Run the first set of tests again with: Spaces.SpaceAfterCStyleCast = true; @@ -16817,6 +16828,7 @@ verifyFormat("bool *y = ( bool * ) ( void * ) (x);", Spaces); verifyFormat("bool *y = ( bool * ) (x);", Spaces); verifyFormat("throw ( int32 ) x;", Spaces); + verifyFormat("SomeType *__attribute__( (attr) ) *a = NULL;", Spaces); // Run subset of tests again with: Spaces.SpacesInParensOptions.InCStyleCasts = false;