[clang-format] Correctly format loops and `if` statements even if preceded with comments.

Fixes https://github.com/llvm/llvm-project/issues/53758.

Braces in loops and in `if` statements with leading (block) comments were formatted according to `BraceWrapping.AfterFunction` and not `AllowShortBlocksOnASingleLine`/`AllowShortLoopsOnASingleLine`/`AllowShortIfStatementsOnASingleLine`.

Previously, the code:
```
while (true) {
  f();
}
/*comment*/ while (true) {
  f();
}
```

was incorrectly formatted to:
```
while (true) {
  f();
}
/*comment*/ while (true) { f(); }
```

when using config:
```
BasedOnStyle: LLVM
BreakBeforeBraces: Custom
BraceWrapping:
  AfterFunction: false
AllowShortBlocksOnASingleLine: false
AllowShortLoopsOnASingleLine: false
```

and it was (correctly but by chance) formatted to:
```
while (true) {
  f();
}
/*comment*/ while (true) {
  f();
}
```

when using enabling brace wrapping after functions:
```
BasedOnStyle: LLVM
BreakBeforeBraces: Custom
BraceWrapping:
  AfterFunction: true
AllowShortBlocksOnASingleLine: false
AllowShortLoopsOnASingleLine: false
```

Reviewed By: MyDeveloperDay, HazardyKnusperkeks, owenpan

Differential Revision: https://reviews.llvm.org/D119649
This commit is contained in:
Marek Kurdej 2022-02-11 14:53:36 +01:00
parent 986afe8479
commit 9cb9445979
2 changed files with 42 additions and 3 deletions

View File

@ -319,6 +319,15 @@ private:
bool MergeShortFunctions = ShouldMergeShortFunctions();
const FormatToken *FirstNonComment = TheLine->First;
if (FirstNonComment->is(tok::comment)) {
FirstNonComment = FirstNonComment->getNextNonComment();
if (!FirstNonComment)
return 0;
}
// FIXME: There are probably cases where we should use FirstNonComment
// instead of TheLine->First.
if (Style.CompactNamespaces) {
if (auto nsToken = TheLine->First->getNamespaceToken()) {
int i = 0;
@ -358,9 +367,9 @@ private:
if (TheLine->Last->is(TT_FunctionLBrace) && TheLine->First != TheLine->Last)
return MergeShortFunctions ? tryMergeSimpleBlock(I, E, Limit) : 0;
// 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,
TT_ForEachMacro)) {
if (TheLine->Last->is(tok::l_brace) && FirstNonComment != TheLine->Last &&
FirstNonComment->isOneOf(tok::kw_if, tok::kw_while, tok::kw_for,
TT_ForEachMacro)) {
return Style.AllowShortBlocksOnASingleLine != FormatStyle::SBS_Never
? tryMergeSimpleBlock(I, E, Limit)
: 0;

View File

@ -1520,6 +1520,36 @@ TEST_F(FormatTest, FormatLoopsWithoutCompoundStatement) {
TEST_F(FormatTest, FormatShortBracedStatements) {
FormatStyle AllowSimpleBracedStatements = getLLVMStyle();
EXPECT_EQ(AllowSimpleBracedStatements.AllowShortBlocksOnASingleLine, false);
EXPECT_EQ(AllowSimpleBracedStatements.AllowShortIfStatementsOnASingleLine,
FormatStyle::SIS_Never);
EXPECT_EQ(AllowSimpleBracedStatements.AllowShortLoopsOnASingleLine, false);
EXPECT_EQ(AllowSimpleBracedStatements.BraceWrapping.AfterFunction, false);
verifyFormat("for (;;) {\n"
" f();\n"
"}");
verifyFormat("/*comment*/ for (;;) {\n"
" f();\n"
"}");
verifyFormat("BOOST_FOREACH (int v, vec) {\n"
" f();\n"
"}");
verifyFormat("/*comment*/ BOOST_FOREACH (int v, vec) {\n"
" f();\n"
"}");
verifyFormat("while (true) {\n"
" f();\n"
"}");
verifyFormat("/*comment*/ while (true) {\n"
" f();\n"
"}");
verifyFormat("if (true) {\n"
" f();\n"
"}");
verifyFormat("/*comment*/ if (true) {\n"
" f();\n"
"}");
AllowSimpleBracedStatements.IfMacros.push_back("MYIF");
// Where line-lengths matter, a 2-letter synonym that maintains line length.
// Not IF to avoid any confusion that IF is somehow special.