Skip to content

Commit d4a6e4c

Browse files
committed
Revert "[Clang] Fix parsing of (auto(x))."
This reverts commit ef47318. This patch breaks valid code https://reviews.llvm.org/D149276#4345620
1 parent 65abcf6 commit d4a6e4c

File tree

7 files changed

+30
-113
lines changed

7 files changed

+30
-113
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -449,8 +449,6 @@ Bug Fixes to C++ Support
449449
- Some predefined expressions are now treated as string literals in MSVC
450450
compatibility mode.
451451
(`#114 <https://github.com/llvm/llvm-project/issues/114>`_)
452-
- Fix parsing of `auto(x)`, when it is surrounded by parentheses.
453-
(`#62494 <https://github.com/llvm/llvm-project/issues/62494>`_)
454452

455453
Bug Fixes to AST Handling
456454
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Parse/Parser.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,10 +2521,10 @@ class Parser : public CodeCompletionHandler {
25212521
enum TentativeCXXTypeIdContext {
25222522
TypeIdInParens,
25232523
TypeIdUnambiguous,
2524-
TypeIdAsTemplateArgument,
2525-
TypeIdInTrailingReturnType,
2524+
TypeIdAsTemplateArgument
25262525
};
25272526

2527+
25282528
/// isTypeIdInParens - Assumes that a '(' was parsed and now we want to know
25292529
/// whether the parens contain an expression or a type-id.
25302530
/// Returns true for a type-id and false for an expression.
@@ -2652,15 +2652,14 @@ class Parser : public CodeCompletionHandler {
26522652
TPResult TryParseProtocolQualifiers();
26532653
TPResult TryParsePtrOperatorSeq();
26542654
TPResult TryParseOperatorId();
2655-
TPResult TryParseInitDeclaratorList(bool MayHaveTrailingReturnType = false);
2655+
TPResult TryParseInitDeclaratorList();
26562656
TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true,
2657-
bool mayHaveDirectInit = false,
2658-
bool mayHaveTrailingReturnType = false);
2657+
bool mayHaveDirectInit = false);
26592658
TPResult TryParseParameterDeclarationClause(
26602659
bool *InvalidAsDeclaration = nullptr, bool VersusTemplateArg = false,
26612660
ImplicitTypenameContext AllowImplicitTypename =
26622661
ImplicitTypenameContext::No);
2663-
TPResult TryParseFunctionDeclarator(bool MayHaveTrailingReturnType = false);
2662+
TPResult TryParseFunctionDeclarator();
26642663
TPResult TryParseBracketDeclarator();
26652664
TPResult TryConsumeDeclarationSpecifier();
26662665

clang/lib/Parse/ParseDecl.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6494,9 +6494,8 @@ void Parser::ParseDirectDeclarator(Declarator &D) {
64946494
// that it's an initializer instead.
64956495
if (D.mayOmitIdentifier() && D.mayBeFollowedByCXXDirectInit()) {
64966496
RevertingTentativeParsingAction PA(*this);
6497-
if (TryParseDeclarator(true, D.mayHaveIdentifier(), true,
6498-
D.getDeclSpec().getTypeSpecType() == TST_auto) ==
6499-
TPResult::False) {
6497+
if (TryParseDeclarator(true, D.mayHaveIdentifier(), true) ==
6498+
TPResult::False) {
65006499
D.SetIdentifier(nullptr, Tok.getLocation());
65016500
goto PastIdentifier;
65026501
}

clang/lib/Parse/ParseTentative.cpp

Lines changed: 11 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,6 @@ Parser::TPResult Parser::TryConsumeDeclarationSpecifier() {
262262
/// attribute-specifier-seqopt type-specifier-seq declarator
263263
///
264264
Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
265-
bool DeclSpecifierIsAuto = Tok.is(tok::kw_auto);
266265
if (TryConsumeDeclarationSpecifier() == TPResult::Error)
267266
return TPResult::Error;
268267

@@ -278,8 +277,7 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
278277
assert(TPR == TPResult::False);
279278
}
280279

281-
TPResult TPR = TryParseInitDeclaratorList(
282-
/*mayHaveTrailingReturnType=*/DeclSpecifierIsAuto);
280+
TPResult TPR = TryParseInitDeclaratorList();
283281
if (TPR != TPResult::Ambiguous)
284282
return TPR;
285283

@@ -316,15 +314,10 @@ Parser::TPResult Parser::TryParseSimpleDeclaration(bool AllowForRangeDecl) {
316314
/// '{' initializer-list ','[opt] '}'
317315
/// '{' '}'
318316
///
319-
Parser::TPResult
320-
Parser::TryParseInitDeclaratorList(bool MayHaveTrailingReturnType) {
317+
Parser::TPResult Parser::TryParseInitDeclaratorList() {
321318
while (true) {
322319
// declarator
323-
TPResult TPR = TryParseDeclarator(
324-
/*mayBeAbstract=*/false,
325-
/*mayHaveIdentifier=*/true,
326-
/*mayHaveDirectInit=*/false,
327-
/*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType);
320+
TPResult TPR = TryParseDeclarator(false/*mayBeAbstract*/);
328321
if (TPR != TPResult::Ambiguous)
329322
return TPR;
330323

@@ -539,18 +532,13 @@ Parser::isCXXConditionDeclarationOrInitStatement(bool CanBeInitStatement,
539532
RevertingTentativeParsingAction PA(*this);
540533

541534
// FIXME: A tag definition unambiguously tells us this is an init-statement.
542-
bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);
543535
if (State.update(TryConsumeDeclarationSpecifier()))
544536
return State.result();
545537
assert(Tok.is(tok::l_paren) && "Expected '('");
546538

547539
while (true) {
548540
// Consume a declarator.
549-
if (State.update(TryParseDeclarator(
550-
/*mayBeAbstract=*/false,
551-
/*mayHaveIdentifier=*/true,
552-
/*mayHaveDirectInit=*/false,
553-
/*mayHaveTrailingReturnType=*/MayHaveTrailingReturnType)))
541+
if (State.update(TryParseDeclarator(false/*mayBeAbstract*/)))
554542
return State.result();
555543

556544
// Attributes, asm label, or an initializer imply this is not an expression.
@@ -635,16 +623,13 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
635623
// We need tentative parsing...
636624

637625
RevertingTentativeParsingAction PA(*this);
638-
bool MayHaveTrailingReturnType = Tok.is(tok::kw_auto);
639626

640627
// type-specifier-seq
641628
TryConsumeDeclarationSpecifier();
642629
assert(Tok.is(tok::l_paren) && "Expected '('");
643630

644631
// declarator
645-
TPR = TryParseDeclarator(true /*mayBeAbstract*/, false /*mayHaveIdentifier*/,
646-
/*mayHaveDirectInit=*/false,
647-
MayHaveTrailingReturnType);
632+
TPR = TryParseDeclarator(true/*mayBeAbstract*/, false/*mayHaveIdentifier*/);
648633

649634
// In case of an error, let the declaration parsing code handle it.
650635
if (TPR == TPResult::Error)
@@ -673,9 +658,6 @@ bool Parser::isCXXTypeId(TentativeCXXTypeIdContext Context, bool &isAmbiguous) {
673658
TPR = TPResult::True;
674659
isAmbiguous = true;
675660

676-
} else if (Context == TypeIdInTrailingReturnType) {
677-
TPR = TPResult::True;
678-
isAmbiguous = true;
679661
} else
680662
TPR = TPResult::False;
681663
}
@@ -1060,8 +1042,7 @@ Parser::TPResult Parser::TryParseOperatorId() {
10601042
///
10611043
Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
10621044
bool mayHaveIdentifier,
1063-
bool mayHaveDirectInit,
1064-
bool mayHaveTrailingReturnType) {
1045+
bool mayHaveDirectInit) {
10651046
// declarator:
10661047
// direct-declarator
10671048
// ptr-operator declarator
@@ -1103,7 +1084,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
11031084
ImplicitTypenameContext::No))) { // 'int(int)' is a function.
11041085
// '(' parameter-declaration-clause ')' cv-qualifier-seq[opt]
11051086
// exception-specification[opt]
1106-
TPResult TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);
1087+
TPResult TPR = TryParseFunctionDeclarator();
11071088
if (TPR != TPResult::Ambiguous)
11081089
return TPR;
11091090
} else {
@@ -1142,7 +1123,7 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract,
11421123
// direct-declarator '(' parameter-declaration-clause ')'
11431124
// cv-qualifier-seq[opt] exception-specification[opt]
11441125
ConsumeParen();
1145-
TPR = TryParseFunctionDeclarator(mayHaveTrailingReturnType);
1126+
TPR = TryParseFunctionDeclarator();
11461127
} else if (Tok.is(tok::l_square)) {
11471128
// direct-declarator '[' constant-expression[opt] ']'
11481129
// direct-abstract-declarator[opt] '[' constant-expression[opt] ']'
@@ -1409,16 +1390,6 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
14091390
return isCXXDeclarationSpecifier(ImplicitTypenameContext::Yes,
14101391
BracedCastResult, InvalidAsDeclSpec);
14111392

1412-
case tok::kw_auto: {
1413-
if (!getLangOpts().CPlusPlus23)
1414-
return TPResult::True;
1415-
if (NextToken().is(tok::l_brace))
1416-
return TPResult::False;
1417-
if (NextToken().is(tok::l_paren))
1418-
return TPResult::Ambiguous;
1419-
return TPResult::True;
1420-
}
1421-
14221393
case tok::coloncolon: { // ::foo::bar
14231394
const Token &Next = NextToken();
14241395
if (Next.isOneOf(tok::kw_new, // ::new
@@ -1452,6 +1423,7 @@ Parser::isCXXDeclarationSpecifier(ImplicitTypenameContext AllowImplicitTypename,
14521423
case tok::kw_static:
14531424
case tok::kw_extern:
14541425
case tok::kw_mutable:
1426+
case tok::kw_auto:
14551427
case tok::kw___thread:
14561428
case tok::kw_thread_local:
14571429
case tok::kw__Thread_local:
@@ -2051,10 +2023,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause(
20512023

20522024
// declarator
20532025
// abstract-declarator[opt]
2054-
TPR = TryParseDeclarator(/*mayBeAbstract=*/true,
2055-
/*mayHaveIdentifier=*/true,
2056-
/*mayHaveDirectInit=*/false,
2057-
/*mayHaveTrailingReturnType=*/true);
2026+
TPR = TryParseDeclarator(true/*mayBeAbstract*/);
20582027
if (TPR != TPResult::Ambiguous)
20592028
return TPR;
20602029

@@ -2108,8 +2077,7 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause(
21082077
/// exception-specification:
21092078
/// 'throw' '(' type-id-list[opt] ')'
21102079
///
2111-
Parser::TPResult
2112-
Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {
2080+
Parser::TPResult Parser::TryParseFunctionDeclarator() {
21132081
// The '(' is already parsed.
21142082

21152083
TPResult TPR = TryParseParameterDeclarationClause();
@@ -2154,19 +2122,6 @@ Parser::TryParseFunctionDeclarator(bool MayHaveTrailingReturnType) {
21542122
}
21552123
}
21562124

2157-
// attribute-specifier-seq
2158-
if (!TrySkipAttributes())
2159-
return TPResult::Ambiguous;
2160-
2161-
// trailing-return-type
2162-
if (Tok.is(tok::arrow) && MayHaveTrailingReturnType) {
2163-
if (TPR == TPResult::True)
2164-
return TPR;
2165-
ConsumeToken();
2166-
if (isCXXTypeId(TentativeCXXTypeIdContext::TypeIdInTrailingReturnType))
2167-
return TPResult::True;
2168-
}
2169-
21702125
return TPResult::Ambiguous;
21712126
}
21722127

clang/lib/Parse/Parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1950,7 +1950,7 @@ bool Parser::TryAnnotateTypeOrScopeToken(
19501950
assert((Tok.is(tok::identifier) || Tok.is(tok::coloncolon) ||
19511951
Tok.is(tok::kw_typename) || Tok.is(tok::annot_cxxscope) ||
19521952
Tok.is(tok::kw_decltype) || Tok.is(tok::annot_template_id) ||
1953-
Tok.is(tok::kw___super) || Tok.is(tok::kw_auto)) &&
1953+
Tok.is(tok::kw___super)) &&
19541954
"Cannot be a type or scope token!");
19551955

19561956
if (Tok.is(tok::kw_typename)) {

clang/test/Parser/cxx1z-decomposition.cpp

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
// RUN: %clang_cc1 -std=c++17 %s -verify=expected,cxx17 -fcxx-exceptions
2-
// RUN: %clang_cc1 -std=c++2b %s -verify=expected,cxx2b -fcxx-exceptions
1+
// RUN: %clang_cc1 -std=c++17 %s -verify -fcxx-exceptions
32
// RUN: not %clang_cc1 -std=c++17 %s -emit-llvm-only -fcxx-exceptions
43

54
struct S { int a, b, c; };
@@ -31,7 +30,7 @@ namespace ForRangeDecl {
3130
namespace OtherDecl {
3231
// A parameter-declaration is not a simple-declaration.
3332
// This parses as an array declaration.
34-
void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
33+
void f(auto [a, b, c]); // expected-error {{'auto' not allowed in function prototype}} expected-error {{'a'}}
3534

3635
void g() {
3736
// A condition is allowed as a Clang extension.
@@ -58,7 +57,7 @@ namespace OtherDecl {
5857
namespace GoodSpecifiers {
5958
void f() {
6059
int n[1];
61-
const volatile auto &[a] = n; // cxx2b-warning {{volatile qualifier in structured binding declaration is deprecated}}
60+
const volatile auto &[a] = n;
6261
}
6362
}
6463

@@ -68,8 +67,8 @@ namespace BadSpecifiers {
6867
struct S { int n; } s;
6968
void f() {
7069
// storage-class-specifiers
71-
static auto &[a] = n; // cxx17-warning {{declared 'static' is a C++20 extension}}
72-
thread_local auto &[b] = n; // cxx17-warning {{declared 'thread_local' is a C++20 extension}}
70+
static auto &[a] = n; // expected-warning {{declared 'static' is a C++20 extension}}
71+
thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++20 extension}}
7372
extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{declaration of block scope identifier with linkage cannot have an initializer}}
7473
struct S {
7574
mutable auto &[d] = n; // expected-error {{not permitted in this context}}
@@ -86,19 +85,16 @@ namespace BadSpecifiers {
8685
}
8786

8887
static constexpr inline thread_local auto &[j1] = n; // expected-error {{cannot be declared with 'constexpr inline' specifiers}}
89-
static thread_local auto &[j2] = n; // cxx17-warning {{declared with 'static thread_local' specifiers is a C++20 extension}}
88+
static thread_local auto &[j2] = n; // expected-warning {{declared with 'static thread_local' specifiers is a C++20 extension}}
9089

9190
inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}}
9291

9392
const int K = 5;
94-
auto ([c]) = s; // expected-error {{decomposition declaration cannot be declared with parentheses}}
9593
void g() {
9694
// defining-type-specifiers other than cv-qualifiers and 'auto'
9795
S [a] = s; // expected-error {{cannot be declared with type 'S'}}
9896
decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}}
99-
auto ([c2]) = s; // cxx17-error {{decomposition declaration cannot be declared with parenthese}} \
100-
// cxx2b-error {{use of undeclared identifier 'c2'}} \
101-
// cxx2b-error {{expected body of lambda expression}} \
97+
auto ([c]) = s; // expected-error {{cannot be declared with parentheses}}
10298

10399
// FIXME: This error is not very good.
104100
auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}

clang/test/Parser/cxx2b-auto-x.cpp

Lines changed: 4 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,7 @@ struct looks_like_declaration {
1818

1919
using T = looks_like_declaration *;
2020
void f() { T(&a)->n = 1; }
21-
void g() { auto(&a)->n = 0; } // cxx23-warning {{before C++23}} \
22-
// cxx20-error {{declaration of variable 'a' with deduced type 'auto (&)' requires an initializer}} \
23-
// cxx20-error {{expected ';' at end of declaration}}
24-
void h() { auto{&a}->n = 0; } // cxx23-warning {{before C++23}} \
25-
// cxx20-error {{expected unqualified-id}} \
26-
// cxx20-error {{expected expression}}
27-
28-
void e(auto (*p)(int y) -> decltype(y)) {}
29-
30-
struct M;
31-
struct S{
32-
S operator()();
33-
S* operator->();
34-
int N;
35-
int M;
36-
} s; // expected-note {{here}}
37-
38-
void test() {
39-
auto(s)()->N; // cxx23-warning {{expression result unused}} \
40-
// cxx23-warning {{before C++23}} \
41-
// cxx20-error {{unknown type name 'N'}}
42-
auto(s)()->M; // expected-error {{redefinition of 's' as different kind of symbol}}
43-
}
44-
45-
void test_paren() {
46-
int a = (auto(0)); // cxx23-warning {{before C++23}} \
47-
// cxx20-error {{expected expression}} \
48-
// cxx20-error {{expected ')'}} \
49-
// cxx20-note {{to match this '('}}
50-
int b = (auto{0}); // cxx23-warning {{before C++23}} \
51-
// cxx20-error {{expected expression}} \
52-
// cxx20-error {{expected ')'}} \
53-
// cxx20-note {{to match this '('}}
54-
}
21+
// FIXME: They should be deemed expressions without breaking function pointer
22+
// parameter declarations with trailing return types.
23+
// void g() { auto(&a)->n = 0; }
24+
// void h() { auto{&a}->n = 0; }

0 commit comments

Comments
 (0)