diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst --- a/clang/docs/ClangFormatStyleOptions.rst +++ b/clang/docs/ClangFormatStyleOptions.rst @@ -4704,6 +4704,28 @@ true: false: ! someExpression(); vs. !someExpression(); +.. _SpaceAfterOperatorKeyword: + +**SpaceAfterOperatorKeyword** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ ` + If ``true``, a space will be inserted after the 'operator' keyword. + + .. code-block:: c++ + + true: false: + bool operator ==(...); vs. bool operator==(...); + +.. _SpaceAfterOperatorKeywordInCall: + +**SpaceAfterOperatorKeywordInCall** (``Boolean``) :versionbadge:`clang-format 17` :ref:`¶ ` + If ``true``, a space will be inserted after the 'operator' keyword in a call expression. + This option defaults to SpaceAfterOperatorKeyword. + + .. code-block:: c++ + + true: false: + foo.operator ==(...); vs. foo.operator==(...); + foo.Foo::operator ==(...); vs. foo.Foo::operator==(...); + .. _SpaceAfterTemplateKeyword: **SpaceAfterTemplateKeyword** (``Boolean``) :versionbadge:`clang-format 4` :ref:`¶ ` diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -708,6 +708,8 @@ - Add ``BracedInitializerIndentWidth`` which can be used to configure the indentation level of the contents of braced init lists. - Add ``KeepEmptyLinesAtEOF`` to keep empty lines at end of file. +- Add ``SpaceAfterOperatorKeyword`` style option. +- Add ``SpaceAfterOperatorKeywordInCall`` style option. 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 @@ -3692,6 +3692,23 @@ /// \version 9 bool SpaceAfterLogicalNot; + /// If \c true, a space will be inserted after the 'operator' keyword. + /// \code + /// true: false: + /// bool operator ==(...); vs. bool operator==(...); + /// \endcode + /// \version 17 + bool SpaceAfterOperatorKeyword; + + /// If \c true, a space will be inserted after the 'operator' keyword in a + /// call expression. This option defaults to SpaceAfterOperatorKeyword. \code + /// true: false: + /// foo.operator ==(...); vs. foo.operator==(...); + /// foo.Foo::operator ==(...); vs. foo.Foo::operator==(...); + /// \endcode + /// \version 17 + bool SpaceAfterOperatorKeywordInCall; + /// If \c true, a space will be inserted after the 'template' keyword. /// \code /// true: false: @@ -4411,6 +4428,9 @@ SortJavaStaticImport == R.SortJavaStaticImport && SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceAfterLogicalNot == R.SpaceAfterLogicalNot && + SpaceAfterOperatorKeyword == R.SpaceAfterOperatorKeyword && + SpaceAfterOperatorKeywordInCall == + R.SpaceAfterOperatorKeywordInCall && SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && SpaceBeforeCaseColon == R.SpaceBeforeCaseColon && 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 @@ -1000,6 +1000,10 @@ IO.mapOptional("SortUsingDeclarations", Style.SortUsingDeclarations); IO.mapOptional("SpaceAfterCStyleCast", Style.SpaceAfterCStyleCast); IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); + IO.mapOptional("SpaceAfterOperatorKeyword", + Style.SpaceAfterOperatorKeyword); + IO.mapOptional("SpaceAfterOperatorKeywordInCall", + Style.SpaceAfterOperatorKeywordInCall); IO.mapOptional("SpaceAfterTemplateKeyword", Style.SpaceAfterTemplateKeyword); IO.mapOptional("SpaceAroundPointerQualifiers", @@ -1439,6 +1443,8 @@ LLVMStyle.SortUsingDeclarations = FormatStyle::SUD_LexicographicNumeric; LLVMStyle.SpaceAfterCStyleCast = false; LLVMStyle.SpaceAfterLogicalNot = false; + LLVMStyle.SpaceAfterOperatorKeyword = false; + LLVMStyle.SpaceAfterOperatorKeywordInCall = false; LLVMStyle.SpaceAfterTemplateKeyword = true; LLVMStyle.SpaceAroundPointerQualifiers = FormatStyle::SAPQ_Default; LLVMStyle.SpaceBeforeCaseColon = false; 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 @@ -3759,6 +3759,7 @@ Left.Previous->is(tok::kw_operator)) { return false; } + // co_await (x), co_yield (x), co_return (x) if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) && !Right.isOneOf(tok::semi, tok::r_paren)) { @@ -4200,9 +4201,14 @@ // Space in __attribute__((attr)) ::type. if (Left.is(TT_AttributeParen) && Right.is(tok::coloncolon)) return true; - - if (Left.is(tok::kw_operator)) - return Right.is(tok::coloncolon); + if (Left.is(tok::kw_operator)) { + if (Left.Previous && + Left.Previous->isOneOf(tok::coloncolon, tok::period)) { + return Style.SpaceAfterOperatorKeywordInCall || + Right.is(tok::coloncolon); + } + return Style.SpaceAfterOperatorKeyword || Right.is(tok::coloncolon); + } if (Right.is(tok::l_brace) && Right.is(BK_BracedInit) && !Left.opensScope() && Style.SpaceBeforeCpp11BracedList) { return true; 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 @@ -183,6 +183,8 @@ CHECK_PARSE_BOOL(SpacesInContainerLiterals); CHECK_PARSE_BOOL(SpacesInCStyleCastParentheses); CHECK_PARSE_BOOL(SpaceAfterCStyleCast); + CHECK_PARSE_BOOL(SpaceAfterOperatorKeyword); + CHECK_PARSE_BOOL(SpaceAfterOperatorKeywordInCall); CHECK_PARSE_BOOL(SpaceAfterTemplateKeyword); CHECK_PARSE_BOOL(SpaceAfterLogicalNot); CHECK_PARSE_BOOL(SpaceBeforeAssignmentOperators); 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 @@ -22901,8 +22901,25 @@ Spaces); } +TEST_F(FormatTest, SpaceAfterOperatorKeyword) { + FormatStyle Style = getLLVMStyle(); + verifyFormat("bool operator==();", Style); + Style.SpaceAfterOperatorKeyword = true; + verifyFormat("bool operator ==();", Style); +} + +TEST_F(FormatTest, SpaceAfterOperatorKeywordInCall) { + FormatStyle Style = getLLVMStyle(); + verifyFormat("foo.operator==();", Style); + verifyFormat("foo.Foo::operator==();", Style); + Style.SpaceAfterOperatorKeywordInCall = true; + verifyFormat("foo.operator ==();", Style); + verifyFormat("foo.Foo::operator ==();", Style); +} + TEST_F(FormatTest, SpaceAfterTemplateKeyword) { FormatStyle Style = getLLVMStyle(); + verifyFormat("template void foo();", Style); Style.SpaceAfterTemplateKeyword = false; verifyFormat("template void foo();", Style); }