Index: clang/lib/Format/TokenAnnotator.cpp =================================================================== --- clang/lib/Format/TokenAnnotator.cpp +++ clang/lib/Format/TokenAnnotator.cpp @@ -4410,6 +4410,14 @@ return false; if (Left.is(TT_TemplateCloser) && Right.is(TT_TemplateOpener)) return true; + if ((Left.is(tok::greater) && Right.is(tok::greater)) || + (Left.is(tok::less) && Right.is(tok::less))) + return false; + if (Right.is(TT_BinaryOperator) && + Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None && + (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All || + Right.getPrecedence() != prec::Assignment)) + return true; if (Left.isOneOf(TT_TemplateCloser, TT_UnaryOperator) || Left.is(tok::kw_operator)) return false; @@ -4483,14 +4491,6 @@ if (Right.is(TT_InheritanceComma) && Style.BreakInheritanceList == FormatStyle::BILS_BeforeComma) return true; - if ((Left.is(tok::greater) && Right.is(tok::greater)) || - (Left.is(tok::less) && Right.is(tok::less))) - return false; - if (Right.is(TT_BinaryOperator) && - Style.BreakBeforeBinaryOperators != FormatStyle::BOS_None && - (Style.BreakBeforeBinaryOperators == FormatStyle::BOS_All || - Right.getPrecedence() != prec::Assignment)) - return true; if (Left.is(TT_ArrayInitializerLSquare)) return true; if (Right.is(tok::kw_typename) && Left.isNot(tok::kw_const)) Index: clang/unittests/Format/FormatTest.cpp =================================================================== --- clang/unittests/Format/FormatTest.cpp +++ clang/unittests/Format/FormatTest.cpp @@ -6440,6 +6440,46 @@ Style); } +TEST_F(FormatTest, BreakBinaryOperatorsInPresenceOfTemplates) { + auto Style = getLLVMStyleWithColumns(45); + EXPECT_EQ(Style.BreakBeforeBinaryOperators, FormatStyle::BOS_None); + verifyFormat( + "bool b =\n" + " is_default_constructible_v> and\n" + " is_copy_constructible_v> and\n" + " is_move_constructible_v> and\n" + " is_copy_assignable_v> and\n" + " is_move_assignable_v> and\n" + " is_destructible_v> and\n" + " is_swappable_v> and\n" + " is_callable_v(T)>;", + Style); + + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_NonAssignment; + verifyFormat( + "bool b = is_default_constructible_v>\n" + " and is_copy_constructible_v>\n" + " and is_move_constructible_v>\n" + " and is_copy_assignable_v>\n" + " and is_move_assignable_v>\n" + " and is_destructible_v>\n" + " and is_swappable_v>\n" + " and is_callable_v(T)>;", + Style); + + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + verifyFormat( + "bool b = is_default_constructible_v>\n" + " and is_copy_constructible_v>\n" + " and is_move_constructible_v>\n" + " and is_copy_assignable_v>\n" + " and is_move_assignable_v>\n" + " and is_destructible_v>\n" + " and is_swappable_v>\n" + " and is_callable_v(T)>;", + Style); +} + TEST_F(FormatTest, ConstructorInitializers) { verifyFormat("Constructor() : Initializer(FitsOnTheLine) {}"); verifyFormat("Constructor() : Inttializer(FitsOnTheLine) {}", @@ -24060,6 +24100,40 @@ " return number_zero_v;\n" " }\n" "};"); + + auto Style = getLLVMStyle(); + + verifyFormat( + "template \n" + " requires is_default_constructible_v> and\n" + " is_copy_constructible_v> and\n" + " is_move_constructible_v> and\n" + " is_copy_assignable_v> and " + "is_move_assignable_v> and\n" + " is_destructible_v> and is_swappable_v> and\n" + " is_callable_v(T)> and\n" + " is_same_v(declval()))> and\n" + " is_same_v(declval()))> and\n" + " is_same_v(declval()))>\n" + "struct S {};", + Style); + + Style.BreakBeforeBinaryOperators = FormatStyle::BOS_All; + verifyFormat( + "template \n" + " requires is_default_constructible_v>\n" + " and is_copy_constructible_v>\n" + " and is_move_constructible_v>\n" + " and is_copy_assignable_v> and " + "is_move_assignable_v>\n" + " and is_destructible_v> and is_swappable_v>\n" + " and is_callable_v(T)>\n" + " and is_same_v(declval()))>\n" + " and is_same_v(declval()))>\n" + " and is_same_v(declval()))>\n" + "struct S {};", + Style); } TEST_F(FormatTest, StatementAttributeLikeMacros) {