Author: Gedare Bloom Date: 2024-07-24T19:47:11-07:00 New Revision: ccae7b461be339e717d02f99ac857cf0bc7d17fc
URL: https://github.com/llvm/llvm-project/commit/ccae7b461be339e717d02f99ac857cf0bc7d17fc DIFF: https://github.com/llvm/llvm-project/commit/ccae7b461be339e717d02f99ac857cf0bc7d17fc.diff LOG: [clang-format] Improve BlockIndent at ColumnLimit (#93140) Fixes #55731 The reported formatting problems were related to ignoring deep nesting of "simple" functions (causing #54808) and to allowing the trailing annotation to become separated from the closing parens, which allowed a break to occur between the closing parens and the trailing annotation. The fix for the nesting of "simple" functions is to detect them more carefully. "Simple" was defined in a comment as being a single non-expression argument. I tried to stay as close to the original intent of the implementation while fixing the various bad formatting reports. In the process of fixing these bugs, some latent bugs were discovered related to how JavaScript Template Strings are handled. Those are also fixed here. --------- Co-authored-by: Owen Pan <owenpi...@gmail.com> Added: Modified: clang/lib/Format/ContinuationIndenter.cpp clang/lib/Format/FormatToken.h clang/lib/Format/TokenAnnotator.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp index b07360425ca6e..df86a774ba0f4 100644 --- a/clang/lib/Format/ContinuationIndenter.cpp +++ b/clang/lib/Format/ContinuationIndenter.cpp @@ -803,6 +803,37 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, return !Tok.Previous->isOneOf(TT_CastRParen, tok::kw_for, tok::kw_while, tok::kw_switch); }; + auto IsFunctionCallParen = [](const FormatToken &Tok) { + return Tok.is(tok::l_paren) && Tok.ParameterCount > 0 && Tok.Previous && + Tok.Previous->is(tok::identifier); + }; + const auto IsInTemplateString = [this](const FormatToken &Tok) { + if (!Style.isJavaScript()) + return false; + for (const auto *Prev = &Tok; Prev; Prev = Prev->Previous) { + if (Prev->is(TT_TemplateString) && Prev->opensScope()) + return true; + if (Prev->is(TT_TemplateString) && Prev->closesScope()) + break; + } + return false; + }; + // Identifies simple (no expression) one-argument function calls. + const auto IsSimpleFunction = [&](const FormatToken &Tok) { + if (!Tok.FakeLParens.empty() && Tok.FakeLParens.back() > prec::Unknown) + return false; + const auto *Previous = Tok.Previous; + if (!Previous || (!Previous->isOneOf(TT_FunctionDeclarationLParen, + TT_LambdaDefinitionLParen) && + !IsFunctionCallParen(*Previous))) { + return true; + } + if (IsOpeningBracket(Tok) || IsInTemplateString(Tok)) + return true; + const auto *Next = Tok.Next; + return !Next || Next->isMemberAccess() || + Next->is(TT_FunctionDeclarationLParen) || IsFunctionCallParen(*Next); + }; if ((Style.AlignAfterOpenBracket == FormatStyle::BAS_AlwaysBreak || Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) && IsOpeningBracket(Previous) && State.Column > getNewLineColumn(State) && @@ -813,10 +844,10 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, // caaaaaaaaaaaall( // caaaaaaaaaaaall( // caaaaaaaaaaaaaaaaaaaaaaall(aaaaaaaaaaaaaa, aaaaaaaaa)))); - Current.FakeLParens.size() > 0 && - Current.FakeLParens.back() > prec::Unknown) { + !IsSimpleFunction(Current)) { CurrentState.NoLineBreak = true; } + if (Previous.is(TT_TemplateString) && Previous.opensScope()) CurrentState.NoLineBreak = true; @@ -831,7 +862,8 @@ void ContinuationIndenter::addTokenOnCurrentLine(LineState &State, bool DryRun, Previous.isNot(TT_TableGenDAGArgOpenerToBreak) && !(Current.MacroParent && Previous.MacroParent) && (Current.isNot(TT_LineComment) || - Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen))) { + Previous.isOneOf(BK_BracedInit, TT_VerilogMultiLineListLParen)) && + !IsInTemplateString(Current)) { CurrentState.Indent = State.Column + Spaces; CurrentState.IsAligned = true; } diff --git a/clang/lib/Format/FormatToken.h b/clang/lib/Format/FormatToken.h index cc45d5a8c5c1e..abcedb66b57cc 100644 --- a/clang/lib/Format/FormatToken.h +++ b/clang/lib/Format/FormatToken.h @@ -102,6 +102,7 @@ namespace format { TYPE(JsTypeColon) \ TYPE(JsTypeOperator) \ TYPE(JsTypeOptionalQuestion) \ + TYPE(LambdaDefinitionLParen) \ TYPE(LambdaLBrace) \ TYPE(LambdaLSquare) \ TYPE(LeadingJavaAnnotation) \ diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp index 5c11f3cb1a874..16ab18e1af959 100644 --- a/clang/lib/Format/TokenAnnotator.cpp +++ b/clang/lib/Format/TokenAnnotator.cpp @@ -62,6 +62,7 @@ static bool canBeObjCSelectorComponent(const FormatToken &Tok) { /// With `Left` being '(', check if we're at either `[...](` or /// `[...]<...>(`, where the [ opens a lambda capture list. +// FIXME: this doesn't cover attributes/constraints before the l_paren. static bool isLambdaParameterList(const FormatToken *Left) { // Skip <...> if present. if (Left->Previous && Left->Previous->is(tok::greater) && @@ -365,6 +366,7 @@ class AnnotatingParser { Contexts.back().IsExpression = false; } else if (isLambdaParameterList(&OpeningParen)) { // This is a parameter list of a lambda expression. + OpeningParen.setType(TT_LambdaDefinitionLParen); Contexts.back().IsExpression = false; } else if (OpeningParen.is(TT_RequiresExpressionLParen)) { Contexts.back().IsExpression = false; @@ -6196,6 +6198,12 @@ bool TokenAnnotator::canBreakBefore(const AnnotatedLine &Line, return !(Previous && (Previous->is(tok::kw_for) || Previous->isIf())); } + if (Left.isOneOf(tok::r_paren, TT_TrailingAnnotation) && + Right.is(TT_TrailingAnnotation) && + Style.AlignAfterOpenBracket == FormatStyle::BAS_BlockIndent) { + return false; + } + // Allow breaking after a trailing annotation, e.g. after a method // declaration. if (Left.is(TT_TrailingAnnotation)) { diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 39fcbab3447a7..d7f81813835fa 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -9338,6 +9338,31 @@ TEST_F(FormatTest, AlignsAfterOpenBracket) { " aaaaaaaaaaaaaaaa\n" ");", Style); + verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaaaaa(\n" + " const bool &aaaaaaaaa, const void *aaaaaaaaaa\n" + ") const {\n" + " return true;\n" + "}", + Style); + verifyFormat("bool aaaaaaaaaaaaaaaaaaaaaaaa(\n" + " const bool &aaaaaaaaaa, const void *aaaaaaaaaa\n" + ") const;", + Style); + verifyFormat("void aaaaaaaaa(\n" + " int aaaaaa, int bbbbbb, int cccccc, int dddddddddd\n" + ") const noexcept -> std::vector<of_very_long_type>;", + Style); + verifyFormat( + "x = aaaaaaaaaaaaaaa(\n" + " \"a aaaaaaa aaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaa aaaaaaaaaaaaa\"\n" + ");", + Style); + Style.ColumnLimit = 60; + verifyFormat("auto lambda =\n" + " [&b](\n" + " auto aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" + " ) {};", + Style); } TEST_F(FormatTest, ParenthesesAndOperandAlignment) { diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index 51810ad047a26..1f820d83c261a 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1645,38 +1645,45 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { auto Tokens = annotate("[]() constexpr {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() consteval {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() mutable {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() static {}"); ASSERT_EQ(Tokens.size(), 8u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[5], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto & {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[]() -> auto * {}"); ASSERT_EQ(Tokens.size(), 10u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); @@ -1705,6 +1712,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { Tokens = annotate("foo([&](u32 bar) __attribute__((attr)) -> void {});"); ASSERT_EQ(Tokens.size(), 22u) << Tokens; EXPECT_TOKEN(Tokens[2], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[5], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); @@ -1712,6 +1720,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 11u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[8], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <typename T> {}"); @@ -1724,6 +1733,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <typename... T> {}"); @@ -1736,6 +1746,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <int... T> {}"); @@ -1748,6 +1759,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 12u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[9], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <Foo... T> {}"); @@ -1761,6 +1773,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 18u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[14]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); @@ -1769,6 +1782,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 19u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[8], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[11], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[15]->ClosesRequiresClause); @@ -1778,6 +1792,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 23u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[19]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); @@ -1786,6 +1801,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { ASSERT_EQ(Tokens.size(), 20u) << Tokens; EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::arrow, TT_TrailingReturnArrow); EXPECT_TOKEN(Tokens[12], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[16]->ClosesRequiresClause); @@ -1797,6 +1813,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[10]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <typename T> requires Bar<T> (T &&t) {}"); @@ -1805,6 +1823,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[10]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_LambdaLBrace); @@ -1814,6 +1834,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[15]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[16], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <typename T> requires true (T&& t) {}"); @@ -1822,6 +1844,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[7]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_LambdaLBrace); @@ -1856,6 +1880,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[6], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[10]->ClosesRequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[11], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[15], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[19]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); @@ -1865,6 +1891,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <int I = 0> (T t) {}"); @@ -1872,6 +1899,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <bool b = false> (T t) {}"); @@ -1879,6 +1907,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::l_brace, TT_LambdaLBrace); Tokens = annotate("[] <bool b = true && false> (T&& t) {}"); @@ -1887,6 +1916,7 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::ampamp, TT_BinaryOperator); EXPECT_TOKEN(Tokens[9], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[10], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_PointerOrReference); EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); @@ -1896,6 +1926,8 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); EXPECT_TOKEN(Tokens[7], tok::greater, TT_TemplateCloser); EXPECT_TOKEN(Tokens[8], tok::kw_requires, TT_RequiresClause); + // FIXME: + // EXPECT_TOKEN(Tokens[13], tok::l_paren, TT_LambdaDefinitionLParen); EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits