Skip to content

Commit 2496985

Browse files
owencapaulhuggett
authored andcommitted
[clang-format] Add LT_RequiresExpression and LT_SimpleRequirement (llvm#121681)
The new line types help to annotate */&/&& in simple requirements as binary operators. Fixes llvm#121675.
1 parent 3ce85be commit 2496985

File tree

3 files changed

+37
-17
lines changed

3 files changed

+37
-17
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,10 @@ class AnnotatingParser {
15821582
return false;
15831583
break;
15841584
case tok::l_brace:
1585-
if (Style.Language == FormatStyle::LK_TextProto) {
1585+
if (IsCpp) {
1586+
if (Tok->is(TT_RequiresExpressionLBrace))
1587+
Line.Type = LT_RequiresExpression;
1588+
} else if (Style.Language == FormatStyle::LK_TextProto) {
15861589
FormatToken *Previous = Tok->getPreviousNonComment();
15871590
if (Previous && Previous->isNot(TT_DictLiteral))
15881591
Previous->setType(TT_SelectorName);
@@ -2024,8 +2027,11 @@ class AnnotatingParser {
20242027
if (!consumeToken())
20252028
return LT_Invalid;
20262029
}
2027-
if (Line.Type == LT_AccessModifier)
2028-
return LT_AccessModifier;
2030+
if (const auto Type = Line.Type; Type == LT_AccessModifier ||
2031+
Type == LT_RequiresExpression ||
2032+
Type == LT_SimpleRequirement) {
2033+
return Type;
2034+
}
20292035
if (KeywordVirtualFound)
20302036
return LT_VirtualFunctionDecl;
20312037
if (ImportStatement)
@@ -3102,8 +3108,10 @@ class AnnotatingParser {
31023108
}
31033109
}
31043110

3105-
if (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)
3111+
if (Line.Type == LT_SimpleRequirement ||
3112+
(!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {
31063113
return TT_BinaryOperator;
3114+
}
31073115

31083116
return TT_PointerOrReference;
31093117
}
@@ -3693,8 +3701,15 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
36933701

36943702
if (!Line.Children.empty()) {
36953703
ScopeStack.push_back(ST_ChildBlock);
3696-
for (auto &Child : Line.Children)
3704+
const bool InRequiresExpression = Line.Type == LT_RequiresExpression;
3705+
for (auto &Child : Line.Children) {
3706+
if (InRequiresExpression &&
3707+
!Child->First->isOneOf(tok::kw_typename, tok::kw_requires,
3708+
TT_CompoundRequirementLBrace)) {
3709+
Child->Type = LT_SimpleRequirement;
3710+
}
36973711
annotate(*Child);
3712+
}
36983713
// ScopeStack can become empty if Child has an unmatched `}`.
36993714
if (!ScopeStack.empty())
37003715
ScopeStack.pop_back();

clang/lib/Format/TokenAnnotator.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ enum LineType {
3333
LT_VirtualFunctionDecl,
3434
LT_ArrayOfStructInitializer,
3535
LT_CommentAbovePPDirective,
36+
LT_RequiresExpression,
37+
LT_SimpleRequirement,
3638
};
3739

3840
enum ScopeType {

clang/unittests/Format/TokenAnnotatorTest.cpp

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsUsesOfStarAndAmp) {
370370
ASSERT_EQ(Tokens.size(), 18u) << Tokens;
371371
EXPECT_TOKEN(Tokens[8], tok::r_paren, TT_CastRParen);
372372
EXPECT_TOKEN(Tokens[11], tok::star, TT_BinaryOperator);
373+
374+
Tokens = annotate("template <typename T>\n"
375+
"concept C = requires(T a, T b) { a && b; };");
376+
ASSERT_EQ(Tokens.size(), 24u) << Tokens;
377+
EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_RequiresExpressionLBrace);
378+
EXPECT_TOKEN(Tokens[18], tok::ampamp, TT_BinaryOperator);
379+
380+
Tokens = annotate("template <typename T, typename V>\n"
381+
"concept CheckMultiplicableBy = requires(T a, V b) {\n"
382+
" { a * b } -> std::same_as<T>;\n"
383+
"};");
384+
ASSERT_EQ(Tokens.size(), 36u) << Tokens;
385+
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace);
386+
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace);
387+
EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator);
373388
}
374389

375390
TEST_F(TokenAnnotatorTest, UnderstandsUsesOfPlusAndMinus) {
@@ -1456,18 +1471,6 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {
14561471
EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_RequiresExpressionLBrace);
14571472
}
14581473

1459-
TEST_F(TokenAnnotatorTest, CompoundRequirement) {
1460-
auto Tokens = annotate("template <typename T, typename V>\n"
1461-
"concept CheckMultiplicableBy = requires(T a, V b) {\n"
1462-
" { a * b } -> std::same_as<T>;\n"
1463-
"};");
1464-
ASSERT_EQ(Tokens.size(), 36u) << Tokens;
1465-
1466-
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace);
1467-
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace);
1468-
EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator);
1469-
}
1470-
14711474
TEST_F(TokenAnnotatorTest, UnderstandsPragmaRegion) {
14721475
// Everything after #pragma region should be ImplicitStringLiteral
14731476
auto Tokens = annotate("#pragma region Foo(Bar: Hello)");

0 commit comments

Comments
 (0)