Skip to content

Commit bdf0c2e

Browse files
committed
[clang-format] Add LT_RequiresExpression and LT_SimpleRequirement
The new line types help to annotate */&/&& in simple requirements as binary operators. Fixes #121675.
1 parent 0093450 commit bdf0c2e

File tree

3 files changed

+36
-17
lines changed

3 files changed

+36
-17
lines changed

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 19 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,10 @@ class AnnotatingParser {
20242027
if (!consumeToken())
20252028
return LT_Invalid;
20262029
}
2027-
if (Line.Type == LT_AccessModifier)
2028-
return LT_AccessModifier;
2030+
if (Line.Type == LT_AccessModifier || Line.Type == LT_RequiresExpression ||
2031+
Line.Type == LT_SimpleRequirement) {
2032+
return Line.Type;
2033+
}
20292034
if (KeywordVirtualFound)
20302035
return LT_VirtualFunctionDecl;
20312036
if (ImportStatement)
@@ -3102,8 +3107,10 @@ class AnnotatingParser {
31023107
}
31033108
}
31043109

3105-
if (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)
3110+
if (Line.Type == LT_SimpleRequirement ||
3111+
(!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {
31063112
return TT_BinaryOperator;
3113+
}
31073114

31083115
return TT_PointerOrReference;
31093116
}
@@ -3693,8 +3700,15 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
36933700

36943701
if (!Line.Children.empty()) {
36953702
ScopeStack.push_back(ST_ChildBlock);
3696-
for (auto &Child : Line.Children)
3703+
const bool InRequiresExpression = Line.Type == LT_RequiresExpression;
3704+
for (auto &Child : Line.Children) {
3705+
if (InRequiresExpression &&
3706+
!Child->First->isOneOf(tok::kw_typename, tok::kw_requires,
3707+
TT_CompoundRequirementLBrace)) {
3708+
Child->Type = LT_SimpleRequirement;
3709+
}
36973710
annotate(*Child);
3711+
}
36983712
// ScopeStack can become empty if Child has an unmatched `}`.
36993713
if (!ScopeStack.empty())
37003714
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
@@ -830,6 +830,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) {
830830
EXPECT_TOKEN(Tokens[9], tok::identifier, TT_TypeName);
831831
EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen);
832832
EXPECT_TOKEN(Tokens[11], tok::amp, TT_UnaryOperator);
833+
834+
Tokens = annotate("template <typename T>\n"
835+
"concept Multiplicable = requires(T a, T b) { a * b; };");
836+
ASSERT_EQ(Tokens.size(), 24u) << Tokens;
837+
EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_RequiresExpressionLBrace);
838+
EXPECT_TOKEN(Tokens[18], tok::star, TT_BinaryOperator);
839+
840+
Tokens = annotate("template <typename T, typename V>\n"
841+
"concept CheckMultiplicableBy = requires(T a, V b) {\n"
842+
" { a * b } -> std::same_as<T>;\n"
843+
"};");
844+
ASSERT_EQ(Tokens.size(), 36u) << Tokens;
845+
EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace);
846+
EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace);
847+
EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator);
833848
}
834849

835850
TEST_F(TokenAnnotatorTest, UnderstandsDynamicExceptionSpecifier) {
@@ -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)