HazardyKnusperkeks updated this revision to Diff 385594.
HazardyKnusperkeks added a comment.

Now the new diff.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D113369/new/

https://reviews.llvm.org/D113369

Files:
  clang/docs/ClangFormatStyleOptions.rst
  clang/include/clang/Format/Format.h
  clang/lib/Format/Format.cpp
  clang/lib/Format/TokenAnnotator.cpp
  clang/lib/Format/UnwrappedLineParser.cpp
  clang/unittests/Format/FormatTest.cpp

Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -14300,6 +14300,73 @@
   verifyFormat("X A::operator++ (T);", SomeSpace2);
   verifyFormat("int x = int (y);", SomeSpace2);
   verifyFormat("auto lambda = []() { return 0; };", SomeSpace2);
+
+  auto SpaceAfterRequires = getLLVMStyle();
+  SpaceAfterRequires.SpaceBeforeParens = FormatStyle::SBPO_Custom;
+  verifyFormat(
+      "template <typename T> void func(T) requires(trait<T> && trait<T>) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+  verifyFormat("template <typename T> void func(T) requires requires(T &&t) {\n"
+               "  typename T::size_type;\n"
+               "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+               "}\n"
+               "{}",
+               SpaceAfterRequires);
+
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresClause = true;
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresExpression = false;
+  verifyFormat(
+      "template <typename T> void func(T) requires (trait<T> && trait<T>) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+  verifyFormat(
+      "template <typename T> void func(T) requires requires(T &&t) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresClause = false;
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresExpression = true;
+  verifyFormat(
+      "template <typename T> void func(T) requires(trait<T> && trait<T>) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+  verifyFormat(
+      "template <typename T> void func(T) requires requires (T &&t) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresClause = true;
+  SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresExpression = true;
+  verifyFormat(
+      "template <typename T> void func(T) requires (trait<T> && trait<T>) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
+  verifyFormat(
+      "template <typename T> void func(T) requires requires (T &&t) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      SpaceAfterRequires);
 }
 
 TEST_F(FormatTest, SpaceAfterLogicalNot) {
@@ -22565,6 +22632,21 @@
                "}\n"
                "{}",
                Style);
+
+  Style.SpaceBeforeParens = FormatStyle::SBPO_Custom;
+  Style.SpaceBeforeParensOptions.AfterRequiresClause = true;
+  Style.SpaceBeforeParensOptions.AfterRequiresExpression = true;
+  verifyFormat("template <typename T>\n"
+               "  requires (std::is_integral_v<T> && std::is_signed_v<T>)\n"
+               "void func(T) {}",
+               Style);
+  verifyFormat(
+      "template <typename T> void func(T) requires requires (T &&t) {\n"
+      "  typename T::size_type;\n"
+      "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+      "}\n"
+      "{}",
+      Style);
 }
 
 TEST_F(FormatTest, StatementAttributeLikeMacros) {
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -2477,6 +2477,13 @@
 void UnwrappedLineParser::parseConstraintExpression(
     unsigned int OriginalLevel) {
   // requires Id<T> && Id<T> || Id<T>
+
+  if (FormatTok->Tok.is(tok::kw_requires)) {
+    assert(FormatTok->Previous);
+    assert(FormatTok->Previous->is(TT_RequiresClause));
+    FormatTok->setType(TT_RequiresExpression);
+  }
+
   while (
       FormatTok->isOneOf(tok::identifier, tok::kw_requires, tok::coloncolon)) {
     nextToken();
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -3137,8 +3137,16 @@
   if (Right.is(tok::l_paren)) {
     if (Left.is(TT_TemplateCloser) && Right.isNot(TT_FunctionTypeLParen))
       return spaceRequiredBeforeParens(Right);
-    if (Left.is(tok::kw_requires))
-      return spaceRequiredBeforeParens(Right);
+    if (Left.is(tok::kw_requires)) {
+      if (spaceRequiredBeforeParens(Right))
+        return true;
+      if (Left.is(TT_RequiresClause))
+        return Style.SpaceBeforeParensOptions.AfterRequiresClause;
+      else {
+        assert(Left.is(TT_RequiresExpression));
+        return Style.SpaceBeforeParensOptions.AfterRequiresExpression;
+      }
+    }
     if ((Left.is(tok::r_paren) && Left.is(TT_AttributeParen)) ||
         (Left.is(tok::r_square) && Left.is(TT_AttributeSquare)))
       return true;
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -855,6 +855,8 @@
     IO.mapOptional("AfterFunctionDeclarationName",
                    Spacing.AfterFunctionDeclarationName);
     IO.mapOptional("AfterIfMacros", Spacing.AfterIfMacros);
+    IO.mapOptional("AfterRequiresClause", Spacing.AfterRequiresClause);
+    IO.mapOptional("AfterRequiresExpression", Spacing.AfterRequiresExpression);
     IO.mapOptional("BeforeNonEmptyParentheses",
                    Spacing.BeforeNonEmptyParentheses);
   }
@@ -1214,6 +1216,7 @@
   LLVMStyle.SpaceBeforeCtorInitializerColon = true;
   LLVMStyle.SpaceBeforeInheritanceColon = true;
   LLVMStyle.SpaceBeforeParens = FormatStyle::SBPO_ControlStatements;
+  LLVMStyle.SpaceBeforeParensOptions = {};
   LLVMStyle.SpaceBeforeParensOptions.AfterControlStatements = true;
   LLVMStyle.SpaceBeforeParensOptions.AfterForeachMacros = true;
   LLVMStyle.SpaceBeforeParensOptions.AfterIfMacros = true;
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -3367,6 +3367,25 @@
     ///      <conditional-body>                     <conditional-body>
     /// \endcode
     bool AfterIfMacros;
+    /// If ``true``, put space between requires keyword in a requires clause and
+    /// opening parentheses, if there is one.
+    /// \code
+    ///    true:                                  false:
+    ///    template<typename T>            vs.    template<typename T>
+    ///    requires (A<T> && B<T>)                requires(A<T> && B<T>)
+    ///    ...                                    ...
+    /// \endcode
+    bool AfterRequiresClause;
+    /// If ``true``, put space between requires keyword in a requires expression
+    /// and opening parentheses.
+    /// \code
+    ///    true:                                  false:
+    ///    template<typename T>            vs.    template<typename T>
+    ///    requires (T t) {                       requires(T t) {
+    ///      ...                                    ...
+    ///    }                                      }
+    /// \endcode
+    bool AfterRequiresExpression;
     /// If ``true``, put a space before opening parentheses only if the
     /// parentheses are not empty.
     /// \code
@@ -3380,6 +3399,7 @@
         : AfterControlStatements(false), AfterForeachMacros(false),
           AfterFunctionDeclarationName(false),
           AfterFunctionDefinitionName(false), AfterIfMacros(false),
+          AfterRequiresClause(false), AfterRequiresExpression(false),
           BeforeNonEmptyParentheses(false) {}
 
     bool operator==(const SpaceBeforeParensCustom &Other) const {
@@ -3389,6 +3409,8 @@
                  Other.AfterFunctionDeclarationName &&
              AfterFunctionDefinitionName == Other.AfterFunctionDefinitionName &&
              AfterIfMacros == Other.AfterIfMacros &&
+             AfterRequiresClause == Other.AfterRequiresClause &&
+             AfterRequiresExpression == Other.AfterRequiresExpression &&
              BeforeNonEmptyParentheses == Other.BeforeNonEmptyParentheses;
     }
   };
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -3752,6 +3752,27 @@
        IF (...)                        vs.    IF(...)
          <conditional-body>                     <conditional-body>
 
+  * ``bool AfterRequiresClause`` If ``true``, put space between requires keyword in a requires clause and
+    opening parentheses, if there is one.
+
+    .. code-block:: c++
+
+       true:                                  false:
+       template<typename T>            vs.    template<typename T>
+       requires (A<T> && B<T>)                requires(A<T> && B<T>)
+       ...                                    ...
+
+  * ``bool AfterRequiresExpression`` If ``true``, put space between requires keyword in a requires expression
+    and opening parentheses.
+
+    .. code-block:: c++
+
+       true:                                  false:
+       template<typename T>            vs.    template<typename T>
+       requires (T t) {                       requires(T t) {
+         ...                                    ...
+       }                                      }
+
   * ``bool BeforeNonEmptyParentheses`` If ``true``, put a space before opening parentheses only if the
     parentheses are not empty.
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to