[clang-format] Disallow decltype in the middle of constraints
authorEmilia Dreamer <emilia@rymiel.space>
Fri, 6 Jan 2023 03:18:19 +0000 (05:18 +0200)
committerEmilia Dreamer <emilia@rymiel.space>
Fri, 6 Jan 2023 03:18:28 +0000 (05:18 +0200)
If a function with a `requires` clause as a constraint has a decltype
return type, such as `decltype(auto)`, the decltype was seen to be part
of the constraint clause, rather than as part of the function
declaration, causing it to be placed on the wrong line.

This patch disallows decltype to be a part of these clauses

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

Depends on D140339

Reviewed By: HazardyKnusperkeks, owenpan, MyDeveloperDay

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

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

index 81a6d8f..c97ecc7 100644 (file)
@@ -3543,7 +3543,6 @@ void UnwrappedLineParser::parseConstraintExpression() {
     case tok::minus:
     case tok::star:
     case tok::slash:
-    case tok::kw_decltype:
       LambdaNextTimeAllowed = true;
       // Just eat them.
       nextToken();
index 21b497b..b2a1e2c 100644 (file)
@@ -24199,6 +24199,10 @@ TEST_F(FormatTest, RequiresClauses) {
                "  }\n"
                "};");
 
+  verifyFormat("template <class T>\n"
+               "  requires(std::same_as<int, T>)\n"
+               "decltype(auto) fun() {}");
+
   auto Style = getLLVMStyle();
 
   verifyFormat(
index 806c75d..dba893d 100644 (file)
@@ -581,6 +581,14 @@ TEST_F(TokenAnnotatorTest, UnderstandsRequiresClausesAndConcepts) {
   EXPECT_TOKEN(Tokens[11], tok::identifier, TT_FunctionDeclarationName);
 
   Tokens = annotate("template <typename T>\n"
+                    "requires Bar<T>\n"
+                    "decltype(auto) foo(T) { return false; }");
+  ASSERT_EQ(Tokens.size(), 24u) << Tokens;
+  EXPECT_TOKEN(Tokens[5], tok::kw_requires, TT_RequiresClause);
+  EXPECT_TRUE(Tokens[9]->ClosesRequiresClause);
+  EXPECT_TOKEN(Tokens[14], tok::identifier, TT_FunctionDeclarationName);
+
+  Tokens = annotate("template <typename T>\n"
                     "struct S {\n"
                     "  void foo() const requires Bar<T>;\n"
                     "  void bar() const & requires Baz<T>;\n"