diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index d4ce01e327844..3015cd2be8879 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -4414,6 +4414,14 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, 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; @@ -4487,14 +4495,6 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, 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)) diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 64807e144ae10..5fa56a9048b03 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -6440,6 +6440,43 @@ TEST_F(FormatTest, AllowBinPackingInsideArguments) { 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) {}", @@ -24054,6 +24091,40 @@ TEST_F(FormatTest, RequiresClauses) { " }\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); + // Not a clause, but we once hit an assert. verifyFormat("#if 0\n" "#else\n"