diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -5527,6 +5527,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 @@ -850,6 +850,8 @@ - Add ``AllowBreakBeforeNoexceptSpecifier`` option. - Add ``AllowShortCompoundRequirementOnASingleLine`` option. - Change ``BreakAfterAttributes`` from ``Never`` to ``Leave`` in LLVM style. +- 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 @@ -4420,6 +4420,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 @@ -4453,17 +4459,20 @@ bool Other; SpacesInParensCustom() - : InConditionalStatements(false), InCStyleCasts(false), - InEmptyParentheses(false), Other(false) {} + : InAttributeSpecifiers(false), InConditionalStatements(false), + InCStyleCasts(false), InEmptyParentheses(false), Other(false) {} - SpacesInParensCustom(bool InConditionalStatements, bool InCStyleCasts, + SpacesInParensCustom(bool InAttributeSpecifiers, + bool InConditionalStatements, bool InCStyleCasts, bool InEmptyParentheses, bool Other) - : InConditionalStatements(InConditionalStatements), + : 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; } 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 @@ -752,6 +752,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); @@ -1186,6 +1187,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 @@ -3967,10 +3967,19 @@ } 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.isOneOf(TT_AttributeLParen, TT_AttributeRParen) || + Right.isOneOf(TT_AttributeLParen, TT_AttributeRParen) || + (Left.Previous && Left.Previous->isOneOf(TT_AttributeLParen, + TT_AttributeRParen)) || + (Right.Next && Right.Next->isOneOf(TT_AttributeLParen, + TT_AttributeRParen))) { + 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 @@ -230,6 +230,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); @@ -625,19 +626,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 @@ -16680,6 +16680,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); @@ -16754,6 +16755,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);