[clang] [clang-format] Adjust requires clause wrapping (#101550) (PR #102078)
Nathan Sidwell via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 8 14:09:09 PDT 2024
https://github.com/urnathan updated https://github.com/llvm/llvm-project/pull/102078
>From 193e704ea21251ea639bfb733671b4047c93c4ea Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan at acm.org>
Date: Sun, 4 Aug 2024 19:15:20 -0400
Subject: [PATCH 1/2] [clang-format] Adjust requires clause wrapping (#101550)
Adjust line wrapping after a requires clause to permit a following '{'
on the same line with OwnLine and WithPreceeding RequiresClausePositioning.
Thus, instead of:
```
bool Foo ()
requires(true)
{
return true;
}
```
we have:
```
bool Foo ()
requires(true) {
return true;
}
```
If the function body is empty, we'll get:
```
bool Foo ()
requires(true) {}
```
I attempted to get a line break between the open and close braces, but
failed. Perhaps that's fine -- it's rare and only happens in the empty
body case.
---
clang/lib/Format/TokenAnnotator.cpp | 3 +-
clang/unittests/Format/FormatTest.cpp | 53 +++++++++------------------
2 files changed, 19 insertions(+), 37 deletions(-)
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 4ed3e9d0e8e855..04ac0e2b90c609 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5682,7 +5682,8 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
(Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
Right.NewlinesBefore > 0);
}
- if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
+ if (Left.ClosesRequiresClause && Right.isNot(tok::semi) &&
+ Right.isNot(tok::l_brace)) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
case FormatStyle::RCPS_WithPreceding:
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 2a754a29e81e73..792c1971dae499 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4325,8 +4325,7 @@ TEST_F(FormatTest, FormatsNamespaces) {
Style);
verifyFormat("template <int I>\n"
"constexpr void foo()\n"
- " requires(I == 42)\n"
- "{}\n"
+ " requires(I == 42) {}\n"
"namespace ns {\n"
"void foo() {}\n"
"} // namespace ns",
@@ -17041,12 +17040,10 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
EXPECT_FALSE(
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression);
verifyFormat("void f(auto x)\n"
- " requires requires(int i) { x + i; }\n"
- "{}",
+ " requires requires(int i) { x + i; } {}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires(requires(int i) { x + i; })\n"
- "{}",
+ " requires(requires(int i) { x + i; }) {}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
@@ -17059,12 +17056,10 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
- " requires requires(int i) { x + i; }\n"
- "{}",
+ " requires requires(int i) { x + i; } {}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires (requires(int i) { x + i; })\n"
- "{}",
+ " requires (requires(int i) { x + i; }) {}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
@@ -17078,12 +17073,10 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = false;
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression = true;
verifyFormat("void f(auto x)\n"
- " requires requires (int i) { x + i; }\n"
- "{}",
+ " requires requires (int i) { x + i; } {}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires(requires (int i) { x + i; })\n"
- "{}",
+ " requires(requires (int i) { x + i; }) {}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
@@ -17096,12 +17089,10 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
- " requires requires (int i) { x + i; }\n"
- "{}",
+ " requires requires (int i) { x + i; } {}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires (requires (int i) { x + i; })\n"
- "{}",
+ " requires (requires (int i) { x + i; }) {}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
@@ -25799,8 +25790,7 @@ TEST_F(FormatTest, RequiresClausesPositions) {
" requires Foo<T> && requires(T t) {\n"
" { t.baz() } -> std::same_as<bool>;\n"
" requires std::same_as<T::Factor, int>;\n"
- " }\n"
- "{\n"
+ " } {\n"
" return t.baz() ? T::Factor : 5;\n"
"}",
Style);
@@ -25814,16 +25804,14 @@ TEST_F(FormatTest, RequiresClausesPositions) {
verifyFormat("template <typename T>\n"
"int bar(T t)\n"
- " requires F<T>\n"
- "{\n"
+ " requires F<T> {\n"
" return 5;\n"
"}",
Style);
verifyFormat("template <typename T>\n"
"int S::bar(T t) &&\n"
- " requires F<T>\n"
- "{\n"
+ " requires F<T> {\n"
" return 5;\n"
"}",
Style);
@@ -25843,16 +25831,14 @@ TEST_F(FormatTest, RequiresClausesPositions) {
verifyFormat("template <typename T>\n"
"int S::bar(T t) &&\n"
- "requires F<T>\n"
- "{\n"
+ "requires F<T> {\n"
" return 5;\n"
"}",
Style);
verifyFormat("template <typename T>\n"
"int bar(T t)\n"
- "requires F<T>\n"
- "{\n"
+ "requires F<T> {\n"
" return 5;\n"
"}",
Style);
@@ -25982,13 +25968,9 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"struct Bar {};\n"
"template <typename T> requires Foo<T>\n"
"void bar() {}\n"
- "template <typename T>\n"
- "void bar() requires Foo<T>\n"
- "{}\n"
+ "template <typename T> void bar() requires Foo<T> {}\n"
"template <typename T> void bar() requires Foo<T>;\n"
- "template <typename T>\n"
- "void S::bar() && requires Foo<T>\n"
- "{}\n"
+ "template <typename T> void S::bar() && requires Foo<T> {}\n"
"template <typename T> requires Foo<T>\n"
"Bar(T) -> Bar<T>;",
Style);
@@ -26001,8 +25983,7 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"void bar() {}\n"
"template <typename AAAAAAA>\n"
"void bar()\n"
- " requires Foo<AAAAAAAAAAAAAAAA>\n"
- "{}\n"
+ " requires Foo<AAAAAAAAAAAAAAAA> {}\n"
"template <typename AAAAAAA>\n"
"requires Foo<AAAAAAAA>\n"
"Bar(T) -> Bar<T>;\n"
>From 1fcb1f95d18803b980dda372c8da0b6b79b0fe1d Mon Sep 17 00:00:00 2001
From: Nathan Sidwell <nathan at acm.org>
Date: Thu, 8 Aug 2024 17:04:47 -0400
Subject: [PATCH 2/2] [clang-format] Add OwnLineWithBrace requires clause style
---
clang/docs/ClangFormatStyleOptions.rst | 33 ++++-
clang/include/clang/Format/Format.h | 31 ++++-
clang/lib/Format/ContinuationIndenter.cpp | 1 +
clang/lib/Format/Format.cpp | 1 +
clang/lib/Format/TokenAnnotator.cpp | 8 +-
clang/unittests/Format/FormatTest.cpp | 140 +++++++++++++++++++---
6 files changed, 187 insertions(+), 27 deletions(-)
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 6c2e6da5948478..5e7a55f24a1e78 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -5379,23 +5379,48 @@ the configuration (without a prefix: ``Auto``).
Possible values:
* ``RCPS_OwnLine`` (in configuration: ``OwnLine``)
- Always put the ``requires`` clause on its own line.
+ Always put the ``requires`` clause on its own line (possibly followed by
+ a semicolon).
.. code-block:: c++
template <typename T>
- requires C<T>
+ requires C<T>
struct Foo {...
template <typename T>
- requires C<T>
+ void bar(T t)
+ requires C<T>;
+
+ template <typename T>
+ requires C<T>
void bar(T t) {...
template <typename T>
void baz(T t)
- requires C<T>
+ requires C<T>
{...
+ * ``RCPS_OwnLineWithBrace`` (in configuration: ``OwnLineWithBrace``)
+ As with ``OwnLine``, except, unless otherwise prohibited, place a
+ following open brace (of a function definition) to follow on the same
+ line.
+
+ .. code-block:: c++
+
+ void bar(T t)
+ requires C<T> {
+ return;
+ }
+
+ void bar(T t)
+ requires C<T> {}
+
+ template <typename T>
+ requires C<T>
+ void baz(T t) {
+ ...
+
* ``RCPS_WithPreceding`` (in configuration: ``WithPreceding``)
Try to put the clause together with the preceding part of a declaration.
For class templates: stick to the template declaration.
diff --git a/clang/include/clang/Format/Format.h b/clang/include/clang/Format/Format.h
index c454ab2bc0ce29..1000cb5a8daeda 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -3909,22 +3909,45 @@ struct FormatStyle {
/// ``IndentRequires`` option is only used if the ``requires`` is put on the
/// start of a line.
enum RequiresClausePositionStyle : int8_t {
- /// Always put the ``requires`` clause on its own line.
+ /// Always put the ``requires`` clause on its own line (possibly followed by
+ /// a semicolon).
/// \code
/// template <typename T>
- /// requires C<T>
+ /// requires C<T>
/// struct Foo {...
///
/// template <typename T>
- /// requires C<T>
+ /// void bar(T t)
+ /// requires C<T>;
+ ///
+ /// template <typename T>
+ /// requires C<T>
/// void bar(T t) {...
///
/// template <typename T>
/// void baz(T t)
- /// requires C<T>
+ /// requires C<T>
/// {...
/// \endcode
RCPS_OwnLine,
+ /// As with ``OwnLine``, except, unless otherwise prohibited, place a
+ /// following open brace (of a function definition) to follow on the same
+ /// line.
+ /// \code
+ /// void bar(T t)
+ /// requires C<T> {
+ /// return;
+ /// }
+ ///
+ /// void bar(T t)
+ /// requires C<T> {}
+ ///
+ /// template <typename T>
+ /// requires C<T>
+ /// void baz(T t) {
+ /// ...
+ /// \endcode
+ RCPS_OwnLineWithBrace,
/// Try to put the clause together with the preceding part of a declaration.
/// For class templates: stick to the template declaration.
/// For function templates: stick to the template declaration.
diff --git a/clang/lib/Format/ContinuationIndenter.cpp b/clang/lib/Format/ContinuationIndenter.cpp
index df86a774ba0f4f..21adcc890d67f7 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1395,6 +1395,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
case FormatStyle::RCPS_WithFollowing:
+ case FormatStyle::RCPS_OwnLineWithBrace:
return CurrentState.Indent;
default:
break;
diff --git a/clang/lib/Format/Format.cpp b/clang/lib/Format/Format.cpp
index 7fd42e46e0ccb7..4c82a4f1109525 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -530,6 +530,7 @@ struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
static void enumeration(IO &IO,
FormatStyle::RequiresClausePositionStyle &Value) {
IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
+ IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace);
IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);
diff --git a/clang/lib/Format/TokenAnnotator.cpp b/clang/lib/Format/TokenAnnotator.cpp
index 04ac0e2b90c609..fb8476401afea0 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5664,6 +5664,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
if (Right.is(TT_RequiresClause)) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
+ case FormatStyle::RCPS_OwnLineWithBrace:
case FormatStyle::RCPS_WithFollowing:
return true;
default:
@@ -5682,12 +5683,15 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
(Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
Right.NewlinesBefore > 0);
}
- if (Left.ClosesRequiresClause && Right.isNot(tok::semi) &&
- Right.isNot(tok::l_brace)) {
+ if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
case FormatStyle::RCPS_WithPreceding:
return true;
+ case FormatStyle::RCPS_OwnLineWithBrace:
+ if (Right.isNot(tok::l_brace))
+ return true;
+ break;
default:
break;
}
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index 792c1971dae499..b80c419e6c0f8c 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -4325,7 +4325,8 @@ TEST_F(FormatTest, FormatsNamespaces) {
Style);
verifyFormat("template <int I>\n"
"constexpr void foo()\n"
- " requires(I == 42) {}\n"
+ " requires(I == 42)\n"
+ "{}\n"
"namespace ns {\n"
"void foo() {}\n"
"} // namespace ns",
@@ -17040,10 +17041,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
EXPECT_FALSE(
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression);
verifyFormat("void f(auto x)\n"
- " requires requires(int i) { x + i; } {}",
+ " requires requires(int i) { x + i; }\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires(requires(int i) { x + i; }) {}",
+ " requires(requires(int i) { x + i; })\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
@@ -17056,10 +17059,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
- " requires requires(int i) { x + i; } {}",
+ " requires requires(int i) { x + i; }\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires (requires(int i) { x + i; }) {}",
+ " requires (requires(int i) { x + i; })\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x + i; })\n"
" return;",
@@ -17073,10 +17078,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = false;
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInExpression = true;
verifyFormat("void f(auto x)\n"
- " requires requires (int i) { x + i; } {}",
+ " requires requires (int i) { x + i; }\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires(requires (int i) { x + i; }) {}",
+ " requires(requires (int i) { x + i; })\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
@@ -17089,10 +17096,12 @@ TEST_F(FormatTest, ConfigurableSpaceBeforeParens) {
SpaceAfterRequires.SpaceBeforeParensOptions.AfterRequiresInClause = true;
verifyFormat("void f(auto x)\n"
- " requires requires (int i) { x + i; } {}",
+ " requires requires (int i) { x + i; }\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("void f(auto x)\n"
- " requires (requires (int i) { x + i; }) {}",
+ " requires (requires (int i) { x + i; })\n"
+ "{}",
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x + i; })\n"
" return;",
@@ -25790,7 +25799,8 @@ TEST_F(FormatTest, RequiresClausesPositions) {
" requires Foo<T> && requires(T t) {\n"
" { t.baz() } -> std::same_as<bool>;\n"
" requires std::same_as<T::Factor, int>;\n"
- " } {\n"
+ " }\n"
+ "{\n"
" return t.baz() ? T::Factor : 5;\n"
"}",
Style);
@@ -25804,14 +25814,16 @@ TEST_F(FormatTest, RequiresClausesPositions) {
verifyFormat("template <typename T>\n"
"int bar(T t)\n"
- " requires F<T> {\n"
+ " requires F<T>\n"
+ "{\n"
" return 5;\n"
"}",
Style);
verifyFormat("template <typename T>\n"
"int S::bar(T t) &&\n"
- " requires F<T> {\n"
+ " requires F<T>\n"
+ "{\n"
" return 5;\n"
"}",
Style);
@@ -25831,19 +25843,108 @@ TEST_F(FormatTest, RequiresClausesPositions) {
verifyFormat("template <typename T>\n"
"int S::bar(T t) &&\n"
- "requires F<T> {\n"
+ "requires F<T>\n"
+ "{\n"
" return 5;\n"
"}",
Style);
verifyFormat("template <typename T>\n"
"int bar(T t)\n"
- "requires F<T> {\n"
+ "requires F<T>\n"
+ "{\n"
" return 5;\n"
"}",
Style);
+ Style.RequiresClausePosition = FormatStyle::RCPS_OwnLineWithBrace;
+ Style.IndentRequiresClause = true;
+
+ // The default in LLVM style is REI_OuterScope, but these tests were written
+ // when the default was REI_Keyword.
+ Style.RequiresExpressionIndentation = FormatStyle::REI_Keyword;
+
+ verifyFormat("template <typename T>\n"
+ " requires(Foo<T> && std::trait<T>)\n"
+ "struct Bar;",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ " requires(Foo<T> && std::trait<T>)\n"
+ "class Bar {\n"
+ "public:\n"
+ " Bar(T t);\n"
+ " bool baz();\n"
+ "};",
+ Style);
+
+ verifyFormat(
+ "template <typename T>\n"
+ " requires requires(T &&t) {\n"
+ " typename T::I;\n"
+ " requires(F<typename T::I> && std::trait<typename T::I>);\n"
+ " }\n"
+ "Bar(T) -> Bar<typename T::I>;",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ " requires(Foo<T> && std::trait<T>)\n"
+ "constexpr T MyGlobal;",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ " requires Foo<T> && requires(T t) {\n"
+ " { t.baz() } -> std::same_as<bool>;\n"
+ " requires std::same_as<T::Factor, int>;\n"
+ " }\n"
+ "inline int bar(T t) {\n"
+ " return t.baz() ? T::Factor : 5;\n"
+ "}",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ "inline int bar(T t)\n"
+ " requires Foo<T> && requires(T t) {\n"
+ " { t.baz() } -> std::same_as<bool>;\n"
+ " requires std::same_as<T::Factor, int>;\n"
+ " } {\n"
+ " return t.baz() ? T::Factor : 5;\n"
+ "}",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ " requires F<T>\n"
+ "int bar(T t) {\n"
+ " return 5;\n"
+ "}",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ "int bar(T t)\n"
+ " requires F<T> {\n"
+ " return 5;\n"
+ "}",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ "int S::bar(T t) &&\n"
+ " requires F<T> {\n"
+ " return 5;\n"
+ "}",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ "int bar(T t)\n"
+ " requires F<T>;",
+ Style);
+
+ verifyFormat("template <typename T>\n"
+ "int bar(T t)\n"
+ " requires F<T> {}",
+ Style);
+
Style.RequiresClausePosition = FormatStyle::RCPS_SingleLine;
+ Style.IndentRequiresClause = false;
verifyFormat("template <typename T> requires Foo<T> struct Bar {};\n"
"template <typename T> requires Foo<T> void bar() {}\n"
"template <typename T> void bar() requires Foo<T> {}\n"
@@ -25968,9 +26069,13 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"struct Bar {};\n"
"template <typename T> requires Foo<T>\n"
"void bar() {}\n"
- "template <typename T> void bar() requires Foo<T> {}\n"
+ "template <typename T>\n"
+ "void bar() requires Foo<T>\n"
+ "{}\n"
"template <typename T> void bar() requires Foo<T>;\n"
- "template <typename T> void S::bar() && requires Foo<T> {}\n"
+ "template <typename T>\n"
+ "void S::bar() && requires Foo<T>\n"
+ "{}\n"
"template <typename T> requires Foo<T>\n"
"Bar(T) -> Bar<T>;",
Style);
@@ -25983,7 +26088,8 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"void bar() {}\n"
"template <typename AAAAAAA>\n"
"void bar()\n"
- " requires Foo<AAAAAAAAAAAAAAAA> {}\n"
+ " requires Foo<AAAAAAAAAAAAAAAA>\n"
+ "{}\n"
"template <typename AAAAAAA>\n"
"requires Foo<AAAAAAAA>\n"
"Bar(T) -> Bar<T>;\n"
More information about the cfe-commits
mailing list