Skip to content

Commit 9b68c09

Browse files
authored
[clang-format] Allow decltype in requires clause (#78847)
If clang-format is not sure whether a `requires` keyword starts a requires clause or a requires expression, it looks ahead to see if any token disqualifies it from being a requires clause. Among these tokens was `decltype`, since it fell through the switch. This patch allows decltype to exist in a require clause. I'm not 100% sure this change won't have repercussions, but that just means we need more test coverage! Fixes #78645
1 parent b777bb7 commit 9b68c09

File tree

2 files changed

+23
-5
lines changed

2 files changed

+23
-5
lines changed

clang/lib/Format/UnwrappedLineParser.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3446,18 +3446,14 @@ bool clang::format::UnwrappedLineParser::parseRequires() {
34463446
return false;
34473447
}
34483448
break;
3449-
case tok::r_paren:
3450-
case tok::pipepipe:
3451-
FormatTok = Tokens->setPosition(StoredPosition);
3452-
parseRequiresClause(RequiresToken);
3453-
return true;
34543449
case tok::eof:
34553450
// Break out of the loop.
34563451
Lookahead = 50;
34573452
break;
34583453
case tok::coloncolon:
34593454
LastWasColonColon = true;
34603455
break;
3456+
case tok::kw_decltype:
34613457
case tok::identifier:
34623458
if (FoundType && !LastWasColonColon && OpenAngles == 0) {
34633459
FormatTok = Tokens->setPosition(StoredPosition);

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,28 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
10761076
"concept C = (!Foo<T>) && Bar;");
10771077
ASSERT_EQ(Tokens.size(), 19u) << Tokens;
10781078
EXPECT_TOKEN(Tokens[15], tok::ampamp, TT_BinaryOperator);
1079+
1080+
Tokens = annotate("void f() & requires(C<decltype(x)>) {}");
1081+
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
1082+
EXPECT_TOKEN(Tokens[4], tok::amp, TT_PointerOrReference);
1083+
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
1084+
1085+
Tokens = annotate("auto f() -> int& requires(C<decltype(x)>) {}");
1086+
ASSERT_EQ(Tokens.size(), 20u) << Tokens;
1087+
EXPECT_TOKEN(Tokens[6], tok::amp, TT_PointerOrReference);
1088+
EXPECT_TOKEN(Tokens[7], tok::kw_requires, TT_RequiresClause);
1089+
1090+
Tokens = annotate("bool x = t && requires(decltype(t) x) { x.foo(); };");
1091+
ASSERT_EQ(Tokens.size(), 23u) << Tokens;
1092+
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression);
1093+
1094+
Tokens = annotate("bool x = t && requires(Foo<decltype(t)> x) { x.foo(); };");
1095+
ASSERT_EQ(Tokens.size(), 26u) << Tokens;
1096+
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression);
1097+
1098+
Tokens = annotate("bool x = t && requires(Foo<C1 || C2> x) { x.foo(); };");
1099+
ASSERT_EQ(Tokens.size(), 25u) << Tokens;
1100+
EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresExpression);
10791101
}
10801102

10811103
TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {

0 commit comments

Comments
 (0)