[clang-format] Correctly indent closing brace of compound requires
authorEmilia Dreamer <emilia@rymiel.space>
Sat, 1 Oct 2022 05:16:45 +0000 (08:16 +0300)
committerEmilia Dreamer <emilia@rymiel.space>
Sat, 1 Oct 2022 05:16:57 +0000 (08:16 +0300)
When a compound requirement is too long to fit onto a single line, the
braces are split apart onto separate lines, and the contained expression
is indented. However, this indentation would also apply to the closing
brace and the trailing return type requirement thereof.
This was because the indentation level was being restored after all
trailing things were already read

With this change, the initial level of the opening brace is set before
attempting to read any trailing return type requirements

Fixes https://github.com/llvm/llvm-project/issues/57108

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

Differential Revision: https://reviews.llvm.org/D134626

clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTest.cpp

index ead3f7f..f39c107 100644 (file)
@@ -964,6 +964,8 @@ FormatToken *UnwrappedLineParser::parseBlock(
   if (MacroBlock && FormatTok->is(tok::l_paren))
     parseParens();
 
+  Line->Level = InitialLevel;
+
   if (FormatTok->is(tok::kw_noexcept)) {
     // A noexcept in a requires expression.
     nextToken();
@@ -979,8 +981,6 @@ FormatToken *UnwrappedLineParser::parseBlock(
   if (MunchSemi && FormatTok->is(tok::semi))
     nextToken();
 
-  Line->Level = InitialLevel;
-
   if (PPStartHash == PPEndHash) {
     Line->MatchingOpeningBlockLineIndex = OpeningLineIndex;
     if (OpeningLineIndex != UnwrappedLine::kInvalidIndex) {
index 9a1396b..fd567be 100644 (file)
@@ -24510,6 +24510,16 @@ TEST_F(FormatTest, Concepts) {
       "              { x * 1 } -> std::convertible_to<T>;\n"
       "            };");
 
+  verifyFormat("template <typename T>\n"
+               "concept C = requires(T x) {\n"
+               "              {\n"
+               "                long_long_long_function_call(1, 2, 3, 4, 5)\n"
+               "              } -> long_long_concept_name<T>;\n"
+               "              {\n"
+               "                long_long_long_function_call(1, 2, 3, 4, 5)\n"
+               "              } noexcept -> long_long_concept_name<T>;\n"
+               "            };");
+
   verifyFormat(
       "template <typename T, typename U = T>\n"
       "concept Swappable = requires(T &&t, U &&u) {\n"