Skip to content

Commit

Permalink
[clang-format] Fix requires misannotation with comma (#65908)
Browse files Browse the repository at this point in the history
clang-format uses a heuristic to determine if a requires() is either a
requires clause or requires expression, based on what is in the
parentheses. Part of this heuristic assumed that a requires clause can
never contain a comma, however this is not the case if said comma is in
the template argument of a type.

This patch allows commas to appear in a requires clause if an angle
bracket `<` has been opened.

Fixes #65904
  • Loading branch information
rymiel committed Sep 27, 2023
1 parent 63544af commit 3e87829
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
9 changes: 6 additions & 3 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3362,9 +3362,12 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
case tok::kw_volatile:
case tok::kw_const:
case tok::comma:
FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
if (OpenAngles == 0) {
FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresExpression(RequiresToken);
return false;
}
break;
case tok::r_paren:
case tok::pipepipe:
FormatTok = Tokens->setPosition(StoredPosition);
Expand Down
18 changes: 18 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,16 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
ASSERT_EQ(Tokens.size(), 22u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::kw_requires, TT_RequiresClause);
EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_PointerOrReference);

Tokens = annotate("void f() & requires(true) {}");
EXPECT_EQ(Tokens.size(), 12u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);

Tokens = annotate("void f() & requires(C<true, true>) {}");
EXPECT_EQ(Tokens.size(), 17u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
}

TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {
Expand Down Expand Up @@ -1151,6 +1161,14 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {
EXPECT_TOKEN(Tokens[3], tok::kw_requires, TT_RequiresExpression);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_RequiresExpressionLParen);
EXPECT_TOKEN(Tokens[14], tok::l_brace, TT_RequiresExpressionLBrace);

Tokens = annotate("bool foo = requires(C<true, true> c) {\n"
" { c.foo(); }\n"
"};");
ASSERT_EQ(Tokens.size(), 25u) << Tokens;
EXPECT_TOKEN(Tokens[3], tok::kw_requires, TT_RequiresExpression);
EXPECT_TOKEN(Tokens[4], tok::l_paren, TT_RequiresExpressionLParen);
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_RequiresExpressionLBrace);
}

TEST_F(TokenAnnotatorTest, UnderstandsPragmaRegion) {
Expand Down

0 comments on commit 3e87829

Please sign in to comment.