[clang] d4a6e4c - Revert "[Clang] Fix parsing of `(auto(x))`."

Corentin Jabot via cfe-commits cfe-commits at lists.llvm.org
Tue May 16 04:56:42 PDT 2023


Author: Corentin Jabot
Date: 2023-05-16T13:56:33+02:00
New Revision: d4a6e4c1eec0f2634febd15725d921d4a25d47e7

URL: https://github.com/llvm/llvm-project/commit/d4a6e4c1eec0f2634febd15725d921d4a25d47e7
DIFF: https://github.com/llvm/llvm-project/commit/d4a6e4c1eec0f2634febd15725d921d4a25d47e7.diff

LOG: Revert "[Clang] Fix parsing of `(auto(x))`."

This reverts commit ef47318ec3615e83c328b07341046dfb9d869414.

This patch breaks valid code https://reviews.llvm.org/D149276#4345620

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Parse/Parser.h
    clang/lib/Parse/ParseDecl.cpp
    clang/lib/Parse/ParseTentative.cpp
    clang/lib/Parse/Parser.cpp
    clang/test/Parser/cxx1z-decomposition.cpp
    clang/test/Parser/cxx2b-auto-x.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c62823ddec980..9601849bd67d3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -449,8 +449,6 @@ Bug Fixes to C++ Support
 - Some predefined expressions are now treated as string literals in MSVC
   compatibility mode.
   (`#114 <https://github.com/llvm/llvm-project/issues/114>`_)
-- Fix parsing of `auto(x)`, when it is surrounded by parentheses.
-  (`#62494 <https://github.com/llvm/llvm-project/issues/62494>`_)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^

diff  --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 8927af55e3712..fc892d71b51bf 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2521,10 +2521,10 @@ class Parser : public CodeCompletionHandler {
   enum TentativeCXXTypeIdContext {
     TypeIdInParens,
     TypeIdUnambiguous,
-    TypeIdAsTemplateArgument,
-    TypeIdInTrailingReturnType,
+    TypeIdAsTemplateArgument
   };
 
+
   /// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
   /// whether the parens contain an expression or a type-id.
   /// Returns true for a type-id and false for an expression.
@@ -2652,15 +2652,14 @@ class Parser : public CodeCompletionHandler {
   TPResult TryParseProtocolQualifiers();
   TPResult TryParsePtrOperatorSeq();
   TPResult TryParseOperatorId();
-  TPResult TryParseInitDeclaratorList(bool MayHaveTrailingReturnType = false);
+  TPResult TryParseInitDeclaratorList();
   TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,
-                              bool mayHaveDirectInit = false,
-                              bool mayHaveTrailingReturnType = false);
+                              bool mayHaveDirectInit = false);
   TPResult TryParseParameterDeclarationClause(
       bool *InvalidAsDeclaration = nullptr, bool VersusTemplateArg = false,
       ImplicitTypenameContext AllowImplicitTypename =
           ImplicitTypenameContext::No);
-  TPResult TryParseFunctionDeclarator(bool MayHaveTrailingReturnType = false);
+  TPResult TryParseFunctionDeclarator();
   TPResult TryParseBracketDeclarator();
   TPResult TryConsumeDeclarationSpecifier();
 

diff  --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index 15a38e647b2de..92fa7d8a8a759 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -6494,9 +6494,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
     // that it's an initializer instead.
     if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
       RevertingTentativeParsingAction PA(*this);
-      if (TryParseDeclarator(true, D.mayHaveIdentifier(), true,
-                             D.getDeclSpec().getTypeSpecType() == TST_auto) ==
-          TPResult::False) {
+      if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
+              TPResult::False) {
         D.SetIdentifier(nullptr, Tok.getLocation());
         goto PastIdentifier;
       }

diff  --git a/clang/lib/Parse/ParseTentative.cpp b/clang/lib/Parse/ParseTentative.cpp
index bdb462d086f2c..02aa59ec6fa1f 100644
--- a/clang/lib/Parse/ParseTentative.cpp
+++ b/clang/lib/Parse/ParseTentative.cpp
@@ -262,7 +262,6 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
 ///    attribute-specifier-seqopt type-specifier-seq declarator
 ///
 Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
-  bool DeclSpecifierIsAuto = Tok.is(tok::kw_auto);
   if (TryConsumeDeclarationSpecifier() == TPResult::Error)
     return TPResult::Error;
 
@@ -278,8 +277,7 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
     assert(TPR == TPResult::False);
   }
 
-  TPResult TPR = TryParseInitDeclaratorList(
-      /*mayHaveTrailingReturnType=*/DeclSpecifierIsAuto);
+  TPResult TPR = TryParseInitDeclaratorList();
   if (TPR != TPResult::Ambiguous)
     return TPR;
 
@@ -316,15 +314,10 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
 ///         '{' initializer-list ','[opt] '}'
 ///         '{' '}'
 ///
-Parser::TPResult
-Parser::TryParseInitDeclaratorList(bool MayHaveTrailingReturnType) {
+Parser::TPResult Parser::TryParseInitDeclaratorList() {
   while (true) {
     // declarator
-    TPResult TPR = TryParseDeclarator(
-        /*mayBeAbstract=*/false,
-        /*mayHaveIdentifier=*/true,
-        /*mayHaveDirectInit=*/false,
-        /*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType);
+    TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
     if (TPR != TPResult::Ambiguous)
       return TPR;
 
@@ -539,18 +532,13 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
   RevertingTentativeParsingAction PA(*this);
 
   // FIXME: A tag definition unambiguously tells us this is an init-statement.
-  bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);
   if (State.update(TryConsumeDeclarationSpecifier()))
     return State.result();
   assert(Tok.is(tok::l_paren) && "Expected '('");
 
   while (true) {
     // Consume a declarator.
-    if (State.update(TryParseDeclarator(
-            /*mayBeAbstract=*/false,
-            /*mayHaveIdentifier=*/true,
-            /*mayHaveDirectInit=*/false,
-            /*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType)))
+    if (State.update(TryParseDeclarator(false/*mayBeAbstract*/)))
       return State.result();
 
     // Attributes, asm label, or an initializer imply this is not an expression.
@@ -635,16 +623,13 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
   // We need tentative parsing...
 
   RevertingTentativeParsingAction PA(*this);
-  bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);
 
   // type-specifier-seq
   TryConsumeDeclarationSpecifier();
   assert(Tok.is(tok::l_paren) && "Expected '('");
 
   // declarator
-  TPR = TryParseDeclarator(true /*mayBeAbstract*/, false /*mayHaveIdentifier*/,
-                           /*mayHaveDirectInit=*/false,
-                           MayHaveTrailingReturnType);
+  TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
 
   // In case of an error, let the declaration parsing code handle it.
   if (TPR == TPResult::Error)
@@ -673,9 +658,6 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
       TPR = TPResult::True;
       isAmbiguous = true;
 
-    } else if (Context == TypeIdInTrailingReturnType) {
-      TPR = TPResult::True;
-      isAmbiguous = true;
     } else
       TPR = TPResult::False;
   }
@@ -1060,8 +1042,7 @@ Parser::TPResult Parser::TryParseOperatorId() {
 ///
 Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
                                             bool mayHaveIdentifier,
-                                            bool mayHaveDirectInit,
-                                            bool mayHaveTrailingReturnType) {
+                                            bool mayHaveDirectInit) {
   // declarator:
   //   direct-declarator
   //   ptr-operator declarator
@@ -1103,7 +1084,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
              ImplicitTypenameContext::No))) { // 'int(int)' is a function.
       // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
       //        exception-specification[opt]
-      TPResult TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);
+      TPResult TPR = TryParseFunctionDeclarator();
       if (TPR != TPResult::Ambiguous)
         return TPR;
     } else {
@@ -1142,7 +1123,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
       // direct-declarator '(' parameter-declaration-clause ')'
       //        cv-qualifier-seq[opt] exception-specification[opt]
       ConsumeParen();
-      TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);
+      TPR = TryParseFunctionDeclarator();
     } else if (Tok.is(tok::l_square)) {
       // direct-declarator '[' constant-expression[opt] ']'
       // direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
@@ -1409,16 +1390,6 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
     return isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes,
                                      BracedCastResult, InvalidAsDeclSpec);
 
-  case tok::kw_auto: {
-    if (!getLangOpts().CPlusPlus23)
-      return TPResult::True;
-    if (NextToken().is(tok::l_brace))
-      return TPResult::False;
-    if (NextToken().is(tok::l_paren))
-      return TPResult::Ambiguous;
-    return TPResult::True;
-  }
-
   case tok::coloncolon: {    // ::foo::bar
     const Token &Next = NextToken();
     if (Next.isOneOf(tok::kw_new,       // ::new
@@ -1452,6 +1423,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
   case tok::kw_static:
   case tok::kw_extern:
   case tok::kw_mutable:
+  case tok::kw_auto:
   case tok::kw___thread:
   case tok::kw_thread_local:
   case tok::kw__Thread_local:
@@ -2051,10 +2023,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause(
 
     // declarator
     // abstract-declarator[opt]
-    TPR = TryParseDeclarator(/*mayBeAbstract=*/true,
-                             /*mayHaveIdentifier=*/true,
-                             /*mayHaveDirectInit=*/false,
-                             /*mayHaveTrailingReturnType=*/true);
+    TPR = TryParseDeclarator(true/*mayBeAbstract*/);
     if (TPR != TPResult::Ambiguous)
       return TPR;
 
@@ -2108,8 +2077,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause(
 /// exception-specification:
 ///   'throw' '(' type-id-list[opt] ')'
 ///
-Parser::TPResult
-Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {
+Parser::TPResult Parser::TryParseFunctionDeclarator() {
   // The '(' is already parsed.
 
   TPResult TPR = TryParseParameterDeclarationClause();
@@ -2154,19 +2122,6 @@ Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {
     }
   }
 
-  // attribute-specifier-seq
-  if (!TrySkipAttributes())
-    return TPResult::Ambiguous;
-
-  // trailing-return-type
-  if (Tok.is(tok::arrow) && MayHaveTrailingReturnType) {
-    if (TPR == TPResult::True)
-      return TPR;
-    ConsumeToken();
-    if (isCXXTypeId(TentativeCXXTypeIdContext::TypeIdInTrailingReturnType))
-      return TPResult::True;
-  }
-
   return TPResult::Ambiguous;
 }
 

diff  --git a/clang/lib/Parse/Parser.cpp b/clang/lib/Parse/Parser.cpp
index f0fa075a91125..c0f4556d743b2 100644
--- a/clang/lib/Parse/Parser.cpp
+++ b/clang/lib/Parse/Parser.cpp
@@ -1950,7 +1950,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(
   assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
           Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) ||
           Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) ||
-          Tok.is(tok::kw___super) || Tok.is(tok::kw_auto)) &&
+          Tok.is(tok::kw___super)) &&
          "Cannot be a type or scope token!");
 
   if (Tok.is(tok::kw_typename)) {

diff  --git a/clang/test/Parser/cxx1z-decomposition.cpp b/clang/test/Parser/cxx1z-decomposition.cpp
index 90d60df2e47fe..10ef464bda50c 100644
--- a/clang/test/Parser/cxx1z-decomposition.cpp
+++ b/clang/test/Parser/cxx1z-decomposition.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx17 -fcxx-exceptions
-// RUN: %clang_cc1 -std=c++2b %s -verify=expected,cxx2b -fcxx-exceptions
+// RUN: %clang_cc1 -std=c++17 %s -verify -fcxx-exceptions
 // RUN: not %clang_cc1 -std=c++17 %s -emit-llvm-only -fcxx-exceptions
 
 struct S { int a, b, c; };
@@ -31,7 +30,7 @@ namespace ForRangeDecl {
 namespace OtherDecl {
   // A parameter-declaration is not a simple-declaration.
   // This parses as an array declaration.
-  void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
+  void f(auto [a, b, c]); // expected-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
 
   void g() {
     // A condition is allowed as a Clang extension.
@@ -58,7 +57,7 @@ namespace OtherDecl {
 namespace GoodSpecifiers {
   void f() {
     int n[1];
-    const volatile auto &[a] = n; // cxx2b-warning {{volatile qualifier in structured binding declaration is deprecated}}
+    const volatile auto &[a] = n;
   }
 }
 
@@ -68,8 +67,8 @@ namespace BadSpecifiers {
   struct S { int n; } s;
   void f() {
     // storage-class-specifiers
-    static auto &[a] = n; // cxx17-warning {{declared 'static' is a C++20 extension}}
-    thread_local auto &[b] = n; // cxx17-warning {{declared 'thread_local' is a C++20 extension}}
+    static auto &[a] = n; // expected-warning {{declared 'static' is a C++20 extension}}
+    thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++20 extension}}
     extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{declaration of block scope identifier with linkage cannot have an initializer}}
     struct S {
       mutable auto &[d] = n; // expected-error {{not permitted in this context}}
@@ -86,19 +85,16 @@ namespace BadSpecifiers {
   }
 
   static constexpr inline thread_local auto &[j1] = n; // expected-error {{cannot be declared with 'constexpr inline' specifiers}}
-  static thread_local auto &[j2] = n; // cxx17-warning {{declared with 'static thread_local' specifiers is a C++20 extension}}
+  static thread_local auto &[j2] = n; // expected-warning {{declared with 'static thread_local' specifiers is a C++20 extension}}
 
   inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}}
 
   const int K = 5;
-  auto ([c]) = s; // expected-error {{decomposition declaration cannot be declared with parentheses}}
   void g() {
     // defining-type-specifiers other than cv-qualifiers and 'auto'
     S [a] = s; // expected-error {{cannot be declared with type 'S'}}
     decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}}
-    auto ([c2]) = s; // cxx17-error {{decomposition declaration cannot be declared with parenthese}} \
-                     // cxx2b-error {{use of undeclared identifier 'c2'}} \
-                     // cxx2b-error {{expected body of lambda expression}} \
+    auto ([c]) = s; // expected-error {{cannot be declared with parentheses}}
 
     // FIXME: This error is not very good.
     auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}

diff  --git a/clang/test/Parser/cxx2b-auto-x.cpp b/clang/test/Parser/cxx2b-auto-x.cpp
index 9e0277eee76a9..5ca11d5f39950 100644
--- a/clang/test/Parser/cxx2b-auto-x.cpp
+++ b/clang/test/Parser/cxx2b-auto-x.cpp
@@ -18,37 +18,7 @@ struct looks_like_declaration {
 
 using T = looks_like_declaration *;
 void f() { T(&a)->n = 1; }
-void g() { auto(&a)->n = 0; } // cxx23-warning {{before C++23}} \
-                              // cxx20-error {{declaration of variable 'a' with deduced type 'auto (&)' requires an initializer}} \
-                              // cxx20-error {{expected ';' at end of declaration}}
-void h() { auto{&a}->n = 0; } // cxx23-warning {{before C++23}} \
-                              // cxx20-error {{expected unqualified-id}} \
-                              // cxx20-error {{expected expression}}
-
-void e(auto (*p)(int y) -> decltype(y)) {}
-
-struct M;
-struct S{
-    S operator()();
-    S* operator->();
-    int N;
-    int M;
-} s; // expected-note {{here}}
-
-void test() {
-    auto(s)()->N; // cxx23-warning {{expression result unused}} \
-                  // cxx23-warning {{before C++23}} \
-                  // cxx20-error {{unknown type name 'N'}}
-    auto(s)()->M; // expected-error {{redefinition of 's' as 
diff erent kind of symbol}}
-}
-
-void test_paren() {
-    int a = (auto(0)); // cxx23-warning {{before C++23}} \
-                       // cxx20-error {{expected expression}} \
-                       // cxx20-error {{expected ')'}} \
-                       // cxx20-note  {{to match this '('}}
-    int b = (auto{0}); // cxx23-warning {{before C++23}} \
-                       // cxx20-error {{expected expression}} \
-                       // cxx20-error {{expected ')'}} \
-                       // cxx20-note  {{to match this '('}}
-}
+// FIXME: They should be deemed expressions without breaking function pointer
+//        parameter declarations with trailing return types.
+// void g() { auto(&a)->n = 0; }
+// void h() { auto{&a}->n = 0; }


        


More information about the cfe-commits mailing list