]> granicus.if.org Git - clang/commitdiff
Fix formatting of lambda introducers with initializers.
authorManuel Klimek <klimek@google.com>
Tue, 19 Sep 2017 09:59:30 +0000 (09:59 +0000)
committerManuel Klimek <klimek@google.com>
Tue, 19 Sep 2017 09:59:30 +0000 (09:59 +0000)
Most of the work was already done when we introduced a look-behind based
lambda introducer detection.

This patch finishes the transition by completely relying on the simple
lambda introducer detection and simply recursing into normal
brace-parsing code to parse until the end of the introducer.

This fixes initializers in lambdas, including nested lambdas.

Before:
  auto a = [b = [c = 42]{}]{};
  auto b = [c = &i + 23]{};

After:
  auto a = [b = [c = 42] {}] {};
  auto b = [c = &i + 23] {};

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@313622 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Format/UnwrappedLineParser.cpp
lib/Format/UnwrappedLineParser.h
unittests/Format/FormatTest.cpp

index 40d133ff0ddf307e7f59db439afdfde66af08f45..8722d80a3958f03d37e12c9ea58bd08c500d18bb 100644 (file)
@@ -1314,14 +1314,6 @@ bool UnwrappedLineParser::tryToParseLambda() {
     nextToken();
     return false;
   }
-  const FormatToken* Previous = getPreviousToken();
-  if (Previous &&
-      (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
-                         tok::kw_delete) ||
-       Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
-    nextToken();
-    return false;
-  }
   assert(FormatTok->is(tok::l_square));
   FormatToken &LSquare = *FormatTok;
   if (!tryToParseLambdaIntroducer())
@@ -1364,49 +1356,17 @@ bool UnwrappedLineParser::tryToParseLambda() {
 }
 
 bool UnwrappedLineParser::tryToParseLambdaIntroducer() {
-  nextToken();
-  if (FormatTok->is(tok::equal)) {
-    nextToken();
-    if (FormatTok->is(tok::r_square)) {
-      nextToken();
-      return true;
-    }
-    if (FormatTok->isNot(tok::comma))
-      return false;
-    nextToken();
-  } else if (FormatTok->is(tok::amp)) {
-    nextToken();
-    if (FormatTok->is(tok::r_square)) {
-      nextToken();
-      return true;
-    }
-    if (!FormatTok->isOneOf(tok::comma, tok::identifier)) {
-      return false;
-    }
-    if (FormatTok->is(tok::comma))
-      nextToken();
-  } else if (FormatTok->is(tok::r_square)) {
+  const FormatToken* Previous = getPreviousToken();
+  if (Previous &&
+      (Previous->isOneOf(tok::identifier, tok::kw_operator, tok::kw_new,
+                         tok::kw_delete) ||
+       Previous->closesScope() || Previous->isSimpleTypeSpecifier())) {
     nextToken();
-    return true;
+    return false;
   }
-  do {
-    if (FormatTok->is(tok::amp))
-      nextToken();
-    if (!FormatTok->isOneOf(tok::identifier, tok::kw_this))
-      return false;
-    nextToken();
-    if (FormatTok->is(tok::ellipsis))
-      nextToken();
-    if (FormatTok->is(tok::comma)) {
-      nextToken();
-    } else if (FormatTok->is(tok::r_square)) {
-      nextToken();
-      return true;
-    } else {
-      return false;
-    }
-  } while (!eof());
-  return false;
+  nextToken();
+  parseSquare(/*LambdaIntroducer=*/true);
+  return true;
 }
 
 void UnwrappedLineParser::tryToParseJSFunction() {
@@ -1608,10 +1568,12 @@ void UnwrappedLineParser::parseParens() {
   } while (!eof());
 }
 
-void UnwrappedLineParser::parseSquare() {
-  assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
-  if (tryToParseLambda())
-    return;
+void UnwrappedLineParser::parseSquare(bool LambdaIntroducer) {
+  if (!LambdaIntroducer) {
+    assert(FormatTok->Tok.is(tok::l_square) && "'[' expected.");
+    if (tryToParseLambda())
+      return;
+  }
   do {
     switch (FormatTok->Tok.getKind()) {
     case tok::l_paren:
index 2637b23e1e05abf981adf01c79363f0354077db5..93b3bfafbad72ce2dbc3ccf83e16c705bd57efd4 100644 (file)
@@ -96,7 +96,7 @@ private:
   bool parseBracedList(bool ContinueOnSemicolons = false,
                        tok::TokenKind ClosingBraceKind = tok::r_brace);
   void parseParens();
-  void parseSquare();
+  void parseSquare(bool LambdaIntroducer = false);
   void parseIfThenElse();
   void parseTryCatch();
   void parseForOrWhileLoop();
index e974550f2254b7b1ad5223f35469d4cbb1c4ae76..34206e9e4187567170e207e64dd829d1f57649e3 100644 (file)
@@ -10770,6 +10770,8 @@ TEST_F(FormatTest, FormatsLambdas) {
   verifyFormat("int c = [&a, &a, a] { [=, a, b, &c] { return b++; }(); }();\n");
   verifyFormat("auto c = {[&a, &a, a] { [=, a, b, &c] { return b++; }(); }}\n");
   verifyFormat("auto c = {[&a, &a, a] { [=, a, b, &c] {}(); }}\n");
+  verifyFormat("auto c = [a = [b = 42] {}] {};\n");
+  verifyFormat("auto c = [a = &i + 10, b = [] {}] {};\n");
   verifyFormat("int x = f(*+[] {});");
   verifyFormat("void f() {\n"
                "  other(x.begin(), x.end(), [&](int, int) { return 1; });\n"