https://github.com/ChrisLee02 updated https://github.com/llvm/llvm-project/pull/228085
>From d84b258b67e6c65c8b23761665b93b4c6c0af924 Mon Sep 17 00:00:00 2001 From: Chrislee02 <[email protected]> Date: Thu, 1 Oct 2026 21:46:08 +0900 Subject: [PATCH 1/3] [clang-format] Add baseline tests for BreakAfterOpenBracket options --- clang/unittests/Format/AlignBracketsTest.cpp | 92 ++++++++++++++++++++ 1 file changed, 92 insertions(+) diff --git a/clang/unittests/Format/AlignBracketsTest.cpp b/clang/unittests/Format/AlignBracketsTest.cpp index e7e57bf839c0e1..171872d6740774 100644 --- a/clang/unittests/Format/AlignBracketsTest.cpp +++ b/clang/unittests/Format/AlignBracketsTest.cpp @@ -861,6 +861,98 @@ TEST_F(AlignBracketsTest, BlockIndentAndNamespace) { Style); } +TEST_F(AlignBracketsTest, BreakAfterOpenBracketIfStatement) { + auto Style = getLLVMStyleWithColumns(40); + Style.PackArguments.BinPack = FormatStyle::BPAS_OnePerLine; + Style.BreakAfterOpenBracketIf = true; + + verifyFormat("void f() {\n" + " if (call(aaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbb,\n" + " cccccccccccccccccccc) < 0)\n" + " return;\n" + "}", + "void f() {\n" + " if (call(aaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, " + "cccccccccccccccccccc) < 0) return;\n" + "}", + Style); +} + +TEST_F(AlignBracketsTest, BreakAfterOpenBracketFunctionCall) { + auto Style = getLLVMStyleWithColumns(40); + Style.PackArguments.BinPack = FormatStyle::BPAS_OnePerLine; + Style.BreakAfterOpenBracketFunction = true; + + verifyFormat("void f() {\n" + " g(aaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbb,\n" + " cccccccccccccccccccc);\n" + "}", + "void f() {\n" + " g(aaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, " + "cccccccccccccccccccc);\n" + "}", + Style); +} + +TEST_F(AlignBracketsTest, BreakAfterOpenBracketLoopStatement) { + auto Style = getLLVMStyleWithColumns(40); + Style.ContinuationIndentWidth = 7; + Style.PackArguments.BinPack = FormatStyle::BPAS_OnePerLine; + Style.BreakAfterOpenBracketLoop = true; + + verifyFormat("void f() {\n" + " while (call(aaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbb,\n" + " cccccccccccccccccccc) < 0)\n" + " return;\n" + "}", + "void f() {\n" + " while (call(aaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, " + "cccccccccccccccccccc) < 0) return;\n" + "}", + Style); +} + +TEST_F(AlignBracketsTest, BreakAfterOpenBracketSwitchStatement) { + auto Style = getLLVMStyleWithColumns(40); + Style.ContinuationIndentWidth = 8; + Style.PackArguments.BinPack = FormatStyle::BPAS_OnePerLine; + Style.BreakAfterOpenBracketSwitch = true; + + verifyFormat("void f() {\n" + " switch (call(aaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbb,\n" + " cccccccccccccccccccc)) {\n" + " default:\n" + " return;\n" + " }\n" + "}", + "void f() {\n" + " switch (call(aaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, " + "cccccccccccccccccccc)) { default: return; }\n" + "}", + Style); +} + +TEST_F(AlignBracketsTest, BreakAfterOpenBracketBracedList) { + auto Style = getLLVMStyle(); + Style.ContinuationIndentWidth = 11; + Style.BreakAfterOpenBracketBracedList = true; + + verifyFormat("void f() {\n" + " int a[] = {111111111111111111, 222222222222222222, " + "333333333333333333,\n" + " 444444444444444444};\n" + "}", + "void f() {\n" + " int a[] = {111111111111111111, 222222222222222222, " + "333333333333333333, 444444444444444444};\n" + "}", + Style); +} + } // namespace } // namespace test } // namespace format >From dbe30504212d86a1ed61755081727181f3b5df55 Mon Sep 17 00:00:00 2001 From: Chrislee02 <[email protected]> Date: Thu, 1 Oct 2026 23:00:40 +0900 Subject: [PATCH 2/3] [clang-format] Fix BreakAfterOpenBracket options being ignored with larger continuation indents --- clang/lib/Format/ContinuationIndenter.cpp | 10 ++++++++-- clang/unittests/Format/AlignBracketsTest.cpp | 19 ++++++++++++------- clang/unittests/Format/FormatTest.cpp | 3 ++- clang/unittests/Format/FormatTestJS.cpp | 14 ++++++++------ 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index cb3dee9d75c23c..1791d0fbfe8b85 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -918,7 +918,7 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // In "AlwaysBreak" or "BlockIndent" mode, enforce wrapping directly after the // parenthesis by disallowing any further line breaks if there is no line // break after the opening parenthesis. Don't break if it doesn't conserve - // columns. + // columns, unless the style option applies and a break is allowed. auto IsOpeningBracket = [&](const FormatToken &Tok) { auto IsStartOfBracedList = [&]() { return Tok.is(tok::l_brace) && Tok.isNot(BK_Block) && @@ -996,7 +996,13 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next); }; if (IsOpeningBracket(Previous) && - State.Column > getNewLineColumn(State).Total && + (State.Column > getNewLineColumn(State).Total || + // IsOpeningBracket checks BreakAfterOpenBracketBracedList before its + // (!Tok.Previous) shortcut. All other true returns with a preceding + // token require a BreakAfterOpenBracket* option. + // Only forbid later breaks if a break here is possible to prevent + // alternatives from being blocked. + ((Previous.Previous || Previous.is(tok::l_brace)) && canBreak(State))) && // Don't do this for simple (no expressions) one-argument function calls // as that feels like needlessly wasting whitespace, e.g.: // diff --git a/clang/unittests/Format/AlignBracketsTest.cpp b/clang/unittests/Format/AlignBracketsTest.cpp index 171872d6740774..fe47ccae86c9f1 100644 --- a/clang/unittests/Format/AlignBracketsTest.cpp +++ b/clang/unittests/Format/AlignBracketsTest.cpp @@ -867,7 +867,8 @@ TEST_F(AlignBracketsTest, BreakAfterOpenBracketIfStatement) { Style.BreakAfterOpenBracketIf = true; verifyFormat("void f() {\n" - " if (call(aaaaaaaaaaaaaaaaaaaa,\n" + " if (\n" + " call(aaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbb,\n" " cccccccccccccccccccc) < 0)\n" " return;\n" @@ -885,9 +886,10 @@ TEST_F(AlignBracketsTest, BreakAfterOpenBracketFunctionCall) { Style.BreakAfterOpenBracketFunction = true; verifyFormat("void f() {\n" - " g(aaaaaaaaaaaaaaaaaaaa,\n" - " bbbbbbbbbbbbbbbbbbbb,\n" - " cccccccccccccccccccc);\n" + " g(\n" + " aaaaaaaaaaaaaaaaaaaa,\n" + " bbbbbbbbbbbbbbbbbbbb,\n" + " cccccccccccccccccccc);\n" "}", "void f() {\n" " g(aaaaaaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbbbbbb, " @@ -903,7 +905,8 @@ TEST_F(AlignBracketsTest, BreakAfterOpenBracketLoopStatement) { Style.BreakAfterOpenBracketLoop = true; verifyFormat("void f() {\n" - " while (call(aaaaaaaaaaaaaaaaaaaa,\n" + " while (\n" + " call(aaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbb,\n" " cccccccccccccccccccc) < 0)\n" " return;\n" @@ -922,7 +925,8 @@ TEST_F(AlignBracketsTest, BreakAfterOpenBracketSwitchStatement) { Style.BreakAfterOpenBracketSwitch = true; verifyFormat("void f() {\n" - " switch (call(aaaaaaaaaaaaaaaaaaaa,\n" + " switch (\n" + " call(aaaaaaaaaaaaaaaaaaaa,\n" " bbbbbbbbbbbbbbbbbbbb,\n" " cccccccccccccccccccc)) {\n" " default:\n" @@ -942,7 +946,8 @@ TEST_F(AlignBracketsTest, BreakAfterOpenBracketBracedList) { Style.BreakAfterOpenBracketBracedList = true; verifyFormat("void f() {\n" - " int a[] = {111111111111111111, 222222222222222222, " + " int a[] = {\n" + " 111111111111111111, 222222222222222222, " "333333333333333333,\n" " 444444444444444444};\n" "}", diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 0a5950c25c60ef..09bebd446da0c8 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -21724,7 +21724,8 @@ TEST_F(FormatTest, FormatsLambdas) { Style.BraceWrapping.BeforeLambdaBody = true; verifyFormat("void foo() {\n" " aFunction(\n" - " 1, b(c(foo, Bar{}, baz, [](d) -> Foo\n" + " 1, b(c(\n" + " foo, Bar{}, baz, [](d) -> Foo\n" " {\n" " auto f = e(\n" " [&]\n" diff --git a/clang/unittests/Format/FormatTestJS.cpp b/clang/unittests/Format/FormatTestJS.cpp index b405a73bce0860..710f8d3682ad8a 100644 --- a/clang/unittests/Format/FormatTestJS.cpp +++ b/clang/unittests/Format/FormatTestJS.cpp @@ -238,7 +238,8 @@ TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) { verifyFormat("aaaaaaa ===\n b;", getGoogleJSStyleWithColumns(10)); verifyFormat("a !== b;"); verifyFormat("aaaaaaa !==\n b;", getGoogleJSStyleWithColumns(10)); - verifyFormat("if (a + b + c +\n" + verifyFormat("if (\n" + " a + b + c +\n" " d !==\n" " e + f + g)\n" " q();", @@ -250,7 +251,8 @@ TEST_F(FormatTestJS, UnderstandsJavaScriptOperators) { verifyFormat("aaaaaaa >>>\n b;", getGoogleJSStyleWithColumns(10)); verifyFormat("a >>>= b;"); verifyFormat("aaaaaaa >>>=\n b;", getGoogleJSStyleWithColumns(10)); - verifyFormat("if (a + b + c +\n" + verifyFormat("if (\n" + " a + b + c +\n" " d >>>\n" " e + f + g)\n" " q();", @@ -1273,10 +1275,10 @@ TEST_F(FormatTestJS, ArrowFunctions) { verifyFormat("var x = (a) => a;"); verifyFormat("return () => [];"); verifyFormat("var aaaaaaaaaaaaaaaaaaaa = {\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaa:\n" - " (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n" - " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaa: (\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) =>\n" + " aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n" "};"); verifyFormat("var a = a.aaaaaaa(\n" " (a: a) => aaaaaaaaaaaaaaaaaaaaaaaaa(bbbbbbbbb) &&\n" >From f3e28468fbb4ee296f3ea31a16726a6908c76f2b Mon Sep 17 00:00:00 2001 From: Chrislee02 <[email protected]> Date: Sat, 3 Oct 2026 21:27:28 +0900 Subject: [PATCH 3/3] [clang-format] Clarify BreakAfterOpenBracket option matching --- clang/lib/Format/ContinuationIndenter.cpp | 25 +++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index 1791d0fbfe8b85..f64c3b3907b71e 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -942,6 +942,26 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, } return false; }; + + auto ShouldBreakAfterOpeningBracket = [&](const FormatToken &Tok) { + // Suppose that IsOpeningBracket returned true for a Tok + + // Corresponds to BreakAfterOpenBracketBracedList + if (Tok.is(tok::l_brace)) + return true; + + const auto *Before = Tok.Previous; + if (!Before) + return false; + + // Corresponds to BreakAfterOpenBracketIf, BreakAfterOpenBracketLoop, + // BreakAfterOpenBracketSwitch, BreakAfterOpenBracketFunction. + return Before->isIf() || Before->isLoop(Style) || + Before->is(tok::kw_switch) || + (!Before->is(TT_CastRParen) && + !(Style.isJavaScript() && Tok.is(Keywords.kw_await))); + }; + auto IsFunctionCallParen = [](const FormatToken &Tok) { return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && Tok.Previous->is(tok::identifier); @@ -997,12 +1017,9 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, }; if (IsOpeningBracket(Previous) && (State.Column > getNewLineColumn(State).Total || - // IsOpeningBracket checks BreakAfterOpenBracketBracedList before its - // (!Tok.Previous) shortcut. All other true returns with a preceding - // token require a BreakAfterOpenBracket* option. // Only forbid later breaks if a break here is possible to prevent // alternatives from being blocked. - ((Previous.Previous || Previous.is(tok::l_brace)) && canBreak(State))) && + (ShouldBreakAfterOpeningBracket(Previous) && canBreak(State))) && // Don't do this for simple (no expressions) one-argument function calls // as that feels like needlessly wasting whitespace, e.g.: // _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
