Fix layout of blocks inside statements.
Previously, we would not indent:
SOME_MACRO({
int i;
});
correctly. This is fixed by adding the trailing }); to the unwrapped
line starting with SOME_MACRO({, so the formatter can correctly match
the braces and indent accordingly.
Also fixes incorrect parsing of initializer lists, like:
int a[] = { 1 };
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172058 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Format/UnwrappedLineParser.cpp b/lib/Format/UnwrappedLineParser.cpp
index c09ee31..736178e 100644
--- a/lib/Format/UnwrappedLineParser.cpp
+++ b/lib/Format/UnwrappedLineParser.cpp
@@ -76,6 +76,40 @@
FormatToken Token;
};
+class ScopedLineState {
+public:
+ ScopedLineState(UnwrappedLineParser &Parser) : Parser(Parser) {
+ PreBlockLine = Parser.Line.take();
+ Parser.Line.reset(new UnwrappedLine(*PreBlockLine));
+ assert(Parser.LastInCurrentLine == NULL ||
+ Parser.LastInCurrentLine->Children.empty());
+ PreBlockLastToken = Parser.LastInCurrentLine;
+ PreBlockRootTokenInitialized = Parser.RootTokenInitialized;
+ Parser.RootTokenInitialized = false;
+ Parser.LastInCurrentLine = NULL;
+ }
+
+ ~ScopedLineState() {
+ if (Parser.RootTokenInitialized) {
+ Parser.addUnwrappedLine();
+ }
+ assert(!Parser.RootTokenInitialized);
+ Parser.Line.reset(PreBlockLine);
+ Parser.RootTokenInitialized = PreBlockRootTokenInitialized;
+ Parser.LastInCurrentLine = PreBlockLastToken;
+ assert(Parser.LastInCurrentLine == NULL ||
+ Parser.LastInCurrentLine->Children.empty());
+ Parser.MustBreakBeforeNextToken = true;
+ }
+
+private:
+ UnwrappedLineParser &Parser;
+
+ UnwrappedLine *PreBlockLine;
+ FormatToken* PreBlockLastToken;
+ bool PreBlockRootTokenInitialized;
+};
+
UnwrappedLineParser::UnwrappedLineParser(const FormatStyle &Style,
FormatTokenSource &Tokens,
UnwrappedLineConsumer &Callback)
@@ -204,6 +238,7 @@
}
void UnwrappedLineParser::parseStructuralElement() {
+ assert(!FormatTok.Tok.is(tok::l_brace));
parseComments();
int TokenNumber = 0;
@@ -289,6 +324,10 @@
parseParens();
break;
case tok::l_brace:
+ // A block outside of parentheses must be the last part of a
+ // structural element.
+ // FIXME: Figure out cases where this is not true, and add projections for
+ // them (the one we know is missing are lambdas).
parseBlock();
addUnwrappedLine();
return;
@@ -301,9 +340,9 @@
break;
case tok::equal:
nextToken();
- // Skip initializers as they will be formatted by a later step.
- if (FormatTok.Tok.is(tok::l_brace))
- nextToken();
+ if (FormatTok.Tok.is(tok::l_brace)) {
+ parseBracedList();
+ }
break;
default:
nextToken();
@@ -312,6 +351,24 @@
} while (!eof());
}
+void UnwrappedLineParser::parseBracedList() {
+ nextToken();
+
+ do {
+ switch (FormatTok.Tok.getKind()) {
+ case tok::l_brace:
+ parseBracedList();
+ break;
+ case tok::r_brace:
+ nextToken();
+ return;
+ default:
+ nextToken();
+ break;
+ }
+ } while (!eof());
+}
+
void UnwrappedLineParser::parseParens() {
assert(FormatTok.Tok.is(tok::l_paren) && "'(' expected.");
nextToken();
@@ -323,6 +380,15 @@
case tok::r_paren:
nextToken();
return;
+ case tok::l_brace:
+ {
+ nextToken();
+ ScopedLineState LineState(*this);
+ Line->Level += 1;
+ parseLevel(/*HasOpeningBrace=*/true);
+ Line->Level -= 1;
+ }
+ break;
default:
nextToken();
break;
@@ -626,22 +692,8 @@
while (!Line->InPPDirective && FormatTok.Tok.is(tok::hash) &&
((FormatTok.NewlinesBefore > 0 && FormatTok.HasUnescapedNewline) ||
FormatTok.IsFirst)) {
- UnwrappedLine* StoredLine = Line.take();
- Line.reset(new UnwrappedLine(*StoredLine));
- assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
- FormatToken *StoredLastInCurrentLine = LastInCurrentLine;
- bool PreviousInitialized = RootTokenInitialized;
- RootTokenInitialized = false;
- LastInCurrentLine = NULL;
-
+ ScopedLineState BlockState(*this);
parsePPDirective();
-
- assert(!RootTokenInitialized);
- Line.reset(StoredLine);
- RootTokenInitialized = PreviousInitialized;
- LastInCurrentLine = StoredLastInCurrentLine;
- assert(LastInCurrentLine == NULL || LastInCurrentLine->Children.empty());
- MustBreakBeforeNextToken = true;
}
}