[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