Author: Emilia Dreamer Date: 2022-09-06T12:24:19+02:00 New Revision: 247613548bac55b47eed88e83d5c8640fd4b200a
URL: https://github.com/llvm/llvm-project/commit/247613548bac55b47eed88e83d5c8640fd4b200a DIFF: https://github.com/llvm/llvm-project/commit/247613548bac55b47eed88e83d5c8640fd4b200a.diff LOG: [clang-format] Change heuristic for locating lambda template arguments Previously, the heuristic was simply to look for template argument- specific keywords, such as typename, class, template and auto that are preceded by a left angle bracket <. This changes the heuristic to instead look for a left angle bracket < preceded by a right square bracket ], since according to the C++ grammar, the template arguments must *directly* follow the introducer. (This sort of check might just end up being *too* aggressive) This patch also adds a bunch more token annotator tests for lambdas, specifically for some of the stranger forms of lambdas now allowed as of C++20 or soon-to-be-allowed as part of C++23. Fixes https://github.com/llvm/llvm-project/issues/57093 This does NOT resolve the FIXME regarding explicit template lists, but perhaps it gets closer Differential Revision: https://reviews.llvm.org/D132295 Added: Modified: clang/lib/Format/UnwrappedLineParser.cpp clang/unittests/Format/FormatTest.cpp clang/unittests/Format/TokenAnnotatorTest.cpp Removed: ################################################################################ diff --git a/clang/lib/Format/UnwrappedLineParser.cpp b/clang/lib/Format/UnwrappedLineParser.cpp index 02b13be0d92e4..7ef1e82d754fe 100644 --- a/clang/lib/Format/UnwrappedLineParser.cpp +++ b/clang/lib/Format/UnwrappedLineParser.cpp @@ -2210,21 +2210,21 @@ bool UnwrappedLineParser::tryToParseLambda() { case tok::l_square: parseSquare(); break; - case tok::kw_auto: - case tok::kw_class: - case tok::kw_template: - case tok::kw_typename: + case tok::less: assert(FormatTok->Previous); - if (FormatTok->Previous->is(tok::less)) + if (FormatTok->Previous->is(tok::r_square)) InTemplateParameterList = true; nextToken(); break; + case tok::kw_auto: + case tok::kw_class: + case tok::kw_template: + case tok::kw_typename: case tok::amp: case tok::star: case tok::kw_const: case tok::kw_constexpr: case tok::comma: - case tok::less: case tok::greater: case tok::identifier: case tok::numeric_constant: diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp index 88c16884d0d89..d3e657b018b77 100644 --- a/clang/unittests/Format/FormatTest.cpp +++ b/clang/unittests/Format/FormatTest.cpp @@ -21730,6 +21730,18 @@ TEST_F(FormatTest, FormatsLambdas) { " g();\n" " }\n" "};\n"); + verifyFormat("auto L = []<int... T>(T...) {\n" + " {\n" + " f();\n" + " g();\n" + " }\n" + "};"); + verifyFormat("auto L = []<Foo... T>(T...) {\n" + " {\n" + " f();\n" + " g();\n" + " }\n" + "};"); // Multiple lambdas in the same parentheses change indentation rules. These // lambdas are forced to start on new lines. diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp index a839fb29115f9..a92d44be34f02 100644 --- a/clang/unittests/Format/TokenAnnotatorTest.cpp +++ b/clang/unittests/Format/TokenAnnotatorTest.cpp @@ -809,18 +809,85 @@ TEST_F(TokenAnnotatorTest, UnderstandsLambdas) { Tokens = annotate("[]() -> auto {}"); ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); EXPECT_TOKEN(Tokens[4], tok::arrow, TT_LambdaArrow); 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[4], tok::arrow, TT_LambdaArrow); 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[4], tok::arrow, TT_LambdaArrow); EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] {}"); + ASSERT_EQ(Tokens.size(), 5u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] noexcept {}"); + ASSERT_EQ(Tokens.size(), 6u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[3], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] -> auto {}"); + ASSERT_EQ(Tokens.size(), 7u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::arrow, TT_LambdaArrow); + EXPECT_TOKEN(Tokens[4], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <typename T> () {}"); + 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[8], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <typename T> {}"); + ASSERT_EQ(Tokens.size(), 9u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[6], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <typename... T> () {}"); + 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[9], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <typename... T> {}"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <int... T> () {}"); + 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[9], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <int... T> {}"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <Foo... T> () {}"); + 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[9], tok::l_brace, TT_LambdaLBrace); + + Tokens = annotate("[] <Foo... T> {}"); + ASSERT_EQ(Tokens.size(), 10u) << Tokens; + EXPECT_TOKEN(Tokens[0], tok::l_square, TT_LambdaLSquare); + EXPECT_TOKEN(Tokens[2], tok::less, TT_TemplateOpener); + EXPECT_TOKEN(Tokens[7], tok::l_brace, TT_LambdaLBrace); } TEST_F(TokenAnnotatorTest, UnderstandsFunctionAnnotations) { _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits