diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst index 4f3a9eb9f4a6..5a52916acc55 100644 --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -3818,6 +3818,15 @@ the configuration (without a prefix: ``Auto``). IF (...) vs. IF(...) + * ``bool AfterOverloadedOperator`` If ``true``, put a space between operator overloading and opening + parentheses. + + .. code-block:: c++ + + true: false: + void operator++ (int a); vs. void operator++(int a); + object.operator++ (10); object.operator++(10); + * ``bool BeforeNonEmptyParentheses`` If ``true``, put a space before opening parentheses only if the parentheses are not empty. diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2f48b1424d09..7e24d06567fc 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -311,6 +311,9 @@ clang-format - Improved C++20 Modules and Coroutines support. +- Option ``AfterOverloadedOperator`` has been added in ``SpaceBeforeParensOptions`` + to allow space between overloaded operator and opening parentheses. + libclang -------- diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h index 24c245642e6a..d3113a5fdba4 100644 --- a/clang/include/clang/Format/Format.h +++ b/clang/include/clang/Format/Format.h @@ -3429,6 +3429,14 @@ struct FormatStyle { /// /// \endcode bool AfterIfMacros; + /// If ``true``, put a space between operator overloading and opening + /// parentheses. + /// \code + /// true: false: + /// void operator++ (int a); vs. void operator++(int a); + /// object.operator++ (10); object.operator++(10); + /// \endcode + bool AfterOverloadedOperator; /// If ``true``, put a space before opening parentheses only if the /// parentheses are not empty. /// \code @@ -3442,7 +3450,7 @@ struct FormatStyle { : AfterControlStatements(false), AfterForeachMacros(false), AfterFunctionDeclarationName(false), AfterFunctionDefinitionName(false), AfterIfMacros(false), - BeforeNonEmptyParentheses(false) {} + AfterOverloadedOperator(false), BeforeNonEmptyParentheses(false) {} bool operator==(const SpaceBeforeParensCustom &Other) const { return AfterControlStatements == Other.AfterControlStatements && @@ -3451,6 +3459,7 @@ struct FormatStyle { Other.AfterFunctionDeclarationName && AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName && AfterIfMacros == Other.AfterIfMacros && + AfterOverloadedOperator == Other.AfterOverloadedOperator && BeforeNonEmptyParentheses == Other.BeforeNonEmptyParentheses; } }; diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp index 11c190ebfba7..a4ce8a20a940 100644 --- a/clang/lib/Format/Format.cpp +++ b/clang/lib/Format/Format.cpp @@ -868,6 +868,7 @@ template <> struct MappingTraits { IO.mapOptional("AfterFunctionDeclarationName", Spacing.AfterFunctionDeclarationName); IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros); + IO.mapOptional("AfterOverloadedOperator", Spacing.AfterOverloadedOperator); IO.mapOptional("BeforeNonEmptyParentheses", Spacing.BeforeNonEmptyParentheses); } diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index a161ee87e6b5..5b3a450e31f2 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -2923,9 +2923,15 @@ unsigned TokenAnnotator::splitPenalty(const AnnotatedLine &Line, } bool TokenAnnotator::spaceRequiredBeforeParens(const FormatToken &Right) const { - return Style.SpaceBeforeParens == FormatStyle::SBPO_Always || - (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses && - Right.ParameterCount > 0); + if (Style.SpaceBeforeParens == FormatStyle::SBPO_Always) + return true; + if (Right.is(TT_OverloadedOperatorLParen) && + Style.SpaceBeforeParensOptions.AfterOverloadedOperator) + return true; + if (Style.SpaceBeforeParensOptions.BeforeNonEmptyParentheses && + Right.ParameterCount > 0) + return true; + return false; } bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line, diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 71f07412a3b6..1d622e80ed12 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -14536,6 +14536,24 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) { // verifyFormat("X A::operator++ (T);", SomeSpace2); verifyFormat("int x = int (y);", SomeSpace2); verifyFormat("auto lambda = []() { return 0; };", SomeSpace2); + + FormatStyle SpaceAfterOverloadedOperator = getLLVMStyle(); + SpaceAfterOverloadedOperator.SpaceBeforeParens = FormatStyle::SBPO_Custom; + SpaceAfterOverloadedOperator.SpaceBeforeParensOptions + .AfterOverloadedOperator = true; + + verifyFormat("auto operator++ () -> int;", SpaceAfterOverloadedOperator); + verifyFormat("X A::operator++ ();", SpaceAfterOverloadedOperator); + verifyFormat("some_object.operator++ ();", SpaceAfterOverloadedOperator); + verifyFormat("auto func() -> int;", SpaceAfterOverloadedOperator); + + SpaceAfterOverloadedOperator.SpaceBeforeParensOptions + .AfterOverloadedOperator = false; + + verifyFormat("auto operator++() -> int;", SpaceAfterOverloadedOperator); + verifyFormat("X A::operator++();", SpaceAfterOverloadedOperator); + verifyFormat("some_object.operator++();", SpaceAfterOverloadedOperator); + verifyFormat("auto func() -> int;", SpaceAfterOverloadedOperator); } TEST_F(FormatTest, SpaceAfterLogicalNot) { @@ -18771,6 +18789,15 @@ TEST_F(FormatTest, ParsesConfigurationBools) { CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyFunction); CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyRecord); CHECK_PARSE_NESTED_BOOL(BraceWrapping, SplitEmptyNamespace); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterControlStatements); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterForeachMacros); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, + AfterFunctionDeclarationName); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, + AfterFunctionDefinitionName); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterIfMacros); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, AfterOverloadedOperator); + CHECK_PARSE_NESTED_BOOL(SpaceBeforeParensOptions, BeforeNonEmptyParentheses); } #undef CHECK_PARSE_BOOL