curdeius created this revision.

This fixes bug #19986 (https://bugs.llvm.org/show_bug.cgi?id=19986).
The code was incorrectly formatted to (mind additional spaces inside brackets) 
when lambda capture contained an initializer expression.
This patch does not handle all possible initializers, but the most common once.
To handle these resting cases, we'd have to parse the whole initializer 
expressions or handle lambda detection differently.

Before:

  int i = 100;
  auto f1 = [ i, value = 23 ]() { return i + value; };
  auto f2 = [ i, value{23} ]() { return i + value; };

After:

  int i = 100;
  auto f1 = [i, value = 23]() { return i + value; };
  auto f2 = [i, value{23}]() { return i + value; };


https://reviews.llvm.org/D37980

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

Index: unittests/Format/FormatTest.cpp
===================================================================
--- unittests/Format/FormatTest.cpp
+++ unittests/Format/FormatTest.cpp
@@ -1413,7 +1413,7 @@
   verifyFormat("typedef enum {} EmptyEnum;");
   verifyFormat("typedef enum { A, B, C } ShortEnum;");
   verifyFormat("typedef enum {\n"
-               "  ZERO = 0,\n"             
+               "  ZERO = 0,\n"
                "  ONE = 1,\n"
                "  TWO = 2,\n"
                "  THREE = 3\n"
@@ -1425,7 +1425,7 @@
   verifyFormat("typedef enum { A, B, C } ShortEnum;");
   verifyFormat("typedef enum\n"
                "{\n"
-               "  ZERO = 0,\n"             
+               "  ZERO = 0,\n"
                "  ONE = 1,\n"
                "  TWO = 2,\n"
                "  THREE = 3\n"
@@ -1574,8 +1574,8 @@
   Style.CompactNamespaces = true;
 
   verifyFormat("namespace A { namespace B {\n"
-			   "}} // namespace A::B",
-			   Style);
+               "}} // namespace A::B",
+               Style);
 
   EXPECT_EQ("namespace out { namespace in {\n"
             "}} // namespace out::in",
@@ -3428,22 +3428,22 @@
   verifyFormat(
       "SomeClass::Constructor() :\n"
       "    aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
-	  Style);
+      Style);
 
   verifyFormat(
       "SomeClass::Constructor() :\n"
       "    aaaaaaaaaaaaa(aaaaaaaaaaaaaa), aaaaaaaaaaaaa(aaaaaaaaaaaaaa),\n"
       "    aaaaaaaaaaaaa(aaaaaaaaaaaaaa) {}",
-	  Style);
+      Style);
   verifyFormat(
       "SomeClass::Constructor() :\n"
       "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
       "    aaaaaaaaaaaaaaa(aaaaaaaaaaaa) {}",
-	  Style);
+      Style);
   verifyFormat("Constructor(aaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
                "            aaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) :\n"
                "    aaaaaaaaaa(aaaaaa) {}",
-			   Style);
+               Style);
 
   verifyFormat("Constructor() :\n"
                "    aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
@@ -3450,17 +3450,17 @@
                "    aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaaaaa,\n"
                "                             aaaaaaaaaaaaaaaaaaaaaaaaaaa),\n"
                "    aaaaaaaaaaaaaaaaaaaaaaa() {}",
-			   Style);
+               Style);
 
   verifyFormat("Constructor() :\n"
                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
                "        aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}",
-			   Style);
+               Style);
 
   verifyFormat("Constructor(int Parameter = 0) :\n"
                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaa),\n"
                "    aaaaaaaaaaaa(aaaaaaaaaaaaaaaaa) {}",
-			   Style);
+               Style);
   verifyFormat("Constructor() :\n"
                "    aaaaaaaaaaaaaaaaaaaaaa(a), bbbbbbbbbbbbbbbbbbbbbbbb(b) {\n"
                "}",
@@ -3468,7 +3468,7 @@
   verifyFormat("Constructor() :\n"
                "    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa(\n"
                "        aaaaaaaaaaaaaaaaaaaaaaaaa(aaaa, aaaa)) {}",
-			   Style);
+               Style);
 
   // Here a line could be saved by splitting the second initializer onto two
   // lines, but that is not desirable.
@@ -3476,7 +3476,7 @@
                "    aaaaaaaaaaaaaaaaaaaaaaaa(aaaaaaaaaaaaaaaaaaaaaaaa),\n"
                "    aaaaaaaaaaa(aaaaaaaaaaa),\n"
                "    aaaaaaaaaaaaaaaaaaaaat(aaaaaaaaaaaaaaaaaaaaaaaaaaaa) {}",
-			   Style);
+               Style);
 
   FormatStyle OnePerLine = Style;
   OnePerLine.ConstructorInitializerAllOnOneLineOrOnePerLine = true;
@@ -3526,7 +3526,7 @@
             format("Constructor() :\n"
                    "    // Comment forcing unwanted break.\n"
                    "    aaaa(aaaa) {}",
-				   Style));
+                   Style));
 
   Style.ColumnLimit = 0;
   verifyFormat("SomeClass::Constructor() :\n"
@@ -3536,7 +3536,7 @@
                "    a(a) {}",
                Style);
   verifyFormat("SomeClass::Constructor() :\n"
-			   "    a(a), b(b), c(c) {}",
+               "    a(a), b(b), c(c) {}",
                Style);
   verifyFormat("SomeClass::Constructor() :\n"
                "    a(a) {\n"
@@ -3547,12 +3547,12 @@
 
   Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
   verifyFormat("SomeClass::Constructor() :\n"
-			   "    a(a), b(b), c(c) {\n"
-			   "}",
+               "    a(a), b(b), c(c) {\n"
+               "}",
                Style);
   verifyFormat("SomeClass::Constructor() :\n"
                "    a(a) {\n"
-			   "}",
+               "}",
                Style);
 
   Style.ColumnLimit = 80;
@@ -6519,7 +6519,7 @@
   // Binpacking only if there is no trailing comma
   verifyFormat("const Aaaaaa aaaaa = {aaaaaaaaaa, bbbbbbbbbb,\n"
                "                      cccccccccc, dddddddddd};",
-			   getLLVMStyleWithColumns(50));
+               getLLVMStyleWithColumns(50));
   verifyFormat("const Aaaaaa aaaaa = {\n"
                "    aaaaaaaaaaa,\n"
                "    bbbbbbbbbbb,\n"
@@ -10770,6 +10770,19 @@
   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 = [*this]() {};\n");
+  verifyFormat("auto c = [i, *this]() {};\n");
+  verifyFormat("auto c = [i, self = *this]() {};\n");
+  verifyFormat("auto c = [i, value = 123]() {};\n");
+  verifyFormat("auto c = [i, value = i]() {};\n");
+  verifyFormat("auto c = [i, ptr = &i]() {};\n");
+  verifyFormat("auto c = [i, &value = i]() {};\n");
+  verifyFormat("auto c = [i, value{i}]() {};\n");
+  verifyFormat("auto c = [i, ptr{&i}]() {};\n");
+  // TODO: Captures may be initialized with any valid initializer expression.
+  // verifyFormat("auto c = [i, ptr = &i + 10]() {};\n");
+
   verifyFormat("int x = f(*+[] {});");
   verifyFormat("void f() {\n"
                "  other(x.begin(), x.end(), [&](int, int) { return 1; });\n"
Index: lib/Format/UnwrappedLineParser.h
===================================================================
--- lib/Format/UnwrappedLineParser.h
+++ lib/Format/UnwrappedLineParser.h
@@ -120,6 +120,7 @@
   void parseJavaScriptEs6ImportExport();
   bool tryToParseLambda();
   bool tryToParseLambdaIntroducer();
+  bool tryToParseLambdaCaptureInitializer();
   void tryToParseJSFunction();
   void addUnwrappedLine();
   bool eof() const;
Index: lib/Format/UnwrappedLineParser.cpp
===================================================================
--- lib/Format/UnwrappedLineParser.cpp
+++ lib/Format/UnwrappedLineParser.cpp
@@ -1390,13 +1390,22 @@
     return true;
   }
   do {
-    if (FormatTok->is(tok::amp))
+    if (FormatTok->isOneOf(tok::amp, tok::star))
       nextToken();
     if (!FormatTok->isOneOf(tok::identifier, tok::kw_this))
       return false;
     nextToken();
-    if (FormatTok->is(tok::ellipsis))
+    if (FormatTok->is(tok::equal)) {
+      if (!tryToParseLambdaCaptureInitializer())
+        return false;
+    } else if (FormatTok->is(tok::l_brace)) {
+      if (!tryToParseLambdaCaptureInitializer())
+        return false;
+      if (!FormatTok->is(tok::r_brace))
+        return false;
       nextToken();
+    } else if (FormatTok->is(tok::ellipsis))
+      nextToken();
     if (FormatTok->is(tok::comma)) {
       nextToken();
     } else if (FormatTok->is(tok::r_square)) {
@@ -1409,6 +1418,19 @@
   return false;
 }
 
+bool UnwrappedLineParser::tryToParseLambdaCaptureInitializer() {
+  // Try to parse a simple initializer expression.
+  nextToken();
+  if (FormatTok->isOneOf(tok::amp, tok::star))
+    nextToken();
+  if (!FormatTok->isOneOf(tok::identifier, tok::kw_this,
+                          tok::numeric_constant)) {
+    return false;
+  }
+  nextToken();
+  return true;
+}
+
 void UnwrappedLineParser::tryToParseJSFunction() {
   assert(FormatTok->is(Keywords.kw_function) ||
          FormatTok->startsSequence(Keywords.kw_async, Keywords.kw_function));
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to