diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -5397,6 +5397,13 @@ InConditionalStatements: true Other: true + * ``bool InAttributeSpecifiers`` Put a space in parentheses of attribute specifiers. + + .. 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/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -171,6 +171,8 @@ clang-format ------------ +- Add ``InAttributeSpecifiers`` style option to ``SpacesInParensOptions`` + to control addition of spaces after the ``__attribute__`` keyword. libclang -------- 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 @@ -4303,6 +4303,12 @@ /// Other: true /// \endcode struct SpacesInParensCustom { + /// Put a space in parentheses of attribute specifiers. + /// \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 @@ -4336,21 +4342,22 @@ bool Other; SpacesInParensCustom() - : InConditionalStatements(false), InCStyleCasts(false), - InEmptyParentheses(false), Other(false) {} - - SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts, - bool InEmptyParentheses, bool Other) - : InConditionalStatements(InConditionalStatements), - InCStyleCasts(InCStyleCasts), - InEmptyParentheses(InEmptyParentheses), + : InAttributeSpecifiers(false), InConditionalStatements(false), + InCStyleCasts(false), InEmptyParentheses(false), Other(false) {} + + SpacesInParensCustom(bool InAttributeSpecifiers, + bool InConditionalStatements, bool InCStyleCasts, + bool InEmptyParentheses, bool Other) + : InAttributeSpecifiers(InAttributeSpecifiers), + InConditionalStatements(InConditionalStatements), + InCStyleCasts(InCStyleCasts), InEmptyParentheses(InEmptyParentheses), Other(Other) {} bool operator==(const SpacesInParensCustom &R) const { - return InConditionalStatements == R.InConditionalStatements && + return InAttributeSpecifiers == R.InAttributeSpecifiers && + InConditionalStatements == R.InConditionalStatements && InCStyleCasts == R.InCStyleCasts && - InEmptyParentheses == R.InEmptyParentheses && - Other == R.Other; + InEmptyParentheses == R.InEmptyParentheses && Other == R.Other; } bool operator!=(const SpacesInParensCustom &R) const { return !(*this == R); 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 @@ -724,6 +724,7 @@ template <> struct MappingTraits { static void mapping(IO &IO, FormatStyle::SpacesInParensCustom &Spaces) { + IO.mapOptional("InAttributeSpecifiers", Spaces.InAttributeSpecifiers); IO.mapOptional("InCStyleCasts", Spaces.InCStyleCasts); IO.mapOptional("InConditionalStatements", Spaces.InConditionalStatements); IO.mapOptional("InEmptyParentheses", Spaces.InEmptyParentheses); @@ -1154,6 +1155,7 @@ if (SpacesInParentheses) { // set all options except InCStyleCasts and InEmptyParentheses // to true for backward compatibility. + Style.SpacesInParensOptions.InAttributeSpecifiers = true; Style.SpacesInParensOptions.InConditionalStatements = true; Style.SpacesInParensOptions.InCStyleCasts = SpacesInCStyleCastParentheses; 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 @@ -3813,10 +3813,16 @@ } 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 (Left.is(TT_AttributeParen) || Right.is(TT_AttributeParen) || + (Left.Previous && Left.Previous->is(TT_AttributeParen)) || + (Right.Next && Right.Next->is(TT_AttributeParen))) { + return Style.SpacesInParensOptions.InAttributeSpecifiers; + } + 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 @@ -222,6 +222,7 @@ CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterIfMacros); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator); CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses); + CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InAttributeSpecifiers); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InCStyleCasts); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InConditionalStatements); CHECK_PARSE_NESTED_BOOL(SpacesInParensOptions, InEmptyParentheses); @@ -599,19 +600,23 @@ Style.SpacesInParens = FormatStyle::SIPO_Never; Style.SpacesInParensOptions = {}; CHECK_PARSE("SpacesInParentheses: true", SpacesInParensOptions, - FormatStyle::SpacesInParensCustom(true, false, false, true)); + FormatStyle::SpacesInParensCustom(true, true, false, false, + true)); Style.SpacesInParens = FormatStyle::SIPO_Never; Style.SpacesInParensOptions = {}; CHECK_PARSE("SpacesInConditionalStatement: true", SpacesInParensOptions, - FormatStyle::SpacesInParensCustom(true, false, false, false)); + 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)); + 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)); + 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 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -16748,6 +16748,7 @@ Spaces.SpacesInParensOptions = {}; Spaces.SpacesInParensOptions.Other = true; Spaces.SpacesInParensOptions.InConditionalStatements = true; + Spaces.SpacesInParensOptions.InAttributeSpecifiers = true; verifyFormat("do_something( ::globalVar );", Spaces); verifyFormat("call( x, y, z );", Spaces); verifyFormat("call();", Spaces); @@ -16822,6 +16823,12 @@ verifyFormat("void __attribute__((naked)) foo(int bar)", Spaces); verifyFormat("void f( ) __attribute__((asdf));", Spaces); + Spaces.SpacesInParensOptions.InAttributeSpecifiers = true; + verifyFormat("SomeType *__attribute__( ( attr ) ) *a = NULL;", Spaces); + verifyFormat("void __attribute__( ( naked ) ) foo(int bar)", Spaces); + verifyFormat("void f( ) __attribute__( ( asdf ) );", Spaces); + Spaces.SpacesInParensOptions.InAttributeSpecifiers = false; + // Run the first set of tests again with: Spaces.SpaceAfterCStyleCast = true; verifyFormat("call(x, y, z);", Spaces);