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->isNot(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)); 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"