Skip to content

[clang-format] Add LT_RequiresExpression and LT_SimpleRequirement #121681

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 6, 2025

Conversation

owenca
Copy link
Contributor

@owenca owenca commented Jan 5, 2025

The new line types help to annotate */&/&& in simple requirements as binary operators.

Fixes #121675.

@llvmbot
Copy link
Member

llvmbot commented Jan 5, 2025

@llvm/pr-subscribers-clang-format

Author: Owen Pan (owenca)

Changes

The new line types help to annotate */&/&& in simple requirements as binary operators.

Fixes #121675.


Full diff: https://github.com/llvm/llvm-project/pull/121681.diff

3 Files Affected:

  • (modified) clang/lib/Format/TokenAnnotator.cpp (+19-5)
  • (modified) clang/lib/Format/TokenAnnotator.h (+2)
  • (modified) clang/unittests/Format/TokenAnnotatorTest.cpp (+15-12)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 945174ca9c5861..fa864f4c5e943d 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -1582,7 +1582,10 @@ class AnnotatingParser {
         return false;
       break;
     case tok::l_brace:
-      if (Style.Language == FormatStyle::LK_TextProto) {
+      if (IsCpp) {
+        if (Tok->is(TT_RequiresExpressionLBrace))
+          Line.Type = LT_RequiresExpression;
+      } else if (Style.Language == FormatStyle::LK_TextProto) {
         FormatToken *Previous = Tok->getPreviousNonComment();
         if (Previous && Previous->isNot(TT_DictLiteral))
           Previous->setType(TT_SelectorName);
@@ -2024,8 +2027,10 @@ class AnnotatingParser {
       if (!consumeToken())
         return LT_Invalid;
     }
-    if (Line.Type == LT_AccessModifier)
-      return LT_AccessModifier;
+    if (Line.Type == LT_AccessModifier || Line.Type == LT_RequiresExpression ||
+        Line.Type == LT_SimpleRequirement) {
+      return Line.Type;
+    }
     if (KeywordVirtualFound)
       return LT_VirtualFunctionDecl;
     if (ImportStatement)
@@ -3102,8 +3107,10 @@ class AnnotatingParser {
       }
     }
 
-    if (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)
+    if (Line.Type == LT_SimpleRequirement ||
+        (!Scopes.empty() && Scopes.back() == ST_CompoundRequirement)) {
       return TT_BinaryOperator;
+    }
 
     return TT_PointerOrReference;
   }
@@ -3693,8 +3700,15 @@ void TokenAnnotator::annotate(AnnotatedLine &Line) {
 
   if (!Line.Children.empty()) {
     ScopeStack.push_back(ST_ChildBlock);
-    for (auto &Child : Line.Children)
+    const bool InRequiresExpression = Line.Type == LT_RequiresExpression;
+    for (auto &Child : Line.Children) {
+      if (InRequiresExpression &&
+          !Child->First->isOneOf(tok::kw_typename, tok::kw_requires,
+                                 TT_CompoundRequirementLBrace)) {
+        Child->Type = LT_SimpleRequirement;
+      }
       annotate(*Child);
+    }
     // ScopeStack can become empty if Child has an unmatched `}`.
     if (!ScopeStack.empty())
       ScopeStack.pop_back();
diff --git a/clang/lib/Format/TokenAnnotator.h b/clang/lib/Format/TokenAnnotator.h
index 1a250e94d97c50..fa15517042f250 100644
--- a/clang/lib/Format/TokenAnnotator.h
+++ b/clang/lib/Format/TokenAnnotator.h
@@ -33,6 +33,8 @@ enum LineType {
   LT_VirtualFunctionDecl,
   LT_ArrayOfStructInitializer,
   LT_CommentAbovePPDirective,
+  LT_RequiresExpression,
+  LT_SimpleRequirement,
 };
 
 enum ScopeType {
diff --git a/clang/unittests/Format/TokenAnnotatorTest.cpp b/clang/unittests/Format/TokenAnnotatorTest.cpp
index a5b2d09a9f704d..c07dbb36deaccc 100644
--- a/clang/unittests/Format/TokenAnnotatorTest.cpp
+++ b/clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -830,6 +830,21 @@ TEST_F(TokenAnnotatorTest, UnderstandsCasts) {
   EXPECT_TOKEN(Tokens[9], tok::identifier, TT_TypeName);
   EXPECT_TOKEN(Tokens[10], tok::r_paren, TT_CastRParen);
   EXPECT_TOKEN(Tokens[11], tok::amp, TT_UnaryOperator);
+
+  Tokens = annotate("template <typename T>\n"
+                    "concept Multiplicable = requires(T a, T b) { a * b; };");
+  ASSERT_EQ(Tokens.size(), 24u) << Tokens;
+  EXPECT_TOKEN(Tokens[16], tok::l_brace, TT_RequiresExpressionLBrace);
+  EXPECT_TOKEN(Tokens[18], tok::star, TT_BinaryOperator);
+
+  Tokens = annotate("template <typename T, typename V>\n"
+                    "concept CheckMultiplicableBy = requires(T a, V b) {\n"
+                    "  { a * b } -> std::same_as<T>;\n"
+                    "};");
+  ASSERT_EQ(Tokens.size(), 36u) << Tokens;
+  EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace);
+  EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace);
+  EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator);
 }
 
 TEST_F(TokenAnnotatorTest, UnderstandsDynamicExceptionSpecifier) {
@@ -1456,18 +1471,6 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresExpressions) {
   EXPECT_TOKEN(Tokens[13], tok::l_brace, TT_RequiresExpressionLBrace);
 }
 
-TEST_F(TokenAnnotatorTest, CompoundRequirement) {
-  auto Tokens = annotate("template <typename T, typename V>\n"
-                         "concept CheckMultiplicableBy = requires(T a, V b) {\n"
-                         "  { a * b } -> std::same_as<T>;\n"
-                         "};");
-  ASSERT_EQ(Tokens.size(), 36u) << Tokens;
-
-  EXPECT_TOKEN(Tokens[19], tok::l_brace, TT_RequiresExpressionLBrace);
-  EXPECT_TOKEN(Tokens[20], tok::l_brace, TT_CompoundRequirementLBrace);
-  EXPECT_TOKEN(Tokens[22], tok::star, TT_BinaryOperator);
-}
-
 TEST_F(TokenAnnotatorTest, UnderstandsPragmaRegion) {
   // Everything after #pragma region should be ImplicitStringLiteral
   auto Tokens = annotate("#pragma region Foo(Bar: Hello)");

The new line types help to annotate */&/&& in simple requirements as binary
operators.

Fixes llvm#121675.
@owenca owenca merged commit 9e4774b into llvm:main Jan 6, 2025
8 checks passed
@owenca owenca deleted the 121675 branch January 6, 2025 09:46
paulhuggett pushed a commit to paulhuggett/llvm-project that referenced this pull request Jan 7, 2025
…vm#121681)

The new line types help to annotate */&/&& in simple requirements as
binary operators.

Fixes llvm#121675.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[clang-format] simple-requirements not formatted as expressions
3 participants