[clang] 2476135 - [clang-format] Change heuristic for locating lambda template arguments
Björn Schäpers via cfe-commits
cfe-commits at lists.llvm.org
Tue Sep 6 03:24:43 PDT 2022
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) {
More information about the cfe-commits
mailing list