Fix layout of lambda captures.

Before:
 int c = [ &, &a, a]{
   [ =, c, &d]{
     return b++;
   }();
 }();

After:
 int c = [&, &a, a] {
   [=, c, &d] {
     return b++;
   }();
 }();

llvm-svn: 189924
This commit is contained in:
Manuel Klimek 2013-09-04 08:20:47 +00:00
parent 5b2000e4d9
commit bab25fdfa5
3 changed files with 29 additions and 21 deletions

View File

@ -624,7 +624,9 @@ private:
Current.Type = determineIncrementUsage(Current); Current.Type = determineIncrementUsage(Current);
} else if (Current.is(tok::exclaim)) { } else if (Current.is(tok::exclaim)) {
Current.Type = TT_UnaryOperator; Current.Type = TT_UnaryOperator;
} else if (Current.isBinaryOperator()) { } else if (Current.isBinaryOperator() &&
(!Current.Previous ||
Current.Previous->isNot(tok::l_square))) {
Current.Type = TT_BinaryOperator; Current.Type = TT_BinaryOperator;
} else if (Current.is(tok::comment)) { } else if (Current.is(tok::comment)) {
if (Current.TokenText.startswith("//")) if (Current.TokenText.startswith("//"))
@ -1188,6 +1190,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return false; return false;
if (Right.is(tok::ellipsis)) if (Right.is(tok::ellipsis))
return false; return false;
if (Left.is(tok::l_square) && Right.is(tok::amp))
return false;
if (Right.Type == TT_PointerOrReference) if (Right.Type == TT_PointerOrReference)
return Left.Tok.isLiteral() || return Left.Tok.isLiteral() ||
((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) && ((Left.Type != TT_PointerOrReference) && Left.isNot(tok::l_paren) &&
@ -1236,7 +1240,8 @@ bool TokenAnnotator::spaceRequiredBetween(const AnnotatedLine &Line,
return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) && return !Left.isOneOf(tok::l_paren, tok::l_square, tok::at) &&
(Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr); (Left.isNot(tok::colon) || Left.Type != TT_ObjCMethodExpr);
if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) && if (Left.isOneOf(tok::identifier, tok::greater, tok::r_square) &&
Right.is(tok::l_brace) && Right.getNextNonComment()) Right.is(tok::l_brace) && Right.getNextNonComment() &&
Right.BlockKind != BK_Block)
return false; return false;
if (Left.is(tok::period) || Right.is(tok::period)) if (Left.is(tok::period) || Right.is(tok::period))
return false; return false;

View File

@ -278,13 +278,11 @@ void UnwrappedLineParser::calculateBraceTypes() {
if (!LBraceStack.empty()) { if (!LBraceStack.empty()) {
if (LBraceStack.back()->BlockKind == BK_Unknown) { if (LBraceStack.back()->BlockKind == BK_Unknown) {
// If there is a comma, semicolon or right paren after the closing // If there is a comma, semicolon or right paren after the closing
// brace, we assume this is a braced initializer list. // brace, we assume this is a braced initializer list. Note that
// regardless how we mark inner braces here, we will overwrite the
// FIXME: Note that this currently works only because we do not // BlockKind later if we parse a braced list (where all blocks inside
// use the brace information while inside a braced init list. // are by default braced lists), or when we explicitly detect blocks
// Thus, if the parent is a braced init list, we consider all // (for example while parsing lambdas).
// brace blocks inside it braced init list. That works good enough
// for now, but we will need to fix it to correctly handle lambdas.
// //
// We exclude + and - as they can be ObjC visibility modifiers. // We exclude + and - as they can be ObjC visibility modifiers.
if (NextTok->isOneOf(tok::comma, tok::semi, tok::r_paren, if (NextTok->isOneOf(tok::comma, tok::semi, tok::r_paren,
@ -315,12 +313,13 @@ void UnwrappedLineParser::calculateBraceTypes() {
} }
Tok = NextTok; Tok = NextTok;
Position += ReadTokens; Position += ReadTokens;
} while (Tok->Tok.isNot(tok::eof)); } while (Tok->Tok.isNot(tok::eof) && !LBraceStack.empty());
// Assume other blocks for all unclosed opening braces. // Assume other blocks for all unclosed opening braces.
for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) { for (unsigned i = 0, e = LBraceStack.size(); i != e; ++i) {
if (LBraceStack[i]->BlockKind == BK_Unknown) if (LBraceStack[i]->BlockKind == BK_Unknown)
LBraceStack[i]->BlockKind = BK_Block; LBraceStack[i]->BlockKind = BK_Block;
} }
FormatTok = Tokens->setPosition(StoredPosition); FormatTok = Tokens->setPosition(StoredPosition);
} }
@ -675,6 +674,7 @@ void UnwrappedLineParser::tryToParseLambda() {
break; break;
} }
} }
FormatTok->BlockKind = BK_Block;
nextToken(); nextToken();
{ {
ScopedLineState LineState(*this); ScopedLineState LineState(*this);
@ -745,6 +745,9 @@ void UnwrappedLineParser::parseBracedList() {
tryToParseLambda(); tryToParseLambda();
break; break;
case tok::l_brace: case tok::l_brace:
// Assume there are no blocks inside a braced init list apart
// from the ones we explicitly parse out (like lambdas).
FormatTok->BlockKind = BK_BracedInit;
parseBracedList(); parseBracedList();
break; break;
case tok::r_brace: case tok::r_brace:

View File

@ -6262,37 +6262,37 @@ TEST_F(FormatTest, FormatsLambdas) {
// parsing of the unwrapped lines doesn't regress. // parsing of the unwrapped lines doesn't regress.
verifyFormat( verifyFormat(
"int c = [b]() mutable {\n" "int c = [b]() mutable {\n"
" return [&b]{\n" " return [&b] {\n"
" return b++;\n" " return b++;\n"
" }();\n" " }();\n"
"}();\n"); "}();\n");
verifyFormat( verifyFormat(
"int c = [&]{\n" "int c = [&] {\n"
" [ = ]{\n" " [=] {\n"
" return b++;\n" " return b++;\n"
" }();\n" " }();\n"
"}();\n"); "}();\n");
verifyFormat( verifyFormat(
"int c = [ &, &a, a]{\n" "int c = [&, &a, a] {\n"
" [ =, c, &d]{\n" " [=, c, &d] {\n"
" return b++;\n" " return b++;\n"
" }();\n" " }();\n"
"}();\n"); "}();\n");
verifyFormat( verifyFormat(
"int c = [&a, &a, a]{\n" "int c = [&a, &a, a] {\n"
" [ =, a, b, &c]{\n" " [=, a, b, &c] {\n"
" return b++;\n" " return b++;\n"
" }();\n" " }();\n"
"}();\n"); "}();\n");
verifyFormat( verifyFormat(
"auto c = {[&a, &a, a]{\n" "auto c = {[&a, &a, a] {\n"
" [ =, a, b, &c]{\n" " [=, a, b, &c] {\n"
" return b++;\n" " return b++;\n"
" }();\n" " }();\n"
"} }\n"); "} }\n");
verifyFormat( verifyFormat(
"auto c = {[&a, &a, a]{\n" "auto c = {[&a, &a, a] {\n"
" [ =, a, b, &c]{\n" " [=, a, b, &c] {\n"
" }();\n" " }();\n"
"} }\n"); "} }\n");
} }