HazardyKnusperkeks updated this revision to Diff 391708.
HazardyKnusperkeks retitled this revision from "[clang-format] Improve require 
handling" to "[clang-format] Improve require and concept handling".
HazardyKnusperkeks edited the summary of this revision.
HazardyKnusperkeks added reviewers: gonzalobg, CaseyCarter.
HazardyKnusperkeks added a comment.
This revision is now accepted and ready to land.

Update on my work in progress. The new test cases are all passed. The old ones 
are only kept to pick some lines from them.

I would like to hear some feedback while I finish the rest, mostly writing 
tests.


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

https://reviews.llvm.org/D113319

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

Index: clang/unittests/Format/TokenAnnotatorTest.cpp
===================================================================
--- clang/unittests/Format/TokenAnnotatorTest.cpp
+++ clang/unittests/Format/TokenAnnotatorTest.cpp
@@ -67,6 +67,51 @@
   EXPECT_TOKEN(Tokens[11], tok::star, TT_PointerOrReference);
 }
 
+TEST_F(TokenAnnotatorTest, UnderstandsRequiresClauses) {
+  auto Tokens = annotate("template <typename T>\n"
+                         "concept C = (Foo && Bar) && (Bar && Baz);");
+
+  EXPECT_EQ(Tokens.size(), 21u) << Tokens;
+  EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[13], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[16], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template <typename T>\n"
+                    "concept C = requires(T t) {\n"
+                    "  { t.foo() };\n"
+                    "} && Bar<T> && Baz<T>;");
+  EXPECT_EQ(Tokens.size(), 35u) << Tokens;
+  EXPECT_TOKEN(Tokens[23], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[28], tok::ampamp, TT_BinaryOperator);
+
+  Tokens = annotate("template<typename T>\n"
+                    "requires C1<T> && (C21<T> || C22<T> && C2e<T>) && C3<T>\n"
+                    "struct Foo;");
+  EXPECT_EQ(Tokens.size(), 36u) << Tokens;
+  EXPECT_TOKEN(Tokens[6], tok::identifier, TT_Unknown);
+  EXPECT_EQ(Tokens[6]->FakeLParens.size(), 1u);
+  EXPECT_TOKEN(Tokens[10], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[16], tok::pipepipe, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[21], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[27], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[31], tok::greater, TT_TemplateCloser);
+  EXPECT_EQ(Tokens[31]->FakeRParens, 1u);
+
+  Tokens =
+      annotate("template<typename T>\n"
+               "requires (C1<T> && (C21<T> || C22<T> && C2e<T>) && C3<T>)\n"
+               "struct Foo;");
+  EXPECT_EQ(Tokens.size(), 38u) << Tokens;
+  EXPECT_TOKEN(Tokens[7], tok::identifier, TT_Unknown);
+  EXPECT_EQ(Tokens[7]->FakeLParens.size(), 1u);
+  EXPECT_TOKEN(Tokens[11], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[17], tok::pipepipe, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[22], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[28], tok::ampamp, TT_BinaryOperator);
+  EXPECT_TOKEN(Tokens[32], tok::greater, TT_TemplateCloser);
+  EXPECT_EQ(Tokens[32]->FakeRParens, 1u);
+}
+
 } // namespace
 } // namespace format
 } // namespace clang
Index: clang/unittests/Format/FormatTest.cpp
===================================================================
--- clang/unittests/Format/FormatTest.cpp
+++ clang/unittests/Format/FormatTest.cpp
@@ -19143,6 +19143,30 @@
   // For backward compatibility:
   CHECK_PARSE("SpacesInAngles: false", SpacesInAngles, FormatStyle::SIAS_Never);
   CHECK_PARSE("SpacesInAngles: true", SpacesInAngles, FormatStyle::SIAS_Always);
+
+  CHECK_PARSE("RequiresClausePositionForClasses: ToPreceeding",
+              RequiresClausePositionForClasses, FormatStyle::RCPS_ToPreceeding);
+  CHECK_PARSE("RequiresClausePositionForClasses: ToFollowing",
+              RequiresClausePositionForClasses, FormatStyle::RCPS_ToFollowing);
+  CHECK_PARSE("RequiresClausePositionForClasses: SingleLine",
+              RequiresClausePositionForClasses, FormatStyle::RCPS_SingleLine);
+  CHECK_PARSE("RequiresClausePositionForClasses: TwoLines",
+              RequiresClausePositionForClasses, FormatStyle::RCPS_TwoLines);
+  CHECK_PARSE("RequiresClausePositionForClasses: OwnLine",
+              RequiresClausePositionForClasses, FormatStyle::RCPS_OwnLine);
+
+  CHECK_PARSE("RequiresClausePositionForFunctions: ToPreceeding",
+              RequiresClausePositionForFunctions,
+              FormatStyle::RCPS_ToPreceeding);
+  CHECK_PARSE("RequiresClausePositionForFunctions: ToFollowing",
+              RequiresClausePositionForFunctions,
+              FormatStyle::RCPS_ToFollowing);
+  CHECK_PARSE("RequiresClausePositionForFunctions: SingleLine",
+              RequiresClausePositionForFunctions, FormatStyle::RCPS_SingleLine);
+  CHECK_PARSE("RequiresClausePositionForFunctions: TwoLines",
+              RequiresClausePositionForFunctions, FormatStyle::RCPS_TwoLines);
+  CHECK_PARSE("RequiresClausePositionForFunctions: OwnLine",
+              RequiresClausePositionForFunctions, FormatStyle::RCPS_OwnLine);
 }
 
 TEST_F(FormatTest, ParsesConfigurationWithLanguages) {
@@ -22257,43 +22281,234 @@
                Style);
 }
 
-TEST_F(FormatTest, ConceptsAndRequires) {
-  FormatStyle Style = getLLVMStyle();
-  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+TEST_F(FormatTest, Concepts) {
+  verifyFormat("template <typename T>\n"
+               "concept True = true;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = ((false || foo()) && C2<T>) || "
+               "(std::trait<T>::value && Baz) ||\n "
+               "           sizeof(T) >= 6;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = true && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = false || requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = !!false || requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat(
+      "template <typename T>\n"
+      "concept DelayedCheck = static_cast<bool>(0) || requires(T t) {\n"
+      "  t.bar();\n"
+      "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = bool(0) || requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = (bool)(0) || requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept DelayedCheck = (bool)0 || requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept Size = sizeof(T) >= 5 && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat(
+      "template <typename T>\n"
+      "concept Size = 2 < 5 && 2 <= 5 && 8 >= 5 && 8 > 5 && requires(T t) {\n"
+      "  t.bar();\n"
+      "} && sizeof(T) <= 8 && !(4 < 3);");
+
+  verifyFormat("template <typename T>\n"
+               "concept TrueOrNot = IsAlwaysTrue || IsNeverTrue;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = foo();");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = foo(T());");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = foo(T{});");
+
+  verifyFormat("template <typename T>\n"
+               "concept Size = V<sizeof(T)>::Value > 5;");
+
+  verifyFormat("template <typename T>\n"
+               "concept True = S<T>::Value;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = []() { return true; }() && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = [] { return true; }() && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = [] -> bool { return true; }() && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat(
+      "template <typename T>\n"
+      "concept C = decltype([]() { return std::true_type{}; }())::value &&\n"
+      "            requires(T t) {\n"
+      "  t.bar();\n"
+      "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = decltype([]() { return std::true_type{}; "
+               "}())::value && requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;",
+               getLLVMStyleWithColumns(120));
+
+  verifyFormat("template <typename T>\n"
+               "concept C = decltype([]() -> std::true_type { return {}; "
+               "}())::value &&\n"
+               "            requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = true;\n"
+               "Foo Bar;");
 
   verifyFormat("template <typename T>\n"
                "concept Hashable = requires(T a) {\n"
                "  { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;\n"
-               "};",
-               Style);
+               "};");
+
   verifyFormat("template <typename T>\n"
                "concept EqualityComparable = requires(T a, T b) {\n"
-               "  { a == b } -> bool;\n"
-               "};",
-               Style);
+               "  { a == b } -> std::same_as<bool>;\n"
+               "};");
+
   verifyFormat("template <typename T>\n"
                "concept EqualityComparable = requires(T a, T b) {\n"
-               "  { a == b } -> bool;\n"
-               "  { a != b } -> bool;\n"
-               "};",
-               Style);
+               "  { a == b } -> std::same_as<bool>;\n"
+               "  { a != b } -> std::same_as<bool>;\n"
+               "};");
+
   verifyFormat("template <typename T>\n"
-               "concept EqualityComparable = requires(T a, T b) {\n"
-               "  { a == b } -> bool;\n"
-               "  { a != b } -> bool;\n"
-               "};",
-               Style);
+               "concept WeakEqualityComparable = requires(T a, T b) {\n"
+               "  { a == b };\n"
+               "  { a != b };\n"
+               "};");
 
-  verifyFormat("template <typename It>\n"
-               "requires Iterator<It>\n"
-               "void sort(It begin, It end) {\n"
-               "  //....\n"
-               "}",
-               Style);
+  verifyFormat("template <typename T>\n"
+               "concept HasSizeT = requires {\n"
+               "  typename T::size_t;\n"
+               "};");
 
   verifyFormat("template <typename T>\n"
-               "concept Large = sizeof(T) > 10;",
-               Style);
+               "concept Semiregular = DefaultConstructible<T> && "
+               "CopyConstructible<T> &&\n"
+               "                      CopyAssignable<T> && requires(T a, "
+               "std::size_t n) {\n"
+               "  requires Same<T *, decltype(&a)>;\n"
+               "  { a.~T() } noexcept;\n"
+               "  requires Same<T *, decltype(new T)>;\n"
+               "  requires Same<T *, decltype(new T[n])>;\n"
+               "  { delete new T; };\n"
+               "  { delete new T[n]; };\n"
+               "};");
+
+  verifyFormat("template <typename T>\n"
+               "concept Semiregular = requires(T a, std::size_t n) {\n"
+               "  requires Same<T *, decltype(&a)>;\n"
+               "  { a.~T() } noexcept;\n"
+               "  requires Same<T *, decltype(new T)>;\n"
+               "  requires Same<T *, decltype(new T[n])>;\n"
+               "  { delete new T; };\n"
+               "  { delete new T[n]; };\n"
+               "  { new T } -> std::same_as<T *>;\n"
+               "} && DefaultConstructible<T> && CopyConstructible<T> && "
+               "CopyAssignable<T>;");
+
+  verifyFormat("template <typename T>\n"
+               "concept Semiregular = DefaultConstructible<T> requires(T a, "
+               "std::size_t n) {\n"
+               "  requires Same<T *, decltype(&a)>;\n"
+               "  { a.~T() } noexcept;\n"
+               "  requires Same<T *, decltype(new T)>;\n"
+               "  requires Same<T *, decltype(new T[n])>;\n"
+               "  { delete new T; };\n"
+               "  { delete new T[n]; };\n"
+               "} && CopyConstructible<T> && CopyAssignable<T>;");
+
+  verifyFormat("template <typename T>\n"
+               "concept Two = requires(T t) {\n"
+               "  { t.foo() } -> std::same_as<Bar>;\n"
+               "} && requires(T &&t) {\n"
+               "  { t.foo() } -> std::same_as<Bar &&>;\n"
+               "}");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = requires(T x) {\n"
+               "  { *x } -> std::convertible_to<typename T::inner>;\n"
+               "  { x + 1 } noexcept -> std::same_as<int>;\n"
+               "  { x * 1 } -> std::convertible_to<T>;\n"
+               "};");
+
+  verifyFormat("template <typename T, typename U = T>\n"
+               "concept Swappable = requires(T &&t, U &&u) {\n"
+               "  swap(std::forward<T>(t), std::forward<U>(u));\n"
+               "  swap(std::forward<U>(u), std::forward<T>(t));\n"
+               "};");
+
+  verifyFormat("template <typename T, typename U>\n"
+               "concept Common = requires(T &&t, U &&u) {\n"
+               "  typename CommonType<T, U>;\n"
+               "  { CommonType<T, U>(std::forward<T>(t)) };\n"
+               "};");
+
+  verifyFormat("template <typename T, typename U>\n"
+               "concept Common = requires(T &&t, U &&u) {\n"
+               "  typename CommonType<T, U>;\n"
+               "  { CommonType<T, U>{std::forward<T>(t)} };\n"
+               "};");
+
+  verifyFormat("template <typename T>\n"
+               "concept C = requires(T t) {\n"
+               "  requires Bar<T> && Foo<T>;\n"
+               "  requires((trait<T> && Baz) || (T2<T> && Foo<T>));\n"
+               "};");
+
+  verifyFormat("template <typename T>\n"
+               "concept HasFoo = requires(T t) {\n"
+               "  { t.foo() };\n"
+               "  t.foo();\n"
+               "};\n"
+               "template <typename T>\n"
+               "concept HasBar = requires(T t) {\n"
+               "  { t.bar() };\n"
+               "  t.bar();\n"
+               "};");
+
+  verifyFormat("template <typename T>\n"
+               "concept Large = sizeof(T) > 10;");
 
   verifyFormat("template <typename T, typename U>\n"
                "concept FooableWith = requires(T t, U u) {\n"
@@ -22301,199 +22516,881 @@
                "  { t.foo(u) } -> typename T::foo_type;\n"
                "  t++;\n"
                "};\n"
-               "void doFoo(FooableWith<int> auto t) {\n"
-               "  t.foo(3);\n"
-               "}",
-               Style);
-  verifyFormat("template <typename T>\n"
-               "concept Context = sizeof(T) == 1;",
-               Style);
-  verifyFormat("template <typename T>\n"
-               "concept Context = is_specialization_of_v<context, T>;",
-               Style);
+               "void doFoo(FooableWith<int> auto t) { t.foo(3); }");
+
   verifyFormat("template <typename T>\n"
-               "concept Node = std::is_object_v<T>;",
-               Style);
+               "concept Context = is_specialization_of_v<context, T>;");
+
   verifyFormat("template <typename T>\n"
-               "concept Tree = true;",
-               Style);
+               "concept Node = std::is_object_v<T>;");
 
-  verifyFormat("template <typename T> int g(T i) requires Concept1<I> {\n"
-               "  //...\n"
-               "}",
+  auto Style = getLLVMStyle();
+  Style.BreakBeforeConceptDeclarations = false;
+
+  verifyFormat("template <typename T> concept C = requires(T t) {\n"
+               "  requires Bar<T> && Foo<T>;\n"
+               "  requires((trait<T> && Baz) || (T2<T> && Foo<T>));\n"
+               "};",
                Style);
 
-  verifyFormat(
-      "template <typename T> int g(T i) requires Concept1<I> && Concept2<I> {\n"
-      "  //...\n"
-      "}",
-      Style);
+  verifyFormat("template <typename T> concept HasFoo = requires(T t) {\n"
+               "  { t.foo() };\n"
+               "  t.foo();\n"
+               "};\n"
+               "template <typename T> concept HasBar = requires(T t) {\n"
+               "  { t.bar() };\n"
+               "  t.bar();\n"
+               "};",
+               Style);
 
-  verifyFormat(
-      "template <typename T> int g(T i) requires Concept1<I> || Concept2<I> {\n"
-      "  //...\n"
-      "}",
-      Style);
+  verifyFormat("template <typename T> concept True = true;", Style);
 
   verifyFormat("template <typename T>\n"
-               "veryveryvery_long_return_type g(T i) requires Concept1<I> || "
-               "Concept2<I> {\n"
-               "  //...\n"
-               "}",
+               "concept C = decltype([]() -> std::true_type { return {}; "
+               "}())::value &&\n"
+               "            requires(T t) {\n"
+               "  t.bar();\n"
+               "} && sizeof(T) <= 8;",
                Style);
 
   verifyFormat("template <typename T>\n"
-               "veryveryvery_long_return_type g(T i) requires Concept1<I> && "
-               "Concept2<I> {\n"
-               "  //...\n"
-               "}",
+               "concept Semiregular = DefaultConstructible<T> && "
+               "CopyConstructible<T> &&\n"
+               "                      CopyAssignable<T> && requires(T a, "
+               "std::size_t n) {\n"
+               "  requires Same<T *, decltype(&a)>;\n"
+               "  { a.~T() } noexcept;\n"
+               "  requires Same<T *, decltype(new T)>;\n"
+               "  requires Same<T *, decltype(new T[n])>;\n"
+               "  { delete new T; };\n"
+               "  { delete new T[n]; };\n"
+               "};",
                Style);
 
-  verifyFormat(
-      "template <typename T>\n"
-      "veryveryvery_long_return_type g(T i) requires Concept1 && Concept2 {\n"
-      "  //...\n"
-      "}",
-      Style);
+  // The following tests are invalid C++, we just want to make sure we don't
+  // assert.
+  verifyFormat("template <typename T>\n"
+               "concept C = requires C2<T>;");
 
-  verifyFormat(
-      "template <typename T>\n"
-      "veryveryvery_long_return_type g(T i) requires Concept1 || Concept2 {\n"
-      "  //...\n"
-      "}",
-      Style);
+  verifyFormat("template <typename T>\n"
+               "concept C = 5 + 4;");
 
-  verifyFormat("template <typename It>\n"
-               "requires Foo<It>() && Bar<It> {\n"
-               "  //....\n"
-               "}",
-               Style);
+  verifyFormat("template <typename T>\n"
+               "concept C =\n"
+               "class X;");
 
-  verifyFormat("template <typename It>\n"
-               "requires Foo<Bar<It>>() && Bar<Foo<It, It>> {\n"
-               "  //....\n"
-               "}",
-               Style);
+  verifyFormat("template <typename T>\n"
+               "concept C = [] && true;");
 
-  verifyFormat("template <typename It>\n"
-               "requires Foo<Bar<It, It>>() && Bar<Foo<It, It>> {\n"
-               "  //....\n"
-               "}",
-               Style);
+  verifyFormat("template <typename T>\n"
+               "concept C = [] && requires(T t) {\n"
+               "  typename T::size_type;\n"
+               "};");
+}
 
-  verifyFormat(
-      "template <typename It>\n"
-      "requires Foo<Bar<It>, Baz<It>>() && Bar<Foo<It>, Baz<It, It>> {\n"
-      "  //....\n"
-      "}",
-      Style);
+TEST_F(FormatTest, RequiresClauseBeforeClass) {
+  auto Style = getLLVMStyle();
+  EXPECT_EQ(Style.RequiresClausePositionForClasses, FormatStyle::RCPS_OwnLine);
+  EXPECT_EQ(Style.IndentRequires, false);
 
-  Style.IndentRequires = true;
-  verifyFormat("template <typename It>\n"
-               "  requires Iterator<It>\n"
-               "void sort(It begin, It end) {\n"
-               "  //....\n"
-               "}",
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+                 "requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+                 "struct constant;",
+                 Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
                Style);
-  verifyFormat("template <std::size index_>\n"
-               "  requires(index_ < sizeof...(Children_))\n"
-               "Tree auto &child() {\n"
-               "  // ...\n"
-               "}",
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires true\n"
+               "struct constant;",
                Style);
 
-  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
-  verifyFormat("template <typename T>\n"
-               "concept Hashable = requires (T a) {\n"
-               "  { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;\n"
-               "};",
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>\n"
+               "struct constant;",
                Style);
 
-  verifyFormat("template <class T = void>\n"
-               "  requires EqualityComparable<T> || Same<T, void>\n"
-               "struct equal_to;",
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>)\n"
+               "struct constant;",
                Style);
 
-  verifyFormat("template <class T>\n"
-               "  requires requires {\n"
-               "    T{};\n"
-               "    T (int);\n"
-               "  }\n",
+  verifyFormat("template <typename T>\n"
+               "requires(C<T> && C2<T>)\n"
+               "class Foo;",
                Style);
 
-  Style.ColumnLimit = 78;
   verifyFormat("template <typename T>\n"
-               "concept Context = Traits<typename T::traits_type> and\n"
-               "    Interface<typename T::interface_type> and\n"
-               "    Request<typename T::request_type> and\n"
-               "    Response<typename T::response_type> and\n"
-               "    ContextExtension<typename T::extension_type> and\n"
-               "    ::std::is_copy_constructable<T> and "
-               "::std::is_move_constructable<T> and\n"
-               "    requires (T c) {\n"
-               "  { c.response; } -> Response;\n"
-               "} and requires (T c) {\n"
-               "  { c.request; } -> Request;\n"
-               "}\n",
+               "requires(C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
                Style);
 
   verifyFormat("template <typename T>\n"
-               "concept Context = Traits<typename T::traits_type> or\n"
-               "    Interface<typename T::interface_type> or\n"
-               "    Request<typename T::request_type> or\n"
-               "    Response<typename T::response_type> or\n"
-               "    ContextExtension<typename T::extension_type> or\n"
-               "    ::std::is_copy_constructable<T> or "
-               "::std::is_move_constructable<T> or\n"
-               "    requires (T c) {\n"
-               "  { c.response; } -> Response;\n"
-               "} or requires (T c) {\n"
-               "  { c.request; } -> Request;\n"
-               "}\n",
+               "requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
                Style);
 
   verifyFormat("template <typename T>\n"
-               "concept Context = Traits<typename T::traits_type> &&\n"
-               "    Interface<typename T::interface_type> &&\n"
-               "    Request<typename T::request_type> &&\n"
-               "    Response<typename T::response_type> &&\n"
-               "    ContextExtension<typename T::extension_type> &&\n"
-               "    ::std::is_copy_constructable<T> && "
-               "::std::is_move_constructable<T> &&\n"
-               "    requires (T c) {\n"
-               "  { c.response; } -> Response;\n"
-               "} && requires (T c) {\n"
-               "  { c.request; } -> Request;\n"
-               "}\n",
+               "requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
                Style);
 
-  verifyFormat("template <typename T>\nconcept someConcept = Constraint1<T> && "
-               "Constraint2<T>;");
+  Style.IndentRequires = true;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
 
-  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
-  Style.BraceWrapping.AfterFunction = true;
-  Style.BraceWrapping.AfterClass = true;
-  Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
-  Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
-  verifyFormat("void Foo () requires (std::copyable<T>)\n"
-               "{\n"
-               "  return\n"
-               "}\n",
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
                Style);
 
-  verifyFormat("void Foo () requires std::copyable<T>\n"
-               "{\n"
-               "  return\n"
-               "}\n",
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires true\n"
+               "struct constant;",
                Style);
 
   verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
-               "  requires (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "  requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>\n"
                "struct constant;",
                Style);
 
   verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
-               "  requires std::invocable<F, std::invoke_result_t<Args>...>\n"
+               "  requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires(C<T> && C2<T>)\n"
+               "class Foo;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires(C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.RequiresClausePositionForClasses = FormatStyle::RCPS_SingleLine;
+  Style.IndentRequires = false;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires true struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F> struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>) struct constant;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>) class Foo;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>) class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T> class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.IndentRequires = true;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires true struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F> struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>) struct constant;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>) class Foo;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>) class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T> class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.RequiresClausePositionForClasses = FormatStyle::RCPS_ToPreceeding;
+  Style.IndentRequires = false;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat(
+      "template <std::semiregular F, std::semiregular... Args> requires true\n"
+      "struct constant;",
+      Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(Concept1<F> && Concept2<Args...> && ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>)\n"
+               "class Foo;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.IndentRequires = true;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat(
+      "template <std::semiregular F, std::semiregular... Args> requires true\n"
+      "struct constant;",
+      Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>)\n"
+               "class Foo;",
+               Style);
+
+  verifyFormat("template <typename T> requires(C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T> requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.RequiresClausePositionForClasses = FormatStyle::RCPS_ToFollowing;
+  Style.IndentRequires = false;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires true struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F> struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "         AndAnotherConcept<F>) struct constant;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires(C<T> && C2<T>) class Foo;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires(C<T> && C2<T>) class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T> class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.IndentRequires = true;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(std::invocable<F, std::invoke_result_t<Args>...>) "
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires true struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F> struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires(Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "           AndAnotherConcept<F>) struct constant;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires(C<T> && C2<T>) class Foo;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires(C<T> && C2<T>) class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T> class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.RequiresClausePositionForClasses = FormatStyle::RCPS_TwoLines;
+  Style.IndentRequires = false;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires\n"
+               "        (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires\n"
+               "        (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires\n"
+               "        true\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "requires\n"
+               "        Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "        AndAnotherConcept<F>\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires\n"
+               "        (C<T> && C2<T>)\n"
+               "class Foo;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires\n"
+               "        (C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires\n"
+               "        requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "requires\n"
+               "        requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  Style.IndentRequires = true;
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires\n"
+               "          (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires\n"
+               "          (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant {\n"
+               "  int Foo;\n"
+               "  double Bar;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires\n"
+               "          true\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires\n"
+               "          Concept1<F> && Concept2<Args...> && "
+               "ThisIsAVeryLongConceptName<F> &&\n"
+               "          AndAnotherConcept<F>\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires\n"
+               "          (C<T> && C2<T>)\n"
+               "class Foo;",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires\n"
+               "          (C<T> && C2<T>)\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires\n"
+               "          requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "}\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires\n"
+               "          requires(T t) {\n"
+               "  typename T::Bar;\n"
+               "  { t.bar() } -> std::same_as<bool>;\n"
+               "} && C<T>\n"
+               "class Foo {\n"
+               "public:\n"
+               "  Foo();\n"
+               "  void foo() const;\n"
+               "};",
+               Style);
+}
+
+TEST_F(FormatTest, ConceptsAndRequires) {
+  return;
+  FormatStyle Style = getLLVMStyle();
+  Style.AllowShortFunctionsOnASingleLine = FormatStyle::SFS_None;
+
+  verifyFormat("template <typename It>\n"
+               "requires Iterator<It>\n"
+               "void sort(It begin, It end) {\n"
+               "  //....\n"
+               "}",
+               Style);
+
+  verifyFormat("template <typename T> int g(T i) requires Concept1<I> {\n"
+               "  //...\n"
+               "}",
+               Style);
+
+  verifyFormat(
+      "template <typename T> int g(T i) requires Concept1<I> && Concept2<I> {\n"
+      "  //...\n"
+      "}",
+      Style);
+
+  verifyFormat(
+      "template <typename T> int g(T i) requires Concept1<I> || Concept2<I> {\n"
+      "  //...\n"
+      "}",
+      Style);
+
+  verifyFormat("template <typename T>\n"
+               "veryveryvery_long_return_type g(T i) requires Concept1<I> || "
+               "Concept2<I> {\n"
+               "  //...\n"
+               "}",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "veryveryvery_long_return_type g(T i) requires Concept1<I> && "
+               "Concept2<I> {\n"
+               "  //...\n"
+               "}",
+               Style);
+
+  verifyFormat(
+      "template <typename T>\n"
+      "veryveryvery_long_return_type g(T i) requires Concept1 && Concept2 {\n"
+      "  //...\n"
+      "}",
+      Style);
+
+  verifyFormat(
+      "template <typename T>\n"
+      "veryveryvery_long_return_type g(T i) requires Concept1 || Concept2 {\n"
+      "  //...\n"
+      "}",
+      Style);
+
+  verifyFormat("template <typename It>\n"
+               "requires Foo<It>() && Bar<It> {\n"
+               "  //....\n"
+               "}",
+               Style);
+
+  verifyFormat("template <typename It>\n"
+               "requires Foo<Bar<It>>() && Bar<Foo<It, It>> {\n"
+               "  //....\n"
+               "}",
+               Style);
+
+  verifyFormat("template <typename It>\n"
+               "requires Foo<Bar<It, It>>() && Bar<Foo<It, It>> {\n"
+               "  //....\n"
+               "}",
+               Style);
+
+  verifyFormat(
+      "template <typename It>\n"
+      "requires Foo<Bar<It>, Baz<It>>() && Bar<Foo<It>, Baz<It, It>> {\n"
+      "  //....\n"
+      "}",
+      Style);
+
+  Style.IndentRequires = true;
+  verifyFormat("template <typename It>\n"
+               "  requires Iterator<It>\n"
+               "void sort(It begin, It end) {\n"
+               "  //....\n"
+               "}",
+               Style);
+  verifyFormat("template <std::size index_>\n"
+               "  requires(index_ < sizeof...(Children_))\n"
+               "Tree auto &child() {\n"
+               "  // ...\n"
+               "}",
+               Style);
+
+  Style.SpaceBeforeParens = FormatStyle::SBPO_Always;
+
+  verifyFormat("template <class T = void>\n"
+               "  requires EqualityComparable<T> || Same<T, void>\n"
+               "struct equal_to;",
+               Style);
+
+  Style.BreakBeforeBraces = FormatStyle::BS_Custom;
+  Style.BraceWrapping.AfterFunction = true;
+  Style.BraceWrapping.AfterClass = true;
+  Style.AlwaysBreakTemplateDeclarations = FormatStyle::BTDS_Yes;
+  Style.BreakConstructorInitializers = FormatStyle::BCIS_BeforeColon;
+  verifyFormat("void Foo () requires (std::copyable<T>)\n"
+               "{\n"
+               "  return\n"
+               "}\n",
+               Style);
+
+  verifyFormat("void Foo () requires std::copyable<T>\n"
+               "{\n"
+               "  return\n"
+               "}\n",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires (std::invocable<F, std::invoke_result_t<Args>...>)\n"
+               "struct constant;",
+               Style);
+
+  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
+               "  requires std::invocable<F, std::invoke_result_t<Args>...>\n"
                "struct constant;",
                Style);
 
@@ -22518,13 +23415,114 @@
                "}\n",
                Style);
 
-  Style.BreakBeforeConceptDeclarations = false;
-  verifyFormat("template <typename T> concept Tree = true;", Style);
-
   Style.IndentRequires = false;
-  verifyFormat("template <std::semiregular F, std::semiregular... Args>\n"
-               "requires (std::invocable<F, std::invoke_result_t<Args>...>) "
-               "struct constant;",
+
+  verifyFormat("template <typename T> void func(T);");
+
+  verifyFormat("template <typename T>\n"
+               "requires std::signed_integral<T> && std::signed_integral<T>\n"
+               "void func(T);");
+  verifyFormat("template <typename T>\n"
+               "requires(std::is_integral_v<T> && std::is_signed_v<T>)\n"
+               "void func(T);");
+  verifyFormat("template <tyename T>\n"
+               "requires requires(T &&t) {\n"
+               "  typename T::size_type;\n"
+               "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+               "}\n"
+               "func(T);");
+
+  verifyFormat("template <typename T>\n"
+               "requires std::signed_integral<T> && std::signed_integral<T>\n"
+               "void func(T) {}");
+  verifyFormat("template <typename T>\n"
+               "requires(std::is_integral_v<T> && std::is_signed_v<T>)\n"
+               "void func(T) {}");
+  verifyFormat("template <tyename T>\n"
+               "requires requires(T &&t) {\n"
+               "  typename T::size_type;\n"
+               "  { t.size() } -> std::same_as<typename T::size_type>;\n"
+               "}\n"
+               "func(T) {}");
+
+  verifyFormat(
+      "template <typename T> void func(T) requires std::signed_integral<T>;");
+  verifyFormat("template <typename T>\n"
+               "void func(T) requires std::signed_integral<T> && "
+               "std::signed_integral<T>;");
+  verifyFormat(
+      "template <typename T>\n"
+      "void func(T) requires(std::is_integral_v<T> && std::is_signed_v<T>);");
+  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"
+               "};");
+
+  verifyFormat(
+      "template <typename T> void func(T) requires std::signed_integral<T> {}");
+  verifyFormat("template <typename T>\n"
+               "void func(T) requires std::signed_integral<T> && "
+               "std::signed_integral<T> {}");
+  verifyFormat(
+      "template <typename T>\n"
+      "void func(T) requires(std::is_integral_v<T> && std::is_signed_v<T>) {}");
+  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 = getLLVMStyle();
+  Style.IndentRequires = true;
+
+  verifyFormat("template <typename T>\n"
+               "  requires std::signed_integral<T> && std::signed_integral<T>\n"
+               "void func(T);",
+               Style);
+  verifyFormat("template <typename T>\n"
+               "  requires(std::is_integral_v<T> && std::is_signed_v<T>)\n"
+               "void func(T);",
+               Style);
+  verifyFormat("template <tyename T>\n"
+               "  requires requires(T &&t) {\n"
+               "    typename T::size_type;\n"
+               "    { t.size() } -> std::same_as<typename T::size_type>;\n"
+               "  }\n"
+               "func(T);",
+               Style);
+
+  verifyFormat("template <typename T>\n"
+               "  requires std::signed_integral<T> && std::signed_integral<T>\n"
+               "void func(T) {}",
+               Style);
+  verifyFormat("template <typename T>\n"
+               "  requires(std::is_integral_v<T> && std::is_signed_v<T>)\n"
+               "void func(T) {}",
+               Style);
+  verifyFormat("template <tyename T>\n"
+               "  requires requires(T &&t) {\n"
+               "    typename T::size_type;\n"
+               "    { t.size() } -> std::same_as<typename T::size_type>;\n"
+               "  }\n"
+               "func(T) {}",
+               Style);
+
+  verifyFormat(
+      "template <typename T> void func(T) requires std::signed_integral<T> {}",
+      Style);
+  verifyFormat("template <typename T>\n"
+               "void func(T) requires std::signed_integral<T> && "
+               "std::signed_integral<T> {}",
+               Style);
+  verifyFormat(
+      "template <typename T>\n"
+      "void func(T) requires(std::is_integral_v<T> && std::is_signed_v<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);
 }
 
Index: clang/lib/Format/UnwrappedLineParser.h
===================================================================
--- clang/lib/Format/UnwrappedLineParser.h
+++ clang/lib/Format/UnwrappedLineParser.h
@@ -83,10 +83,12 @@
 private:
   void reset();
   void parseFile();
-  void parseLevel(bool HasOpeningBrace);
+  void parseLevel(bool HasOpeningBrace, bool CanContainBracedList,
+                  TokenType NextLBracesType = TT_Unknown);
   void parseBlock(bool MustBeDeclaration = false, unsigned AddLevels = 1u,
-                  bool MunchSemi = true,
-                  bool UnindentWhitesmithsBraces = false);
+                  bool MunchSemi = true, bool UnindentWhitesmithsBraces = false,
+                  bool CanContainBracedList = true,
+                  TokenType NextLBracesType = TT_Unknown);
   void parseChildBlock();
   void parsePPDirective();
   void parsePPDefine();
@@ -96,11 +98,12 @@
   void parsePPEndIf();
   void parsePPUnknown();
   void readTokenWithJavaScriptASI();
-  void parseStructuralElement(bool IsTopLevel = false);
+  void parseStructuralElement(bool IsTopLevel = false,
+                              TokenType NextLBracesType = TT_Unknown);
   bool tryToParseBracedList();
   bool parseBracedList(bool ContinueOnSemicolons = false, bool IsEnum = false,
                        tok::TokenKind ClosingBraceKind = tok::r_brace);
-  void parseParens();
+  void parseParens(TokenType AmpAmpTokenType = TT_Unknown);
   void parseSquare(bool LambdaIntroducer = false);
   void parseIfThenElse();
   void parseTryCatch();
@@ -116,9 +119,9 @@
   bool parseEnum();
   bool parseStructLike();
   void parseConcept();
-  void parseRequires();
-  void parseRequiresExpression(unsigned int OriginalLevel);
-  void parseConstraintExpression(unsigned int OriginalLevel);
+  void parseRequiresClause();
+  void parseRequiresExpression();
+  void parseConstraintExpression();
   void parseJavaEnumBody();
   // Parses a record (aka class) as a top level element. If ParseAsExpr is true,
   // parses the record as a child block, i.e. if the class declaration is an
Index: clang/lib/Format/UnwrappedLineParser.cpp
===================================================================
--- clang/lib/Format/UnwrappedLineParser.cpp
+++ clang/lib/Format/UnwrappedLineParser.cpp
@@ -373,7 +373,7 @@
   if (Style.Language == FormatStyle::LK_TextProto)
     parseBracedList();
   else
-    parseLevel(/*HasOpeningBrace=*/false);
+    parseLevel(/*HasOpeningBrace=*/false, /*CanContainBracedList=*/true);
   // Make sure to format the remaining tokens.
   //
   // LK_TextProto is special since its top-level is parsed as the body of a
@@ -432,7 +432,17 @@
   } while (!eof());
 }
 
-void UnwrappedLineParser::parseLevel(bool HasOpeningBrace) {
+/// \brief Parses a level, that is ???.
+/// \param HasOpeningBrace If that level is started by an opening brace.
+/// \param CanContainBracedList If the content can contain (at any level) a
+/// braced list.
+/// \param NextLBracesType The type for left brace found in this level.
+void UnwrappedLineParser::parseLevel(bool HasOpeningBrace,
+                                     bool CanContainBracedList,
+                                     TokenType NextLBracesType) {
+  auto NextLevelLBracesType = NextLBracesType == TT_CompoundRequirementLBrace
+                                  ? TT_BracedListLBrace
+                                  : TT_Unknown;
   bool SwitchLabelEncountered = false;
   do {
     tok::TokenKind kind = FormatTok->Tok.getKind();
@@ -448,11 +458,15 @@
       addUnwrappedLine();
       break;
     case tok::l_brace:
-      // FIXME: Add parameter whether this can happen - if this happens, we must
-      // be in a non-declaration context.
-      if (!FormatTok->is(TT_MacroBlockBegin) && tryToParseBracedList())
+      if (NextLBracesType != TT_Unknown)
+        FormatTok->setType(NextLBracesType);
+      if (CanContainBracedList && !FormatTok->is(TT_MacroBlockBegin) &&
+          tryToParseBracedList())
         continue;
-      parseBlock();
+      parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
+                 /*MunchSemi=*/true, /*UnindentWhitesmithBraces=*/false,
+                 CanContainBracedList,
+                 /*NextLBracesType=*/NextLBracesType);
       addUnwrappedLine();
       break;
     case tok::r_brace:
@@ -498,7 +512,8 @@
       }
       LLVM_FALLTHROUGH;
     default:
-      parseStructuralElement(!HasOpeningBrace);
+      parseStructuralElement(/*IsTopLevel=*/!HasOpeningBrace,
+                             /*NextLBracesType=*/NextLevelLBracesType);
       break;
     }
   } while (!eof());
@@ -572,27 +587,47 @@
           bool NextIsObjCMethod = NextTok->isOneOf(tok::plus, tok::minus) &&
                                   NextTok->OriginalColumn == 0;
 
+          // Try to detect a braced list. Note that regardless how we mark inner
+          // braces here, we will overwrite the BlockKind later if we parse a
+          // braced list (where all blocks inside are by default braced lists),
+          // or when we explicitly detect blocks (for example while parsing
+          // lambdas).
+
+          // If we already marked the opening brace as braced list, the closing
+          // must also be part of it.
+          ProbablyBracedList = LBraceStack.back()->is(TT_BracedListLBrace);
+
+          ProbablyBracedList = ProbablyBracedList ||
+                               (Style.Language == FormatStyle::LK_JavaScript &&
+                                NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
+                                                 Keywords.kw_as));
+          ProbablyBracedList =
+              ProbablyBracedList ||
+              (Style.isCpp() && NextTok->is(tok::l_paren));
+
           // If there is a comma, semicolon or right paren after the closing
-          // brace, we assume this is a braced initializer list.  Note that
-          // regardless how we mark inner braces here, we will overwrite the
-          // BlockKind later if we parse a braced list (where all blocks
-          // inside are by default braced lists), or when we explicitly detect
-          // blocks (for example while parsing lambdas).
+          // brace, we assume this is a braced initializer list.
           // FIXME: Some of these do not apply to JS, e.g. "} {" can never be a
           // braced list in JS.
           ProbablyBracedList =
-              (Style.Language == FormatStyle::LK_JavaScript &&
-               NextTok->isOneOf(Keywords.kw_of, Keywords.kw_in,
-                                Keywords.kw_as)) ||
-              (Style.isCpp() && NextTok->is(tok::l_paren)) ||
+              ProbablyBracedList ||
               NextTok->isOneOf(tok::comma, tok::period, tok::colon,
                                tok::r_paren, tok::r_square, tok::l_brace,
-                               tok::ellipsis) ||
+                               tok::ellipsis);
+
+          ProbablyBracedList =
+              ProbablyBracedList ||
               (NextTok->is(tok::identifier) &&
-               !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace)) ||
-              (NextTok->is(tok::semi) &&
-               (!ExpectClassBody || LBraceStack.size() != 1)) ||
+               !PrevTok->isOneOf(tok::semi, tok::r_brace, tok::l_brace));
+
+          ProbablyBracedList = ProbablyBracedList ||
+                               (NextTok->is(tok::semi) &&
+                                (!ExpectClassBody || LBraceStack.size() != 1));
+
+          ProbablyBracedList =
+              ProbablyBracedList ||
               (NextTok->isBinaryOperator() && !NextIsObjCMethod);
+
           if (!Style.isCSharp() && NextTok->is(tok::l_square)) {
             // We can have an array subscript after a braced init
             // list, but C++11 attributes are expected after blocks.
@@ -659,7 +694,9 @@
 
 void UnwrappedLineParser::parseBlock(bool MustBeDeclaration, unsigned AddLevels,
                                      bool MunchSemi,
-                                     bool UnindentWhitesmithsBraces) {
+                                     bool UnindentWhitesmithsBraces,
+                                     bool CanContainBracedList,
+                                     TokenType NextLBracesType) {
   assert(FormatTok->isOneOf(tok::l_brace, TT_MacroBlockBegin) &&
          "'{' or macro block token expected");
   const bool MacroBlock = FormatTok->is(TT_MacroBlockBegin);
@@ -696,7 +733,7 @@
                                           MustBeDeclaration);
   if (AddLevels > 0u && Style.BreakBeforeBraces != FormatStyle::BS_Whitesmiths)
     Line->Level += AddLevels;
-  parseLevel(/*HasOpeningBrace=*/true);
+  parseLevel(/*HasOpeningBrace=*/true, CanContainBracedList, NextLBracesType);
 
   if (eof())
     return;
@@ -716,8 +753,12 @@
   if (MacroBlock && FormatTok->is(tok::l_paren))
     parseParens();
 
+  if (FormatTok->is(tok::kw_noexcept))
+    // A noexcept in a requires expression.
+    nextToken();
+
   if (FormatTok->is(tok::arrow)) {
-    // Following the } we can find a trailing return type arrow
+    // Following the } or noexcept we can find a trailing return type arrow
     // as part of an implicit conversion constraint.
     nextToken();
     parseStructuralElement();
@@ -797,7 +838,7 @@
     ScopedDeclarationState DeclarationState(*Line, DeclarationScopeStack,
                                             /*MustBeDeclaration=*/false);
     Line->Level += SkipIndent ? 0 : 1;
-    parseLevel(/*HasOpeningBrace=*/true);
+    parseLevel(/*HasOpeningBrace=*/true, /*CanContainBracedList=*/true);
     flushComments(isOnNewLine(*FormatTok));
     Line->Level -= SkipIndent ? 0 : 1;
   }
@@ -1189,7 +1230,8 @@
     return addUnwrappedLine();
 }
 
-void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel) {
+void UnwrappedLineParser::parseStructuralElement(bool IsTopLevel,
+                                                 TokenType NextLBracesType) {
   if (Style.Language == FormatStyle::LK_TableGen &&
       FormatTok->is(tok::pp_include)) {
     nextToken();
@@ -1439,7 +1481,7 @@
       parseConcept();
       break;
     case tok::kw_requires:
-      parseRequires();
+      parseRequiresClause();
       break;
     case tok::kw_enum:
       // Ignore if this is part of "template <enum ...".
@@ -1520,6 +1562,8 @@
         parseChildBlock();
       break;
     case tok::l_brace:
+      if (NextLBracesType != TT_Unknown)
+        FormatTok->setType(NextLBracesType);
       if (!tryToParsePropertyAccessor() && !tryToParseBracedList()) {
         // A block outside of parentheses must be the last part of a
         // structural element.
@@ -2063,7 +2107,10 @@
   return false;
 }
 
-void UnwrappedLineParser::parseParens() {
+/// \brief Parses a parens pair.
+/// \param AmpAmpTokenType If different than TT_Unknown sets this type for all
+/// double ampersands. This only counts for the current parens scope.
+void UnwrappedLineParser::parseParens(TokenType AmpAmpTokenType) {
   assert(FormatTok->Tok.is(tok::l_paren) && "'(' expected.");
   nextToken();
   do {
@@ -2113,6 +2160,13 @@
       else
         nextToken();
       break;
+    case tok::kw_requires:
+      parseRequiresExpression();
+      break;
+    case tok::ampamp:
+      if (AmpAmpTokenType != TT_Unknown)
+        FormatTok->setType(AmpAmpTokenType);
+      LLVM_FALLTHROUGH;
     default:
       nextToken();
       break;
@@ -2522,6 +2576,11 @@
   addUnwrappedLine();
 }
 
+/// \brief Parses a concept definition.
+/// \pre The current token has to be the concept keyword.
+///
+/// Returns if it either has finished parsing the concept, or it detects, that
+/// the concept definition is incorrect.
 void UnwrappedLineParser::parseConcept() {
   assert(FormatTok->Tok.is(tok::kw_concept) && "'concept' expected");
   nextToken();
@@ -2531,107 +2590,168 @@
   if (!FormatTok->Tok.is(tok::equal))
     return;
   nextToken();
-  if (FormatTok->Tok.is(tok::kw_requires)) {
+  parseConstraintExpression();
+  if (FormatTok->Tok.is(tok::semi))
     nextToken();
-    parseRequiresExpression(Line->Level);
-  } else {
-    parseConstraintExpression(Line->Level);
+  addUnwrappedLine();
+}
+
+/// \brief Parses a requires clause.
+/// \pre The current token needs to be the requires keyword.
+/// \sa parseRequiresExpression
+///
+/// Returns if it either has finished parsing the clause, or it detects, that
+/// the clause is incorrect.
+void UnwrappedLineParser::parseRequiresClause() {
+  assert(FormatTok->Tok.is(tok::kw_requires) && "'requires' expected");
+  assert(FormatTok->getType() == TT_Unknown);
+
+  auto RequiresToken = FormatTok;
+
+  nextToken();
+  parseConstraintExpression();
+
+  auto setTypeAndMaybeAddLine =
+      [this,
+       RequiresToken](TokenType Type,
+                      FormatStyle::RequiresClausePositionStyle PositionStyle) {
+        RequiresToken->setType(Type);
+
+        switch (PositionStyle) {
+        case FormatStyle::RCPS_OwnLine:
+        case FormatStyle::RCPS_ToPreceeding:
+        case FormatStyle::RCPS_TwoLines:
+          addUnwrappedLine();
+          break;
+        default:
+          break;
+        }
+      };
+
+  switch (FormatTok->Tok.getKind()) {
+  case tok::kw_class:
+  case tok::kw_struct:
+  case tok::kw_union:
+    setTypeAndMaybeAddLine(TT_RequiresClauseForClasses,
+                           Style.RequiresClausePositionForClasses);
+    break;
+
+  case tok::semi:
+    if (RequiresToken->Previous)
+      // We are a trailing requires clause for a function.
+      RequiresToken->setType(TT_RequiresClauseForFunctions);
+    // Else: We are a requires clause within a requires expression.
+    // The Semi is eaten by the caller, he also adds the unwrapped line.
+    break;
+
+  default:
+    setTypeAndMaybeAddLine(TT_RequiresClauseForFunctions,
+                           Style.RequiresClausePositionForFunctions);
+    break;
   }
 }
 
-void UnwrappedLineParser::parseRequiresExpression(unsigned int OriginalLevel) {
-  // requires (R range)
-  if (FormatTok->Tok.is(tok::l_paren)) {
+/// \brief Parses a requires expression.
+/// \pre The current token needs to be the requires keyword.
+/// \sa parseRequiresClause
+///
+/// Returns if it either has finished parsing the expression, or it detects,
+/// that the expression is incorrect.
+void UnwrappedLineParser::parseRequiresExpression() {
+  assert(FormatTok->Tok.is(tok::kw_requires) && "'requires' expected");
+  assert(FormatTok->getType() == TT_Unknown);
+  nextToken();
+
+  if (FormatTok->is(tok::l_paren))
     parseParens();
-    if (Style.IndentRequires && OriginalLevel != Line->Level) {
-      addUnwrappedLine();
-      --Line->Level;
-    }
-  }
 
-  if (FormatTok->Tok.is(tok::l_brace)) {
-    if (Style.BraceWrapping.AfterFunction)
-      addUnwrappedLine();
-    FormatTok->setType(TT_FunctionLBrace);
-    parseBlock();
-    addUnwrappedLine();
-  } else {
-    parseConstraintExpression(OriginalLevel);
-  }
+  if (FormatTok->is(tok::l_brace))
+    parseBlock(/*MustBeDeclaration=*/false, /*AddLevels=*/1u,
+               /*MunchSemi=*/false, /*UnindentWhitesmithsBraces=*/false,
+               /*CanContainBracedList=*/false,
+               /*NextLBracesType=*/TT_CompoundRequirementLBrace);
 }
 
-void UnwrappedLineParser::parseConstraintExpression(
-    unsigned int OriginalLevel) {
-  // requires Id<T> && Id<T> || Id<T>
-  while (
-      FormatTok->isOneOf(tok::identifier, tok::kw_requires, tok::coloncolon)) {
-    nextToken();
-    while (FormatTok->isOneOf(tok::identifier, tok::coloncolon, tok::less,
-                              tok::greater, tok::comma, tok::ellipsis)) {
-      if (FormatTok->Tok.is(tok::less)) {
+/// \brief Parses a constraint expression.
+///
+/// This is either the definition of a concept, or the body of a requires
+/// clause. It returns, when the parsing is complete, or the expression is
+/// incorrect.
+void UnwrappedLineParser::parseConstraintExpression() {
+  do {
+    switch (FormatTok->Tok.getKind()) {
+    case tok::kw_requires:
+      parseRequiresExpression();
+      break;
+
+    case tok::l_paren:
+      parseParens(/*AmpAmpTokenType=*/TT_BinaryOperator);
+      break;
+
+    case tok::l_square:
+      if (!tryToParseLambda())
+        return;
+      break;
+
+    case tok::identifier:
+      // Read identifier with optional template declaration.
+      nextToken();
+      if (FormatTok->Tok.is(tok::less))
         parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
                         /*ClosingBraceKind=*/tok::greater);
-        continue;
-      }
+      break;
+
+    case tok::semi:
+    case tok::kw_class:
+    case tok::kw_struct:
+    case tok::kw_union:
+      return;
+
+    case tok::l_brace:
+      // Potential function body.
+      return;
+
+    case tok::ampamp:
+      FormatTok->setType(TT_BinaryOperator);
       nextToken();
-    }
-    if (FormatTok->Tok.is(tok::kw_requires)) {
-      parseRequiresExpression(OriginalLevel);
-    }
-    if (FormatTok->Tok.is(tok::less)) {
-      parseBracedList(/*ContinueOnSemicolons=*/false, /*IsEnum=*/false,
-                      /*ClosingBraceKind=*/tok::greater);
-    }
+      break;
 
-    if (FormatTok->Tok.is(tok::l_paren)) {
-      parseParens();
-    }
-    if (FormatTok->Tok.is(tok::l_brace)) {
-      if (Style.BraceWrapping.AfterFunction)
-        addUnwrappedLine();
-      FormatTok->setType(TT_FunctionLBrace);
-      parseBlock();
-    }
-    if (FormatTok->Tok.is(tok::semi)) {
-      // Eat any trailing semi.
+    default:
+      // Just eat them.
       nextToken();
-      addUnwrappedLine();
-    }
-    if (FormatTok->Tok.is(tok::colon)) {
-      return;
-    }
-    if (!FormatTok->Tok.isOneOf(tok::ampamp, tok::pipepipe)) {
-      if (FormatTok->Previous &&
-          !FormatTok->Previous->isOneOf(tok::identifier, tok::kw_requires,
-                                        tok::coloncolon)) {
-        addUnwrappedLine();
-      }
-      if (Style.IndentRequires && OriginalLevel != Line->Level) {
-        --Line->Level;
-      }
       break;
-    } else {
-      FormatTok->setType(TT_ConstraintJunctions);
     }
-
-    nextToken();
-  }
+  } while (!eof());
 }
 
-void UnwrappedLineParser::parseRequires() {
+/*void UnwrappedLineParser::parseRequires() {
   assert(FormatTok->Tok.is(tok::kw_requires) && "'requires' expected");
 
   unsigned OriginalLevel = Line->Level;
-  if (FormatTok->Previous && FormatTok->Previous->is(tok::greater)) {
-    addUnwrappedLine();
-    if (Style.IndentRequires) {
-      Line->Level++;
+  bool IsClause = false;
+  if (FormatTok->Previous) {
+    if (FormatTok->Previous->is(tok::greater)) {
+      FormatTok->setType(TT_RequiresClause);
+      IsClause = true;
+      addUnwrappedLine();
+      if (Style.IndentRequires) {
+        Line->Level++;
+      }
+    } else if (FormatTok->Previous->is(tok::r_paren)) {
+      FormatTok->setType(TT_RequiresClause);
+      IsClause = true;
     }
   }
+  if (!IsClause)
+    FormatTok->setType(TT_RequiresExpression);
+
   nextToken();
 
-  parseRequiresExpression(OriginalLevel);
-}
+  if (IsClause)
+    parseRequiresClause(OriginalLevel);
+  else
+    parseRequiresExpression(OriginalLevel);
+}*/
 
 bool UnwrappedLineParser::parseEnum() {
   // Won't be 'enum' for NS_ENUMs.
@@ -2830,7 +2950,7 @@
   }
 
   // Parse the class body after the enum's ";" if any.
-  parseLevel(/*HasOpeningBrace=*/true);
+  parseLevel(/*HasOpeningBrace=*/true, /*CanContainBracedList=*/true);
   nextToken();
   --Line->Level;
   addUnwrappedLine();
Index: clang/lib/Format/TokenAnnotator.cpp
===================================================================
--- clang/lib/Format/TokenAnnotator.cpp
+++ clang/lib/Format/TokenAnnotator.cpp
@@ -251,7 +251,9 @@
       Contexts.back().IsExpression = false;
     } else if (Left->Previous &&
                (Left->Previous->isOneOf(tok::kw_static_assert, tok::kw_while,
-                                        tok::l_paren, tok::comma) ||
+                                        tok::l_paren, tok::comma,
+                                        TT_RequiresClauseForClasses,
+                                        TT_RequiresClauseForFunctions) ||
                 Left->Previous->isIf() ||
                 Left->Previous->is(TT_BinaryOperator))) {
       // static_assert, if and while usually contain expressions.
@@ -1162,6 +1164,10 @@
         parseCSharpGenericTypeConstraint();
       }
       break;
+    case tok::arrow:
+      if (Tok->Previous && Tok->Previous->is(tok::kw_noexcept))
+        Tok->setType(TT_TrailingReturnArrow);
+      break;
     default:
       break;
     }
@@ -1425,8 +1431,10 @@
             TT_ImplicitStringLiteral, TT_InlineASMBrace, TT_FatArrow,
             TT_LambdaArrow, TT_NamespaceMacro, TT_OverloadedOperator,
             TT_RegexLiteral, TT_TemplateString, TT_ObjCStringLiteral,
-            TT_UntouchableMacroFunc, TT_ConstraintJunctions,
-            TT_StatementAttributeLikeMacro))
+            TT_UntouchableMacroFunc, TT_StatementAttributeLikeMacro,
+            TT_RequiresClauseForClasses, TT_RequiresClauseForFunctions,
+            TT_BinaryOperator, TT_CompoundRequirementLBrace,
+            TT_BracedListLBrace))
       CurrentToken->setType(TT_Unknown);
     CurrentToken->Role.reset();
     CurrentToken->MatchingParen = nullptr;
@@ -2136,7 +2144,7 @@
 public:
   ExpressionParser(const FormatStyle &Style, const AdditionalKeywords &Keywords,
                    AnnotatedLine &Line)
-      : Style(Style), Keywords(Keywords), Current(Line.First) {}
+      : Style(Style), Keywords(Keywords), Line(Line), Current(Line.First) {}
 
   /// Parse expressions with the given operator precedence.
   void parse(int Precedence = 0) {
@@ -2192,7 +2200,11 @@
       }
 
       // Consume scopes: (), [], <> and {}
-      if (Current->opensScope()) {
+      // In addition to that we handle require clauses as scope, so that the
+      // constraints in that are correctly indented.
+      if (Current->opensScope() ||
+          Current->isOneOf(TT_RequiresClauseForClasses,
+                           TT_RequiresClauseForFunctions)) {
         // In fragment of a JavaScript template string can look like '}..${' and
         // thus close a scope and open a new one at the same time.
         while (Current && (!Current->closesScope() || Current->opensScope())) {
@@ -2214,12 +2226,25 @@
     }
 
     if (LatestOperator && (Current || Precedence > 0)) {
-      // LatestOperator->LastOperator = true;
+      // The requires clauses do not neccessarily end in a semicolon or a brace,
+      // but just go over to struct/class or a function declaration, we need to
+      // intervene so that the fake right paren is inserted correctly.
+      auto End = (!Current && Start->Previous &&
+                  Start->Previous->isOneOf(TT_RequiresClauseForClasses,
+                                           TT_RequiresClauseForFunctions))
+                     ? [this](){
+                         auto Ret = Line.Last;
+                         while (Ret->is(tok::comment) && Ret->Previous)
+                           Ret = Ret->Previous;
+                         return Ret;
+                       }()
+                     : nullptr;
+
       if (Precedence == PrecedenceArrowAndPeriod) {
         // Call expressions don't have a binary operator precedence.
-        addFakeParenthesis(Start, prec::Unknown);
+        addFakeParenthesis(Start, prec::Unknown, End);
       } else {
-        addFakeParenthesis(Start, prec::Level(Precedence));
+        addFakeParenthesis(Start, prec::Level(Precedence), End);
       }
     }
   }
@@ -2270,17 +2295,17 @@
     return -1;
   }
 
-  void addFakeParenthesis(FormatToken *Start, prec::Level Precedence) {
+  void addFakeParenthesis(FormatToken *Start, prec::Level Precedence,
+                          FormatToken *End = nullptr) {
     Start->FakeLParens.push_back(Precedence);
     if (Precedence > prec::Unknown)
       Start->StartsBinaryExpression = true;
-    if (Current) {
-      FormatToken *Previous = Current->Previous;
-      while (Previous->is(tok::comment) && Previous->Previous)
-        Previous = Previous->Previous;
-      ++Previous->FakeRParens;
+    if (!End && Current)
+      End = Current->getPreviousNonComment();
+    if (End) {
+      ++End->FakeRParens;
       if (Precedence > prec::Unknown)
-        Previous->EndsBinaryExpression = true;
+        End->EndsBinaryExpression = true;
     }
   }
 
@@ -2326,6 +2351,7 @@
 
   const FormatStyle &Style;
   const AdditionalKeywords &Keywords;
+  const AnnotatedLine &Line;
   FormatToken *Current;
 };
 
@@ -2959,9 +2985,6 @@
   if (Left.isOneOf(tok::kw_co_await, tok::kw_co_yield, tok::kw_co_return) &&
       Right.isNot(tok::semi))
     return true;
-  // requires clause Concept1<T> && Concept2<T>
-  if (Left.is(TT_ConstraintJunctions) && Right.is(tok::identifier))
-    return true;
 
   if (Left.is(tok::l_paren) || Right.is(tok::r_paren))
     return (Right.is(TT_CastRParen) ||
@@ -3832,6 +3855,28 @@
     // concept ...
     if (Right.is(tok::kw_concept))
       return Style.BreakBeforeConceptDeclarations;
+
+    if (Right.is(TT_RequiresClauseForClasses)) {
+      switch (Style.RequiresClausePositionForClasses) {
+      case FormatStyle::RCPS_OwnLine:
+      case FormatStyle::RCPS_ToFollowing:
+      case FormatStyle::RCPS_TwoLines:
+        return true;
+      default:
+        break;
+      }
+    }
+
+    if (Right.is(TT_RequiresClauseForFunctions)) {
+      switch (Style.RequiresClausePositionForFunctions) {
+      case FormatStyle::RCPS_OwnLine:
+      case FormatStyle::RCPS_ToFollowing:
+      case FormatStyle::RCPS_TwoLines:
+        return true;
+      default:
+        break;
+      }
+    }
     return (Style.AlwaysBreakTemplateDeclarations == FormatStyle::BTDS_Yes);
   }
   if (Style.PackConstructorInitializers == FormatStyle::PCIS_Never) {
@@ -4043,6 +4088,13 @@
       return true;
   }
 
+  if (Left.is(TT_RequiresClauseForClasses))
+    return Style.RequiresClausePositionForClasses == FormatStyle::RCPS_TwoLines;
+
+  if (Left.is(TT_RequiresClauseForFunctions))
+    return Style.RequiresClausePositionForFunctions ==
+           FormatStyle::RCPS_TwoLines;
+
   return false;
 }
 
Index: clang/lib/Format/FormatToken.h
===================================================================
--- clang/lib/Format/FormatToken.h
+++ clang/lib/Format/FormatToken.h
@@ -35,12 +35,13 @@
   TYPE(BinaryOperator)                                                         \
   TYPE(BitFieldColon)                                                          \
   TYPE(BlockComment)                                                           \
+  TYPE(BracedListLBrace)                                                       \
   TYPE(CastRParen)                                                             \
+  TYPE(CompoundRequirementLBrace)                                              \
   TYPE(ConditionalExpr)                                                        \
   TYPE(ConflictAlternative)                                                    \
   TYPE(ConflictEnd)                                                            \
   TYPE(ConflictStart)                                                          \
-  TYPE(ConstraintJunctions)                                                    \
   TYPE(CtorInitializerColon)                                                   \
   TYPE(CtorInitializerComma)                                                   \
   TYPE(DesignatedInitializerLSquare)                                           \
@@ -96,6 +97,8 @@
   TYPE(PureVirtualSpecifier)                                                   \
   TYPE(RangeBasedForLoopColon)                                                 \
   TYPE(RegexLiteral)                                                           \
+  TYPE(RequiresClauseForClasses)                                               \
+  TYPE(RequiresClauseForFunctions)                                             \
   TYPE(SelectorName)                                                           \
   TYPE(StartOfName)                                                            \
   TYPE(StatementAttributeLikeMacro)                                            \
Index: clang/lib/Format/Format.cpp
===================================================================
--- clang/lib/Format/Format.cpp
+++ clang/lib/Format/Format.cpp
@@ -450,6 +450,18 @@
   }
 };
 
+template <>
+struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
+  static void enumeration(IO &IO,
+                          FormatStyle::RequiresClausePositionStyle &Value) {
+    IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
+    IO.enumCase(Value, "ToPreceeding", FormatStyle::RCPS_ToPreceeding);
+    IO.enumCase(Value, "ToFollowing", FormatStyle::RCPS_ToFollowing);
+    IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
+    IO.enumCase(Value, "TwoLines", FormatStyle::RCPS_TwoLines);
+  }
+};
+
 template <>
 struct ScalarEnumerationTraits<FormatStyle::SpaceBeforeParensStyle> {
   static void enumeration(IO &IO, FormatStyle::SpaceBeforeParensStyle &Value) {
@@ -769,6 +781,10 @@
     IO.mapOptional("RawStringFormats", Style.RawStringFormats);
     IO.mapOptional("ReferenceAlignment", Style.ReferenceAlignment);
     IO.mapOptional("ReflowComments", Style.ReflowComments);
+    IO.mapOptional("RequiresClausePositionForClasses",
+                   Style.RequiresClausePositionForClasses);
+    IO.mapOptional("RequiresClausePositionForFunctions",
+                   Style.RequiresClausePositionForFunctions);
     IO.mapOptional("ShortNamespaceLines", Style.ShortNamespaceLines);
     IO.mapOptional("SortIncludes", Style.SortIncludes);
     IO.mapOptional("SortJavaStaticImport", Style.SortJavaStaticImport);
@@ -1193,6 +1209,9 @@
   LLVMStyle.ObjCSpaceBeforeProtocolList = true;
   LLVMStyle.PointerAlignment = FormatStyle::PAS_Right;
   LLVMStyle.ReferenceAlignment = FormatStyle::RAS_Pointer;
+  // This is open for discussions! When will LLVM adapt C++20?
+  LLVMStyle.RequiresClausePositionForClasses = FormatStyle::RCPS_OwnLine;
+  LLVMStyle.RequiresClausePositionForFunctions = FormatStyle::RCPS_OwnLine;
   LLVMStyle.ShortNamespaceLines = 1;
   LLVMStyle.SpacesBeforeTrailingComments = 1;
   LLVMStyle.Standard = FormatStyle::LS_Latest;
Index: clang/lib/Format/ContinuationIndenter.cpp
===================================================================
--- clang/lib/Format/ContinuationIndenter.cpp
+++ clang/lib/Format/ContinuationIndenter.cpp
@@ -800,6 +800,18 @@
 
   State.Column = getNewLineColumn(State);
 
+  if (Current.is(TT_RequiresClauseForClasses)) {
+    State.Stack.back().Indent = State.Column;
+    if (Style.RequiresClausePositionForClasses == FormatStyle::RCPS_TwoLines)
+      State.Stack.back().Indent += Current.ColumnWidth;
+  }
+
+  if (Current.is(TT_RequiresClauseForFunctions)) {
+    State.Stack.back().Indent = State.Column;
+    if (Style.RequiresClausePositionForFunctions == FormatStyle::RCPS_TwoLines)
+      State.Stack.back().Indent += Current.ColumnWidth;
+  }
+
   // Add Penalty proportional to amount of whitespace away from FirstColumn
   // This tends to penalize several lines that are far-right indented,
   // and prefers a line-break prior to such a block, e.g:
@@ -1086,6 +1098,10 @@
   }
   if (Previous.is(tok::comma) && State.Stack.back().VariablePos != 0)
     return State.Stack.back().VariablePos;
+  if (Current.isOneOf(TT_RequiresClauseForClasses,
+                      TT_RequiresClauseForFunctions) &&
+      Style.IndentRequires)
+    return State.Stack.back().Indent + Style.IndentWidth;
   if ((PreviousNonComment &&
        (PreviousNonComment->ClosesTemplateDeclaration ||
         PreviousNonComment->isOneOf(
@@ -1343,11 +1359,13 @@
   const FormatToken *Previous = Current.getPreviousNonComment();
 
   // Don't add extra indentation for the first fake parenthesis after
-  // 'return', assignments or opening <({[. The indentation for these cases
-  // is special cased.
+  // 'return', assignments, opening <({[, or requires clauses. The indentation
+  // for these cases is special cased.
   bool SkipFirstExtraIndent =
       (Previous && (Previous->opensScope() ||
-                    Previous->isOneOf(tok::semi, tok::kw_return) ||
+                    Previous->isOneOf(tok::semi, tok::kw_return,
+                                      TT_RequiresClauseForClasses,
+                                      TT_RequiresClauseForFunctions) ||
                     (Previous->getPrecedence() == prec::Assignment &&
                      Style.AlignOperands != FormatStyle::OAS_DontAlign) ||
                     Previous->is(TT_ObjCMethodExpr)));
@@ -1383,7 +1401,8 @@
 
     if (Previous &&
         (Previous->getPrecedence() == prec::Assignment ||
-         Previous->is(tok::kw_return) ||
+         Previous->isOneOf(tok::kw_return, TT_RequiresClauseForClasses,
+                           TT_RequiresClauseForFunctions) ||
          (PrecedenceLevel == prec::Conditional && Previous->is(tok::question) &&
           Previous->is(TT_ConditionalExpr))) &&
         !Newline) {
Index: clang/include/clang/Format/Format.h
===================================================================
--- clang/include/clang/Format/Format.h
+++ clang/include/clang/Format/Format.h
@@ -2501,7 +2501,8 @@
   /// \version 12
   IndentExternBlockStyle IndentExternBlock;
 
-  /// Indent the requires clause in a template
+  /// Indent the requires clause in a template, this only applies if the
+  /// ``requires`` is at the beginning of a line.
   /// \code
   ///    true:
   ///    template <typename It>
@@ -3049,6 +3050,91 @@
   bool ReflowComments;
   // clang-format on
 
+  /// \brief The possible positions for the requires clause. The
+  /// ``IndentRequires`` option is only used if the ``requires`` is put on the
+  /// start of a line.
+  enum RequiresClausePositionStyle {
+    /// The clause always gets its own line.
+    /// \code
+    ///   template<typename T>
+    ///   requires C<T>
+    ///   struct Foo {...
+    ///
+    ///   template<typename T>
+    ///   requires C<T>
+    ///   void bar(T t) {...
+    ///
+    ///   template<typename T>
+    ///   void baz(T t)
+    ///   requires C<T> {...
+    /// \endcode
+    RCPS_OwnLine,
+    /// The clause tries to stick to the template declaration in case of class
+    /// templates or between template and function delcarations. In case of
+    /// after the function delcaration it tries to stick to this.
+    /// \code
+    ///   template<typename T> requires C<T>
+    ///   struct Foo {...
+    ///
+    ///   template<typename T> requires C<T>
+    ///   void bar(T t) {...
+    ///
+    ///   template<typename T>
+    ///   void baz(T t) requires C<T> {...
+    /// \endcode
+    RCPS_ToPreceeding,
+    /// The clause tries to stick to the class respectively function
+    /// declaration.
+    /// \code
+    ///   template<typename T>
+    ///   requires C<T> struct Foo {...
+    ///
+    ///   template<typename T>
+    ///   requires C<T> void bar(T t) {...
+    ///
+    ///   template<typename T>
+    ///   void baz(T t) requires C<T> {...
+    /// \endcode
+    RCPS_ToFollowing,
+    /// The clause tries to get everything in the same line, if it doesn't fit
+    /// normal line breaking rules decide to which part it sticks.
+    /// \code
+    ///   template<typename T> requires C<T> struct Foo {...
+    ///
+    ///   template<typename T> requires C<T> void bar(T t) {...
+    ///
+    ///   template<typename T> void bar(T t) requires C<T> {...
+    /// \endcode
+    RCPS_SingleLine,
+    /// The clause always gets its own line, and the content of the clause go
+    /// into the next line with some indentation.
+    /// \code
+    ///   template<typename T>
+    ///   requires
+    ///           C<T>
+    ///   struct Foo {...
+    ///
+    ///   template<typename T>
+    ///   requires
+    ///           C<T>
+    ///   void bar(T t) {...
+    ///
+    ///   template<typename T>
+    ///   void bar(T t)
+    ///   requires
+    ///           C<T> {...
+    /// \endcode
+    RCPS_TwoLines,
+  };
+
+  /// \brief The position of the ``requires`` clause for class templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForClasses;
+
+  /// \brief The position of the ``requires`` clause for function templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForFunctions;
+
   /// The maximal number of unwrapped lines that a short namespace spans.
   /// Defaults to 1.
   ///
@@ -3790,6 +3876,10 @@
            QualifierOrder == R.QualifierOrder &&
            RawStringFormats == R.RawStringFormats &&
            ReferenceAlignment == R.ReferenceAlignment &&
+           RequiresClausePositionForClasses ==
+               R.RequiresClausePositionForClasses &&
+           RequiresClausePositionForFunctions ==
+               R.RequiresClausePositionForFunctions &&
            ShortNamespaceLines == R.ShortNamespaceLines &&
            SortIncludes == R.SortIncludes &&
            SortJavaStaticImport == R.SortJavaStaticImport &&
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -267,6 +267,10 @@
 
 - Improved C++20 Modules and Coroutines support.
 
+- Reworked and improved handling of concepts and requires. Added the
+  ``RequiresClausePositionForClasses`` and
+  ``RequiresClausePositionForFunctions`` options as part of that.
+
 libclang
 --------
 
Index: clang/docs/ClangFormatStyleOptions.rst
===================================================================
--- clang/docs/ClangFormatStyleOptions.rst
+++ clang/docs/ClangFormatStyleOptions.rst
@@ -2671,7 +2671,8 @@
 
 
 **IndentRequires** (``Boolean``) :versionbadge:`clang-format 13`
-  Indent the requires clause in a template
+  Indent the requires clause in a template, this only applies if the
+  ``requires`` is at the beginning of a line.
 
   .. code-block:: c++
 
@@ -3236,7 +3237,7 @@
 **QualifierAlignment** (``QualifierAlignmentStyle``) :versionbadge:`clang-format 14`
   Different ways to arrange specifiers and qualifiers (e.g. const/volatile).
 
-  .. warning::
+  .. warning:: 
 
    Setting ``QualifierAlignment``  to something other than `Leave`, COULD
    lead to incorrect code formatting due to incorrect decisions made due to
@@ -3395,6 +3396,182 @@
      /* second veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of
       * information */
 
+**RequiresClausePositionForClasses** (``RequiresClausePositionStyle``) :versionbadge:`clang-format 14`
+  The position of the ``requires`` clause for class templates.
+
+  Possible values:
+
+  * ``RCPS_OwnLine`` (in configuration: ``OwnLine``)
+    The clause always gets its own line.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires C<T>
+      struct Foo {...
+
+      template<typename T>
+      requires C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void baz(T t)
+      requires C<T> {...
+
+  * ``RCPS_ToPreceeding`` (in configuration: ``ToPreceeding``)
+    The clause tries to stick to the template declaration in case of class
+    templates or between template and function delcarations. In case of
+    after the function delcaration it tries to stick to this.
+
+    .. code-block:: c++
+
+      template<typename T> requires C<T>
+      struct Foo {...
+
+      template<typename T> requires C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void baz(T t) requires C<T> {...
+
+  * ``RCPS_ToFollowing`` (in configuration: ``ToFollowing``)
+    The clause tries to stick to the class respectively function
+    declaration.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires C<T> struct Foo {...
+
+      template<typename T>
+      requires C<T> void bar(T t) {...
+
+      template<typename T>
+      void baz(T t) requires C<T> {...
+
+  * ``RCPS_SingleLine`` (in configuration: ``SingleLine``)
+    The clause tries to get everything in the same line, if it doesn't fit
+    normal line breaking rules decide to which part it sticks.
+
+    .. code-block:: c++
+
+      template<typename T> requires C<T> struct Foo {...
+
+      template<typename T> requires C<T> void bar(T t) {...
+
+      template<typename T> void bar(T t) requires C<T> {...
+
+  * ``RCPS_TwoLines`` (in configuration: ``TwoLines``)
+    The clause always gets its own line, and the content of the clause go
+    into the next line with some indentation.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires
+              C<T>
+      struct Foo {...
+
+      template<typename T>
+      requires
+              C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void bar(T t)
+      requires
+              C<T> {...
+
+
+
+**RequiresClausePositionForFunctions** (``RequiresClausePositionStyle``) :versionbadge:`clang-format 14`
+  The position of the ``requires`` clause for function templates.
+
+  Possible values:
+
+  * ``RCPS_OwnLine`` (in configuration: ``OwnLine``)
+    The clause always gets its own line.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires C<T>
+      struct Foo {...
+
+      template<typename T>
+      requires C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void baz(T t)
+      requires C<T> {...
+
+  * ``RCPS_ToPreceeding`` (in configuration: ``ToPreceeding``)
+    The clause tries to stick to the template declaration in case of class
+    templates or between template and function delcarations. In case of
+    after the function delcaration it tries to stick to this.
+
+    .. code-block:: c++
+
+      template<typename T> requires C<T>
+      struct Foo {...
+
+      template<typename T> requires C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void baz(T t) requires C<T> {...
+
+  * ``RCPS_ToFollowing`` (in configuration: ``ToFollowing``)
+    The clause tries to stick to the class respectively function
+    declaration.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires C<T> struct Foo {...
+
+      template<typename T>
+      requires C<T> void bar(T t) {...
+
+      template<typename T>
+      void baz(T t) requires C<T> {...
+
+  * ``RCPS_SingleLine`` (in configuration: ``SingleLine``)
+    The clause tries to get everything in the same line, if it doesn't fit
+    normal line breaking rules decide to which part it sticks.
+
+    .. code-block:: c++
+
+      template<typename T> requires C<T> struct Foo {...
+
+      template<typename T> requires C<T> void bar(T t) {...
+
+      template<typename T> void bar(T t) requires C<T> {...
+
+  * ``RCPS_TwoLines`` (in configuration: ``TwoLines``)
+    The clause always gets its own line, and the content of the clause go
+    into the next line with some indentation.
+
+    .. code-block:: c++
+
+      template<typename T>
+      requires
+              C<T>
+      struct Foo {...
+
+      template<typename T>
+      requires
+              C<T>
+      void bar(T t) {...
+
+      template<typename T>
+      void bar(T t)
+      requires
+              C<T> {...
+
+
+
 **ShortNamespaceLines** (``Unsigned``) :versionbadge:`clang-format 14`
   The maximal number of unwrapped lines that a short namespace spans.
   Defaults to 1.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to