[clang] 4cf9a42 - [clang-format] Adjust requires clause wrapping (#101550) (#102078)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 16 18:05:12 PDT 2024
Author: Nathan Sidwell
Date: 2024-08-16T21:05:08-04:00
New Revision: 4cf9a4266167c686e7e405ead5d6c1cd389eeca5
URL: https://github.com/llvm/llvm-project/commit/4cf9a4266167c686e7e405ead5d6c1cd389eeca5
DIFF: https://github.com/llvm/llvm-project/commit/4cf9a4266167c686e7e405ead5d6c1cd389eeca5.diff
LOG: [clang-format] Adjust requires clause wrapping (#101550) (#102078)
Address #101550 by adding OwnLineWithBrace option for RequiresClausePosition. This permits placing a following '{' on the same line as the requires clause.
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.
Added:
Modified:
clang/docs/ClangFormatStyleOptions.rst
clang/include/clang/Format/Format.h
clang/lib/Format/ContinuationIndenter.cpp
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.cpp
clang/unittests/Format/FormatTest.cpp
Removed:
################################################################################
diff --git a/clang/docs/ClangFormatStyleOptions.rst b/clang/docs/ClangFormatStyleOptions.rst
index 72e1bd19b6b520..c79a635d86a6ef 100644
--- a/clang/docs/ClangFormatStyleOptions.rst
+++ b/clang/docs/ClangFormatStyleOptions.rst
@@ -4187,7 +4187,8 @@ the configuration (without a prefix: ``Auto``).
**IndentRequiresClause** (``Boolean``) :versionbadge:`clang-format 15` :ref:`ΒΆ <IndentRequiresClause>`
Indent the requires clause in a template. This only applies when
- ``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``.
+ ``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``,
+ or ``WithFollowing``.
In clang-format 12, 13 and 14 it was named ``IndentRequires``.
@@ -5419,23 +5420,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 ef6c76a070bfaa..2af1d4065c3cc1 100644
--- a/clang/include/clang/Format/Format.h
+++ b/clang/include/clang/Format/Format.h
@@ -2858,7 +2858,8 @@ struct FormatStyle {
PPDirectiveIndentStyle IndentPPDirectives;
/// Indent the requires clause in a template. This only applies when
- /// ``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``.
+ /// ``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``,
+ /// or ``WithFollowing``.
///
/// In clang-format 12, 13 and 14 it was named ``IndentRequires``.
/// \code
@@ -3944,22 +3945,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 43d246b7f82419..46dafad65863dc 100644
--- a/clang/lib/Format/ContinuationIndenter.cpp
+++ b/clang/lib/Format/ContinuationIndenter.cpp
@@ -1427,6 +1427,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 5358b35c19de25..a795d869a3cb66 100644
--- a/clang/lib/Format/Format.cpp
+++ b/clang/lib/Format/Format.cpp
@@ -540,6 +540,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 9f79fa9fc516ca..9d4204655b8ed6 100644
--- a/clang/lib/Format/TokenAnnotator.cpp
+++ b/clang/lib/Format/TokenAnnotator.cpp
@@ -5681,6 +5681,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:
@@ -5699,11 +5700,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
(Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
Right.NewlinesBefore > 0);
}
- if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
+ if (Left.ClosesRequiresClause) {
switch (Style.RequiresClausePosition) {
case FormatStyle::RCPS_OwnLine:
case FormatStyle::RCPS_WithPreceding:
- return true;
+ return Right.isNot(tok::semi);
+ case FormatStyle::RCPS_OwnLineWithBrace:
+ return !Right.isOneOf(tok::semi, tok::l_brace);
default:
break;
}
diff --git a/clang/unittests/Format/FormatTest.cpp b/clang/unittests/Format/FormatTest.cpp
index bad1b1d662d133..794ccab3704534 100644
--- a/clang/unittests/Format/FormatTest.cpp
+++ b/clang/unittests/Format/FormatTest.cpp
@@ -25857,7 +25857,90 @@ TEST_F(FormatTest, RequiresClausesPositions) {
"}",
Style);
+ Style.RequiresClausePosition = FormatStyle::RCPS_OwnLineWithBrace;
+ Style.IndentRequiresClause = true;
+
+ 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"
More information about the cfe-commits
mailing list