diff --git a/clang/lib/Format/UnwrappedLineFormatter.cpp b/clang/lib/Format/UnwrappedLineFormatter.cpp --- a/clang/lib/Format/UnwrappedLineFormatter.cpp +++ b/clang/lib/Format/UnwrappedLineFormatter.cpp @@ -357,7 +357,8 @@ } // Try to merge a control statement block with left brace unwrapped if (TheLine->Last->is(tok::l_brace) && TheLine->First != TheLine->Last && - TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for)) { + TheLine->First->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for, + TT_ForEachMacro)) { return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never ? tryMergeSimpleBlock(I, E, Limit) : 0; @@ -380,7 +381,7 @@ : 0; } else if (I[1]->First->is(tok::l_brace) && TheLine->First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, - tok::kw_for)) { + tok::kw_for, TT_ForEachMacro)) { return (Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Always) ? tryMergeSimpleBlock(I, E, Limit) @@ -495,7 +496,8 @@ ? tryMergeSimpleControlStatement(I, E, Limit) : 0; } - if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do)) { + if (TheLine->First->isOneOf(tok::kw_for, tok::kw_while, tok::kw_do, + TT_ForEachMacro)) { return Style.AllowShortLoopsOnASingleLine ? tryMergeSimpleControlStatement(I, E, Limit) : 0; @@ -543,13 +545,14 @@ if (!Line.First->is(tok::kw_do) && !Line.First->is(tok::kw_else) && !Line.Last->is(tok::kw_else) && Line.Last->isNot(tok::r_paren)) return 0; - // Only merge do while if do is the only statement on the line. + // Only merge `do while` if `do` is the only statement on the line. if (Line.First->is(tok::kw_do) && !Line.Last->is(tok::kw_do)) return 0; if (1 + I[1]->Last->TotalLength > Limit) return 0; + // Don't merge with loops, ifs, a single semicolon or a line comment. if (I[1]->First->isOneOf(tok::semi, tok::kw_if, tok::kw_for, tok::kw_while, - TT_LineComment)) + TT_ForEachMacro, TT_LineComment)) return 0; // Only inline simple if's (no nested if or else), unless specified if (Style.AllowShortIfStatementsOnASingleLine == @@ -637,8 +640,8 @@ } if (Line.First->isOneOf(tok::kw_if, tok::kw_else, tok::kw_while, tok::kw_do, tok::kw_try, tok::kw___try, tok::kw_catch, - tok::kw___finally, tok::kw_for, tok::r_brace, - Keywords.kw___except)) { + tok::kw___finally, tok::kw_for, TT_ForEachMacro, + tok::r_brace, Keywords.kw___except)) { if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Never) return 0; if (Style.AllowShortBlocksOnASingleLine == FormatStyle::SBS_Empty && @@ -658,12 +661,14 @@ I + 2 != E && !I[2]->First->is(tok::r_brace)) return 0; if (!Style.AllowShortLoopsOnASingleLine && - Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) && + Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, + TT_ForEachMacro) && !Style.BraceWrapping.AfterControlStatement && !I[1]->First->is(tok::r_brace)) return 0; if (!Style.AllowShortLoopsOnASingleLine && - Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for) && + Line.First->isOneOf(tok::kw_while, tok::kw_do, tok::kw_for, + TT_ForEachMacro) && Style.BraceWrapping.AfterControlStatement == FormatStyle::BWACS_Always && I + 2 != E && !I[2]->First->is(tok::r_brace)) 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 @@ -1464,6 +1464,7 @@ verifyFormat("while (true) continue;", AllowsMergedLoops); verifyFormat("for (;;) continue;", AllowsMergedLoops); verifyFormat("for (int &v : vec) v *= 2;", AllowsMergedLoops); + verifyFormat("BOOST_FOREACH (int &v, vec) v *= 2;", AllowsMergedLoops); verifyFormat("while (true)\n" " ;", AllowsMergedLoops); @@ -1476,9 +1477,15 @@ verifyFormat("for (;;)\n" " while (true) continue;", AllowsMergedLoops); - verifyFormat("BOOST_FOREACH (int v, vec)\n" + verifyFormat("while (true)\n" + " for (;;) continue;", + AllowsMergedLoops); + verifyFormat("BOOST_FOREACH (int &v, vec)\n" " for (;;) continue;", AllowsMergedLoops); + verifyFormat("for (;;)\n" + " BOOST_FOREACH (int &v, vec) continue;", + AllowsMergedLoops); verifyFormat("for (;;) // Can't merge this\n" " continue;", AllowsMergedLoops); @@ -1645,6 +1652,11 @@ " f();\n" "}", AllowSimpleBracedStatements); + verifyFormat("BOOST_FOREACH (int v, vec) {}", AllowSimpleBracedStatements); + verifyFormat("BOOST_FOREACH (int v, vec) {\n" + " f();\n" + "}", + AllowSimpleBracedStatements); AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine = FormatStyle::SIS_WithoutElse; @@ -1775,6 +1787,12 @@ " f();\n" "}", AllowSimpleBracedStatements); + verifyFormat("BOOST_FOREACH (int v, vec) {}", AllowSimpleBracedStatements); + verifyFormat("BOOST_FOREACH (int v, vec)\n" + "{\n" + " f();\n" + "}", + AllowSimpleBracedStatements); } TEST_F(FormatTest, ShortBlocksInMacrosDontMergeWithCodeAfterMacro) { @@ -2159,20 +2177,89 @@ } TEST_F(FormatTest, ForEachLoops) { + FormatStyle Style = getLLVMStyle(); + EXPECT_EQ(Style.AllowShortBlocksOnASingleLine, FormatStyle::SBS_Never); + EXPECT_EQ(Style.AllowShortLoopsOnASingleLine, false); verifyFormat("void f() {\n" - " foreach (Item *item, itemlist) {}\n" - " Q_FOREACH (Item *item, itemlist) {}\n" - " BOOST_FOREACH (Item *item, itemlist) {}\n" + " for (;;) {\n" + " }\n" + " foreach (Item *item, itemlist) {\n" + " }\n" + " Q_FOREACH (Item *item, itemlist) {\n" + " }\n" + " BOOST_FOREACH (Item *item, itemlist) {\n" + " }\n" " UNKNOWN_FOREACH(Item * item, itemlist) {}\n" - "}"); + "}", + Style); + verifyFormat("void f() {\n" + " for (;;)\n" + " int j = 1;\n" + " Q_FOREACH (int v, vec)\n" + " v *= 2;\n" + " for (;;) {\n" + " int j = 1;\n" + " }\n" + " Q_FOREACH (int v, vec) {\n" + " v *= 2;\n" + " }\n" + "}", + Style); + + FormatStyle ShortBlocks = getLLVMStyle(); + ShortBlocks.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; + EXPECT_EQ(ShortBlocks.AllowShortLoopsOnASingleLine, false); + verifyFormat("void f() {\n" + " for (;;)\n" + " int j = 1;\n" + " Q_FOREACH (int &v, vec)\n" + " v *= 2;\n" + " for (;;) {\n" + " int j = 1;\n" + " }\n" + " Q_FOREACH (int &v, vec) {\n" + " int j = 1;\n" + " }\n" + "}", + ShortBlocks); + + FormatStyle ShortLoops = getLLVMStyle(); + ShortLoops.AllowShortLoopsOnASingleLine = true; + EXPECT_EQ(ShortLoops.AllowShortBlocksOnASingleLine, FormatStyle::SBS_Never); + verifyFormat("void f() {\n" + " for (;;) int j = 1;\n" + " Q_FOREACH (int &v, vec) int j = 1;\n" + " for (;;) {\n" + " int j = 1;\n" + " }\n" + " Q_FOREACH (int &v, vec) {\n" + " int j = 1;\n" + " }\n" + "}", + ShortLoops); + + FormatStyle ShortBlocksAndLoops = getLLVMStyle(); + ShortBlocksAndLoops.AllowShortBlocksOnASingleLine = FormatStyle::SBS_Always; + ShortBlocksAndLoops.AllowShortLoopsOnASingleLine = true; + verifyFormat("void f() {\n" + " for (;;) int j = 1;\n" + " Q_FOREACH (int &v, vec) int j = 1;\n" + " for (;;) { int j = 1; }\n" + " Q_FOREACH (int &v, vec) { int j = 1; }\n" + "}", + ShortBlocksAndLoops); - FormatStyle Style = getLLVMStyle(); Style.SpaceBeforeParens = FormatStyle::SBPO_ControlStatementsExceptControlMacros; verifyFormat("void f() {\n" - " foreach(Item *item, itemlist) {}\n" - " Q_FOREACH(Item *item, itemlist) {}\n" - " BOOST_FOREACH(Item *item, itemlist) {}\n" + " for (;;) {\n" + " }\n" + " foreach(Item *item, itemlist) {\n" + " }\n" + " Q_FOREACH(Item *item, itemlist) {\n" + " }\n" + " BOOST_FOREACH(Item *item, itemlist) {\n" + " }\n" " UNKNOWN_FOREACH(Item * item, itemlist) {}\n" "}", Style); @@ -14596,11 +14683,23 @@ verifyFormat("MYIF (a)\n return;\nelse\n return;", SpaceIfMacros); FormatStyle SpaceForeachMacros = getLLVMStyle(); + EXPECT_EQ(SpaceForeachMacros.AllowShortBlocksOnASingleLine, + FormatStyle::SBS_Never); + EXPECT_EQ(SpaceForeachMacros.AllowShortLoopsOnASingleLine, false); SpaceForeachMacros.SpaceBeforeParens = FormatStyle::SBPO_Custom; SpaceForeachMacros.SpaceBeforeParensOptions.AfterForeachMacros = true; - verifyFormat("foreach (Item *item, itemlist) {}", SpaceForeachMacros); - verifyFormat("Q_FOREACH (Item *item, itemlist) {}", SpaceForeachMacros); - verifyFormat("BOOST_FOREACH (Item *item, itemlist) {}", SpaceForeachMacros); + verifyFormat("for (;;) {\n" + "}", + SpaceForeachMacros); + verifyFormat("foreach (Item *item, itemlist) {\n" + "}", + SpaceForeachMacros); + verifyFormat("Q_FOREACH (Item *item, itemlist) {\n" + "}", + SpaceForeachMacros); + verifyFormat("BOOST_FOREACH (Item *item, itemlist) {\n" + "}", + SpaceForeachMacros); verifyFormat("UNKNOWN_FOREACH(Item *item, itemlist) {}", SpaceForeachMacros); FormatStyle SomeSpace2 = getLLVMStyle();