Skip to content

Commit 4cf9a42

Browse files
authored
[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.
1 parent 8d8f56d commit 4cf9a42

File tree

6 files changed

+150
-12
lines changed

6 files changed

+150
-12
lines changed

clang/docs/ClangFormatStyleOptions.rst

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4187,7 +4187,8 @@ the configuration (without a prefix: ``Auto``).
41874187

41884188
**IndentRequiresClause** (``Boolean``) :versionbadge:`clang-format 15` :ref:`<IndentRequiresClause>`
41894189
Indent the requires clause in a template. This only applies when
4190-
``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``.
4190+
``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``,
4191+
or ``WithFollowing``.
41914192

41924193
In clang-format 12, 13 and 14 it was named ``IndentRequires``.
41934194

@@ -5419,23 +5420,48 @@ the configuration (without a prefix: ``Auto``).
54195420
Possible values:
54205421

54215422
* ``RCPS_OwnLine`` (in configuration: ``OwnLine``)
5422-
Always put the ``requires`` clause on its own line.
5423+
Always put the ``requires`` clause on its own line (possibly followed by
5424+
a semicolon).
54235425

54245426
.. code-block:: c++
54255427

54265428
template <typename T>
5427-
requires C<T>
5429+
requires C<T>
54285430
struct Foo {...
54295431

54305432
template <typename T>
5431-
requires C<T>
5433+
void bar(T t)
5434+
requires C<T>;
5435+
5436+
template <typename T>
5437+
requires C<T>
54325438
void bar(T t) {...
54335439

54345440
template <typename T>
54355441
void baz(T t)
5436-
requires C<T>
5442+
requires C<T>
54375443
{...
54385444

5445+
* ``RCPS_OwnLineWithBrace`` (in configuration: ``OwnLineWithBrace``)
5446+
As with ``OwnLine``, except, unless otherwise prohibited, place a
5447+
following open brace (of a function definition) to follow on the same
5448+
line.
5449+
5450+
.. code-block:: c++
5451+
5452+
void bar(T t)
5453+
requires C<T> {
5454+
return;
5455+
}
5456+
5457+
void bar(T t)
5458+
requires C<T> {}
5459+
5460+
template <typename T>
5461+
requires C<T>
5462+
void baz(T t) {
5463+
...
5464+
54395465
* ``RCPS_WithPreceding`` (in configuration: ``WithPreceding``)
54405466
Try to put the clause together with the preceding part of a declaration.
54415467
For class templates: stick to the template declaration.

clang/include/clang/Format/Format.h

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,7 +2858,8 @@ struct FormatStyle {
28582858
PPDirectiveIndentStyle IndentPPDirectives;
28592859

28602860
/// Indent the requires clause in a template. This only applies when
2861-
/// ``RequiresClausePosition`` is ``OwnLine``, or ``WithFollowing``.
2861+
/// ``RequiresClausePosition`` is ``OwnLine``, ``OwnLineWithBrace``,
2862+
/// or ``WithFollowing``.
28622863
///
28632864
/// In clang-format 12, 13 and 14 it was named ``IndentRequires``.
28642865
/// \code
@@ -3944,22 +3945,45 @@ struct FormatStyle {
39443945
/// ``IndentRequires`` option is only used if the ``requires`` is put on the
39453946
/// start of a line.
39463947
enum RequiresClausePositionStyle : int8_t {
3947-
/// Always put the ``requires`` clause on its own line.
3948+
/// Always put the ``requires`` clause on its own line (possibly followed by
3949+
/// a semicolon).
39483950
/// \code
39493951
/// template <typename T>
3950-
/// requires C<T>
3952+
/// requires C<T>
39513953
/// struct Foo {...
39523954
///
39533955
/// template <typename T>
3954-
/// requires C<T>
3956+
/// void bar(T t)
3957+
/// requires C<T>;
3958+
///
3959+
/// template <typename T>
3960+
/// requires C<T>
39553961
/// void bar(T t) {...
39563962
///
39573963
/// template <typename T>
39583964
/// void baz(T t)
3959-
/// requires C<T>
3965+
/// requires C<T>
39603966
/// {...
39613967
/// \endcode
39623968
RCPS_OwnLine,
3969+
/// As with ``OwnLine``, except, unless otherwise prohibited, place a
3970+
/// following open brace (of a function definition) to follow on the same
3971+
/// line.
3972+
/// \code
3973+
/// void bar(T t)
3974+
/// requires C<T> {
3975+
/// return;
3976+
/// }
3977+
///
3978+
/// void bar(T t)
3979+
/// requires C<T> {}
3980+
///
3981+
/// template <typename T>
3982+
/// requires C<T>
3983+
/// void baz(T t) {
3984+
/// ...
3985+
/// \endcode
3986+
RCPS_OwnLineWithBrace,
39633987
/// Try to put the clause together with the preceding part of a declaration.
39643988
/// For class templates: stick to the template declaration.
39653989
/// For function templates: stick to the template declaration.

clang/lib/Format/ContinuationIndenter.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,6 +1427,7 @@ unsigned ContinuationIndenter::getNewLineColumn(const LineState &State) {
14271427
switch (Style.RequiresClausePosition) {
14281428
case FormatStyle::RCPS_OwnLine:
14291429
case FormatStyle::RCPS_WithFollowing:
1430+
case FormatStyle::RCPS_OwnLineWithBrace:
14301431
return CurrentState.Indent;
14311432
default:
14321433
break;

clang/lib/Format/Format.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,7 @@ struct ScalarEnumerationTraits<FormatStyle::RequiresClausePositionStyle> {
540540
static void enumeration(IO &IO,
541541
FormatStyle::RequiresClausePositionStyle &Value) {
542542
IO.enumCase(Value, "OwnLine", FormatStyle::RCPS_OwnLine);
543+
IO.enumCase(Value, "OwnLineWithBrace", FormatStyle::RCPS_OwnLineWithBrace);
543544
IO.enumCase(Value, "WithPreceding", FormatStyle::RCPS_WithPreceding);
544545
IO.enumCase(Value, "WithFollowing", FormatStyle::RCPS_WithFollowing);
545546
IO.enumCase(Value, "SingleLine", FormatStyle::RCPS_SingleLine);

clang/lib/Format/TokenAnnotator.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5681,6 +5681,7 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
56815681
if (Right.is(TT_RequiresClause)) {
56825682
switch (Style.RequiresClausePosition) {
56835683
case FormatStyle::RCPS_OwnLine:
5684+
case FormatStyle::RCPS_OwnLineWithBrace:
56845685
case FormatStyle::RCPS_WithFollowing:
56855686
return true;
56865687
default:
@@ -5699,11 +5700,13 @@ bool TokenAnnotator::mustBreakBefore(const AnnotatedLine &Line,
56995700
(Style.BreakTemplateDeclarations == FormatStyle::BTDS_Leave &&
57005701
Right.NewlinesBefore > 0);
57015702
}
5702-
if (Left.ClosesRequiresClause && Right.isNot(tok::semi)) {
5703+
if (Left.ClosesRequiresClause) {
57035704
switch (Style.RequiresClausePosition) {
57045705
case FormatStyle::RCPS_OwnLine:
57055706
case FormatStyle::RCPS_WithPreceding:
5706-
return true;
5707+
return Right.isNot(tok::semi);
5708+
case FormatStyle::RCPS_OwnLineWithBrace:
5709+
return !Right.isOneOf(tok::semi, tok::l_brace);
57075710
default:
57085711
break;
57095712
}

clang/unittests/Format/FormatTest.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25857,7 +25857,90 @@ TEST_F(FormatTest, RequiresClausesPositions) {
2585725857
"}",
2585825858
Style);
2585925859

25860+
Style.RequiresClausePosition = FormatStyle::RCPS_OwnLineWithBrace;
25861+
Style.IndentRequiresClause = true;
25862+
25863+
verifyFormat("template <typename T>\n"
25864+
" requires(Foo<T> && std::trait<T>)\n"
25865+
"struct Bar;",
25866+
Style);
25867+
25868+
verifyFormat("template <typename T>\n"
25869+
" requires(Foo<T> && std::trait<T>)\n"
25870+
"class Bar {\n"
25871+
"public:\n"
25872+
" Bar(T t);\n"
25873+
" bool baz();\n"
25874+
"};",
25875+
Style);
25876+
25877+
verifyFormat(
25878+
"template <typename T>\n"
25879+
" requires requires(T &&t) {\n"
25880+
" typename T::I;\n"
25881+
" requires(F<typename T::I> && std::trait<typename T::I>);\n"
25882+
" }\n"
25883+
"Bar(T) -> Bar<typename T::I>;",
25884+
Style);
25885+
25886+
verifyFormat("template <typename T>\n"
25887+
" requires(Foo<T> && std::trait<T>)\n"
25888+
"constexpr T MyGlobal;",
25889+
Style);
25890+
25891+
verifyFormat("template <typename T>\n"
25892+
" requires Foo<T> && requires(T t) {\n"
25893+
" { t.baz() } -> std::same_as<bool>;\n"
25894+
" requires std::same_as<T::Factor, int>;\n"
25895+
" }\n"
25896+
"inline int bar(T t) {\n"
25897+
" return t.baz() ? T::Factor : 5;\n"
25898+
"}",
25899+
Style);
25900+
25901+
verifyFormat("template <typename T>\n"
25902+
"inline int bar(T t)\n"
25903+
" requires Foo<T> && requires(T t) {\n"
25904+
" { t.baz() } -> std::same_as<bool>;\n"
25905+
" requires std::same_as<T::Factor, int>;\n"
25906+
" } {\n"
25907+
" return t.baz() ? T::Factor : 5;\n"
25908+
"}",
25909+
Style);
25910+
25911+
verifyFormat("template <typename T>\n"
25912+
" requires F<T>\n"
25913+
"int bar(T t) {\n"
25914+
" return 5;\n"
25915+
"}",
25916+
Style);
25917+
25918+
verifyFormat("template <typename T>\n"
25919+
"int bar(T t)\n"
25920+
" requires F<T> {\n"
25921+
" return 5;\n"
25922+
"}",
25923+
Style);
25924+
25925+
verifyFormat("template <typename T>\n"
25926+
"int S::bar(T t) &&\n"
25927+
" requires F<T> {\n"
25928+
" return 5;\n"
25929+
"}",
25930+
Style);
25931+
25932+
verifyFormat("template <typename T>\n"
25933+
"int bar(T t)\n"
25934+
" requires F<T>;",
25935+
Style);
25936+
25937+
verifyFormat("template <typename T>\n"
25938+
"int bar(T t)\n"
25939+
" requires F<T> {}",
25940+
Style);
25941+
2586025942
Style.RequiresClausePosition = FormatStyle::RCPS_SingleLine;
25943+
Style.IndentRequiresClause = false;
2586125944
verifyFormat("template <typename T> requires Foo<T> struct Bar {};\n"
2586225945
"template <typename T> requires Foo<T> void bar() {}\n"
2586325946
"template <typename T> void bar() requires Foo<T> {}\n"

0 commit comments

Comments
 (0)