Skip to content

Commit

Permalink
[clang-format] Make some binary operations imply requires clause
Browse files Browse the repository at this point in the history
This patch adjusts the requires clause/expression lookahead heuristic to
assume that some binary operation mean that the requires keyword refers
to a clause.

This partially reverts the removed case clauses from
9b68c09, with an additional check that
we're not in a type parameter.

This is quite a band-aid fix, it may be worth it to rewrite that whole
heuristic to track more state in the future, instead of just blindly
marching forward across multiple unrelated definitions, since right now,
the definition following the one with the requires clause can influence
whether the heuristic chooses clause or expression.

Fixes #110485
  • Loading branch information
rymiel committed Oct 3, 2024
1 parent 6c7a3f8 commit ef604d0
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
11 changes: 11 additions & 0 deletions clang/lib/Format/UnwrappedLineParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3528,6 +3528,17 @@ bool UnwrappedLineParser::parseRequires() {
return false;
}
break;
case tok::equalequal:
case tok::greaterequal:
case tok::lessequal:
case tok::r_paren:
case tok::pipepipe:
if (OpenAngles == 0) {
FormatTok = Tokens->setPosition(StoredPosition);
parseRequiresClause(RequiresToken);
return true;
}
break;
case tok::eof:
// Break out of the loop.
Lookahead = 50;
Expand Down
15 changes: 15 additions & 0 deletions clang/unittests/Format/TokenAnnotatorTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1296,6 +1296,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
Tokens = annotate("bool x = t && requires(Foo<C1 || C2> x) { x.foo(); };");
ASSERT_EQ(Tokens.size(), 25u) << Tokens;
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression);

// Second function definition is required due to lookahead
Tokens = annotate("void f() & requires(n == 1) {}\nvoid g();");
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);

Tokens = annotate("void f() & requires(n || h) {}\nvoid g();");
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);

Tokens = annotate("bool x = t && requires(F<n == 1> x) { x.foo(); };");
ASSERT_EQ(Tokens.size(), 25u) << Tokens;
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression);
}

TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {
Expand Down

0 comments on commit ef604d0

Please sign in to comment.