Skip to content

Commit

Permalink
[clang-format] Allow default values for template parameters in lambda (
Browse files Browse the repository at this point in the history
…#69052)

Previously, upon encountering an equals sign while parsing a lambda in
the UnwrappedLineParser, it would fall through and fail. This caused any
lambda template with a default argument for a template parameter to be
annotated as an ArraySubscriptLSquare.

This patch allows equals signs in the UnwrappedLineParser if we're
currently in a template parameter list. This resolved a FIXME that was
in the lambda parsing function.

This patch seems deceptively easy, it's likely it doesn't solve the
FIXME entirely, or causes other issues (the FIXME itself mentions
something about Objective-C, which I cannot comment about). However this
patch is sufficient to fix the below issue.

Fixes #68913

---------

Co-authored-by: Owen Pan <owenpiano@gmail.com>
  • Loading branch information
rymiel and owenca committed Oct 16, 2023
1 parent 301a0db commit 5f4ed78
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 3 deletions.
8 changes: 5 additions & 3 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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: []<bool b = true && false>(U &&u){}
case tok::plus:
case tok::minus:
case tok::exclaim:
Expand Down Expand Up @@ -2268,6 +2265,11 @@ bool UnwrappedLineParser::tryToParseLambda() {
parseRequiresClause(RequiresToken);
break;
}
case tok::equal:
if (!InTemplateParameterList)
return true;
nextToken();
break;
default:
return true;
}
Expand Down
38 changes: 38 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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("[] <typename T = int> (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("[] <int I = 0> (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("[] <bool b = false> (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("[] <bool b = true && false> (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("[] <typename T = int> requires Foo<T> (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) {
Expand Down

0 comments on commit 5f4ed78

Please sign in to comment.