Index: include/clang/Format/Format.h =================================================================== --- include/clang/Format/Format.h +++ include/clang/Format/Format.h @@ -1718,6 +1718,9 @@ /// Defines in which cases to put a space before opening parentheses. SpaceBeforeParensOptions SpaceBeforeParens; + /// Defines whether a space should be placed after a logical `!` + bool SpaceAfterLogicalNot; + /// If ``false``, spaces will be removed before range-based for loop /// colon. /// \code @@ -1726,7 +1729,7 @@ /// \endcode bool SpaceBeforeRangeBasedForLoopColon; - /// If ``true``, spaces may be inserted into ``()``. + /// \brief If ``true``, spaces may be inserted into ``()``. /// \code /// true: false: /// void f( ) { vs. void f() { @@ -1918,6 +1921,7 @@ R.SpaceBeforeCtorInitializerColon && SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon && SpaceBeforeParens == R.SpaceBeforeParens && + SpaceAfterLogicalNot == R.SpaceAfterLogicalNot && SpaceBeforeRangeBasedForLoopColon == R.SpaceBeforeRangeBasedForLoopColon && SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && Index: lib/Format/Format.cpp =================================================================== --- lib/Format/Format.cpp +++ lib/Format/Format.cpp @@ -489,6 +489,7 @@ IO.mapOptional("SpaceBeforeInheritanceColon", Style.SpaceBeforeInheritanceColon); IO.mapOptional("SpaceBeforeParens", Style.SpaceBeforeParens); + IO.mapOptional("SpaceAfterLogicalNot", Style.SpaceAfterLogicalNot); IO.mapOptional("SpaceBeforeRangeBasedForLoopColon", Style.SpaceBeforeRangeBasedForLoopColon); IO.mapOptional("SpaceInEmptyParentheses", Style.SpaceInEmptyParentheses); @@ -726,6 +727,7 @@ LLVMStyle.ReflowComments = true; LLVMStyle.SpacesInParentheses = false; LLVMStyle.SpacesInSquareBrackets = false; + LLVMStyle.SpaceAfterLogicalNot = false; LLVMStyle.SpaceInEmptyParentheses = false; LLVMStyle.SpacesInContainerLiterals = true; LLVMStyle.SpacesInCStyleCastParentheses = false; Index: lib/Format/TokenAnnotator.cpp =================================================================== --- lib/Format/TokenAnnotator.cpp +++ lib/Format/TokenAnnotator.cpp @@ -2831,8 +2831,10 @@ return false; return true; } - if (Left.is(TT_UnaryOperator)) - return Right.is(TT_BinaryOperator); + if (Left.is(TT_UnaryOperator)) { + return (Style.SpaceAfterLogicalNot && Left.is(tok::exclaim)) || + Right.is(TT_BinaryOperator); + } // If the next token is a binary operator or a selector name, we have // incorrectly classified the parenthesis as a cast. FIXME: Detect correctly. Index: unittests/Format/FormatTest.cpp =================================================================== --- unittests/Format/FormatTest.cpp +++ unittests/Format/FormatTest.cpp @@ -9683,6 +9683,16 @@ verifyFormat("auto lambda = []() { return 0; };", SomeSpace); } +TEST_F(FormatTest, SpaceAfterLogicalNot) { + FormatStyle Spaces = getLLVMStyle(); + Spaces.SpaceAfterLogicalNot = true; + + verifyFormat("bool x = ! y", Spaces); + verifyFormat("if (! isFailure())", Spaces); + verifyFormat("if (! (a && b))", Spaces); + verifyFormat("\"Error!\"", Spaces); +} + TEST_F(FormatTest, ConfigurableSpacesInParentheses) { FormatStyle Spaces = getLLVMStyle(); @@ -11475,6 +11485,12 @@ CHECK_PARSE("SpaceAfterControlStatementKeyword: true", SpaceBeforeParens, FormatStyle::SBPO_ControlStatements); + Style.SpaceAfterLogicalNot = false; + CHECK_PARSE("SpaceAfterLogicalNot: true", SpaceAfterLogicalNot, + true); + CHECK_PARSE("SpaceAfterLogicalNot: false", SpaceAfterLogicalNot, + false); + Style.ColumnLimit = 123; FormatStyle BaseStyle = getLLVMStyle(); CHECK_PARSE("BasedOnStyle: LLVM", ColumnLimit, BaseStyle.ColumnLimit);