Index: clang/docs/ClangFormatStyleOptions.rst =================================================================== --- clang/docs/ClangFormatStyleOptions.rst +++ clang/docs/ClangFormatStyleOptions.rst @@ -4004,6 +4004,27 @@ void operator++ (int a); vs. void operator++(int a); object.operator++ (10); object.operator++(10); + * ``bool AfterRequiresKeywordInRequiresClause`` If ``true``, put space between requires keyword in a requires clause and + opening parentheses, if there is one. + + .. code-block:: c++ + + true: false: + template vs. template + requires (A && B) requires(A && B) + ... ... + + * ``bool AfterRequiresKeywordInRequiresExpression`` If ``true``, put space between requires keyword in a requires expression + and opening parentheses. + + .. code-block:: c++ + + true: false: + template vs. template + concept C = requires (T t) { concept C = requires(T t) { + ... ... + } } + * ``bool BeforeNonEmptyParentheses`` If ``true``, put a space before opening parentheses only if the parentheses are not empty. Index: clang/include/clang/Format/Format.h =================================================================== --- clang/include/clang/Format/Format.h +++ clang/include/clang/Format/Format.h @@ -3594,6 +3594,25 @@ /// object.operator++ (10); object.operator++(10); /// \endcode bool AfterOverloadedOperator; + /// If ``true``, put space between requires keyword in a requires clause and + /// opening parentheses, if there is one. + /// \code + /// true: false: + /// template vs. template + /// requires (A && B) requires(A && B) + /// ... ... + /// \endcode + bool AfterRequiresKeywordInRequiresClause; + /// If ``true``, put space between requires keyword in a requires expression + /// and opening parentheses. + /// \code + /// true: false: + /// template vs. template + /// concept C = requires (T t) { concept C = requires(T t) { + /// ... ... + /// } } + /// \endcode + bool AfterRequiresKeywordInRequiresExpression; /// If ``true``, put a space before opening parentheses only if the /// parentheses are not empty. /// \code @@ -3607,7 +3626,10 @@ : AfterControlStatements(false), AfterForeachMacros(false), AfterFunctionDeclarationName(false), AfterFunctionDefinitionName(false), AfterIfMacros(false), - AfterOverloadedOperator(false), BeforeNonEmptyParentheses(false) {} + AfterOverloadedOperator(false), + AfterRequiresKeywordInRequiresClause(false), + AfterRequiresKeywordInRequiresExpression(false), + BeforeNonEmptyParentheses(false) {} bool operator==(const SpaceBeforeParensCustom &Other) const { return AfterControlStatements == Other.AfterControlStatements && @@ -3617,6 +3639,10 @@ AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName && AfterIfMacros == Other.AfterIfMacros && AfterOverloadedOperator == Other.AfterOverloadedOperator && + AfterRequiresKeywordInRequiresClause == + Other.AfterRequiresKeywordInRequiresClause && + AfterRequiresKeywordInRequiresExpression == + Other.AfterRequiresKeywordInRequiresExpression && BeforeNonEmptyParentheses == Other.BeforeNonEmptyParentheses; } }; Index: clang/lib/Format/Format.cpp =================================================================== --- clang/lib/Format/Format.cpp +++ clang/lib/Format/Format.cpp @@ -898,6 +898,10 @@ Spacing.AfterFunctionDeclarationName); IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); + IO.mapOptional("AfterRequiresKeywordInRequiresClause", + Spacing.AfterRequiresKeywordInRequiresClause); + IO.mapOptional("AfterRequiresKeywordInRequiresExpression", + Spacing.AfterRequiresKeywordInRequiresExpression); IO.mapOptional("BeforeNonEmptyParentheses", Spacing.BeforeNonEmptyParentheses); } @@ -1259,6 +1263,7 @@ LLVMStyle.SpaceBeforeCtorInitializerColon = true; LLVMStyle.SpaceBeforeInheritanceColon = true; LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements; + LLVMStyle.SpaceBeforeParensOptions = {}; LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true; LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true; LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true; Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -3211,8 +3211,14 @@ if (Right.is(tok::l_paren)) { if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen)) return spaceRequiredBeforeParens(Right); - if (Left.is(tok::kw_requires)) - return spaceRequiredBeforeParens(Right); + if (Left.isOneOf(TT_RequiresClause, TT_RequiresClauseInARequiresExpression)) + return Style.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresClause || + spaceRequiredBeforeParens(Right); + if (Left.is(TT_RequiresExpression)) + return Style.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresExpression || + spaceRequiredBeforeParens(Right); if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) || (Left.is(tok::r_square) && Left.is(TT_AttributeSquare))) return true; Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -14912,6 +14912,88 @@ verifyFormat("X A::operator++();", SpaceAfterOverloadedOperator); verifyFormat("some_object.operator++();", SpaceAfterOverloadedOperator); verifyFormat("auto func() -> int;", SpaceAfterOverloadedOperator); + + auto SpaceAfterRequires = getLLVMStyle(); + SpaceAfterRequires.SpaceBeforeParens = FormatStyle::SBPO_Custom; + EXPECT_FALSE(SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresClause); + EXPECT_FALSE(SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresExpression); + verifyFormat("void f(auto x)\n" + " requires requires(int i) { x + i; }\n" + "{}", + SpaceAfterRequires); + verifyFormat("void f(auto x)\n" + " requires(requires(int i) { x + i; })\n" + "{}", + SpaceAfterRequires); + verifyFormat("if (requires(int i) { x + i; })\n" + " return;", + SpaceAfterRequires); + verifyFormat("bool b = requires(int i) { x + i; };", SpaceAfterRequires); + verifyFormat("template \n" + " requires(Foo)\n" + "class Bar;", + SpaceAfterRequires); + + SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresClause = true; + verifyFormat("void f(auto x)\n" + " requires requires(int i) { x + i; }\n" + "{}", + SpaceAfterRequires); + verifyFormat("void f(auto x)\n" + " requires (requires(int i) { x + i; })\n" + "{}", + SpaceAfterRequires); + verifyFormat("if (requires(int i) { x + i; })\n" + " return;", + SpaceAfterRequires); + verifyFormat("bool b = requires(int i) { x + i; };", SpaceAfterRequires); + verifyFormat("template \n" + " requires (Foo)\n" + "class Bar;", + SpaceAfterRequires); + + SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresClause = false; + SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresExpression = true; + verifyFormat("void f(auto x)\n" + " requires requires (int i) { x + i; }\n" + "{}", + SpaceAfterRequires); + verifyFormat("void f(auto x)\n" + " requires(requires (int i) { x + i; })\n" + "{}", + SpaceAfterRequires); + verifyFormat("if (requires (int i) { x + i; })\n" + " return;", + SpaceAfterRequires); + verifyFormat("bool b = requires (int i) { x + i; };", SpaceAfterRequires); + verifyFormat("template \n" + " requires(Foo)\n" + "class Bar;", + SpaceAfterRequires); + + SpaceAfterRequires.SpaceBeforeParensOptions + .AfterRequiresKeywordInRequiresClause = true; + verifyFormat("void f(auto x)\n" + " requires requires (int i) { x + i; }\n" + "{}", + SpaceAfterRequires); + verifyFormat("void f(auto x)\n" + " requires (requires (int i) { x + i; })\n" + "{}", + SpaceAfterRequires); + verifyFormat("if (requires (int i) { x + i; })\n" + " return;", + SpaceAfterRequires); + verifyFormat("bool b = requires (int i) { x + i; };", SpaceAfterRequires); + verifyFormat("template \n" + " requires (Foo)\n" + "class Bar;", + SpaceAfterRequires); } TEST_F(FormatTest, SpaceAfterLogicalNot) {