diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 82a812fc8bcc6..708b70489a114 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2226,9 +2226,6 @@ bool UnwrappedLineParser::tryToParseLambda() { // followed by an `a->b` expression, such as: // ([obj func:arg] + a->b) // Otherwise the code below would parse as a lambda. - // - // FIXME: This heuristic is incorrect for C++20 generic lambdas with - // explicit template lists: [](U &&u){} case tok::plus: case tok::minus: case tok::exclaim: @@ -2268,6 +2265,11 @@ bool UnwrappedLineParser::tryToParseLambda() { parseRequiresClause(RequiresToken); break; } + case tok::equal: + if (!InTemplateParameterList) + return true; + nextToken(); + break; default: return true; } diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index e5cc3ed3686b3..2d04694799669 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -1620,6 +1620,44 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { EXPECT_TOKEN(Tokens[15], tok::kw_requires, TT_RequiresClause); EXPECT_TRUE(Tokens[19]->ClosesRequiresClause); EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] (T t) {}"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + 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[12], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] (T t) {}"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + 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[12], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] (T t) {}"); + ASSERT_EQ(Tokens.size(), 15u) << Tokens; + 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[12], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] (T&& t) {}"); + 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[7], tok::ampamp, TT_BinaryOperator); + EXPECT_TOKEN(Tokens[9], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[12], tok::ampamp, TT_PointerOrReference); + EXPECT_TOKEN(Tokens[15], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] requires Foo (T t) {}"); + 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[7], tok::greater, TT_TemplateCloser); + EXPECT_TOKEN(Tokens[8], tok::kw_requires, TT_RequiresClause); + EXPECT_TOKEN(Tokens[17], tok::l_brace, TT_LambdaLBrace); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) {