LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 48305 - clang-format mismatches braces with nested unnamed scopes
Summary: clang-format mismatches braces with nested unnamed scopes
Status: NEW
Alias: None
Product: clang
Classification: Unclassified
Component: Formatter (show other bugs)
Version: 11.0
Hardware: PC Linux
: P normal
Assignee: Unassigned Clang Bugs
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-11-25 12:29 PST by Mateusz Lewicki
Modified: 2021-11-23 04:56 PST (History)
6 users (show)

See Also:
Fixed By Commit(s):


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mateusz Lewicki 2020-11-25 12:29:44 PST
Hello.
With clang-format -10 and -11 installed from repo on ubuntu 20.11 following c++ code is obviously formatted wrong:
```
clang-format-11 -style=llvm test.cpp 
void foo() {
  {// asdf
   {int a;
}
}
{
  { int b; }
}
}
```
Removing `{// asdf` is sufficient to format it ok.
I expect it to be formatted like this (possibly with comment in new line, but this may be llvm style):
```
void foo() {
  {// asdf
    { int a; }
  }
  {
    { int b; }
  }
}

```
Comment 1 ensadc 2021-11-23 02:09:43 PST
It seems that clang-format erroneously treats `{{int a;` as a malformed initializer list. (The first brace in the repro is on a separate line only because it's followed by a single line comment.)

The problem appears to be caused by `UnwrappedLineParser`.

- [`UnwrappedLineParser::tryToParseBracedList`] calls `calculateBraceTypes` to see whether a left brace starts an initializer list or a block. If the left brace starts an initializer list, `parseBracedList` is called to consume it.
- [`UnwrappedLineParser::calculateBraceTypes`] thinks `{// asdf` starts an initializer list, because its matching right brace is followed by a left brace (which makes sense in a constructor, e.g. in `class Foo { int mem; Foo() : mem{} {};`, the `{}` after `mem` is an initializer list, but does not make sense otherwise).
- [`UnwrappedLineParser::parseBracedList`] consumes the initializer list and stops at the semicolon after `int a` (because it was called with `ContinueOnSemicolons` being the default, i.e. `false`). It is unaware that the left brace has a matching right brace.

[`UnwrappedLineParser::tryToParseBracedList`]: https://github.com/llvm/llvm-project/blob/8ea3e70fb02e59ddfd6a050344c7d177b11104f7/clang/lib/Format/UnwrappedLineParser.cpp#L1843
[`UnwrappedLineParser::calculateBraceTypes`]: https://github.com/llvm/llvm-project/blob/8ea3e70fb02e59ddfd6a050344c7d177b11104f7/clang/lib/Format/UnwrappedLineParser.cpp#L442
[`UnwrappedLineParser::parseBracedList`]: https://github.com/llvm/llvm-project/blob/8ea3e70fb02e59ddfd6a050344c7d177b11104f7/clang/lib/Format/UnwrappedLineParser.cpp#L1854