From 2259286fc5c1514089b17ec93e26ca56ba8ac2b6 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 27 Mar 2012 23:05:05 +0000 Subject: [PATCH] If we see '(...' where we're expecting an abstract-declarator, that doesn't necessarily mean we've found a function declarator. If the next token is not a ')', this is actually a parenthesized pack expansion. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@153544 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Parse/ParseDecl.cpp | 11 +++++++---- lib/Parse/ParseTentative.cpp | 13 ++++++++++--- test/Parser/cxx0x-ambig.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 9d8aed5333..9aa5eaba00 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -3354,15 +3354,17 @@ bool Parser::isConstructorDeclarator() { return false; } - // Current class name must be followed by a left parentheses. + // Current class name must be followed by a left parenthesis. if (Tok.isNot(tok::l_paren)) { TPA.Revert(); return false; } ConsumeParen(); - // A right parentheses or ellipsis signals that we have a constructor. - if (Tok.is(tok::r_paren) || Tok.is(tok::ellipsis)) { + // A right parenthesis, or ellipsis followed by a right parenthesis signals + // that we have a constructor. + if (Tok.is(tok::r_paren) || + (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren))) { TPA.Revert(); return true; } @@ -3948,7 +3950,8 @@ void Parser::ParseParenDeclarator(Declarator &D) { // paren, because we haven't seen the identifier yet. isGrouping = true; } else if (Tok.is(tok::r_paren) || // 'int()' is a function. - (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis)) || // C++ int(...) + (getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) && + NextToken().is(tok::r_paren)) || // C++ int(...) isDeclarationSpecifier()) { // 'int(int)' is a function. // This handles C99 6.7.5.3p11: in "typedef int X; void foo(X)", X is // considered to be a type, not a K&R identifier-list. diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp index 1e30c7fff6..e3b922500f 100644 --- a/lib/Parse/ParseTentative.cpp +++ b/lib/Parse/ParseTentative.cpp @@ -553,7 +553,8 @@ Parser::TPResult Parser::TryParseDeclarator(bool mayBeAbstract, ConsumeParen(); if (mayBeAbstract && (Tok.is(tok::r_paren) || // 'int()' is a function. - Tok.is(tok::ellipsis) || // 'int(...)' is a function. + // 'int(...)' is a function. + (Tok.is(tok::ellipsis) && NextToken().is(tok::r_paren)) || isDeclarationSpecifier())) { // 'int(int)' is a function. // '(' parameter-declaration-clause ')' cv-qualifier-seq[opt] // exception-specification[opt] @@ -1236,7 +1237,10 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() { // '...'[opt] if (Tok.is(tok::ellipsis)) { ConsumeToken(); - return TPResult::True(); // '...' is a sign of a function declarator. + if (Tok.is(tok::r_paren)) + return TPResult::True(); // '...)' is a sign of a function declarator. + else + return TPResult::False(); } ParsedAttributes attrs(AttrFactory); @@ -1269,7 +1273,10 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() { if (Tok.is(tok::ellipsis)) { ConsumeToken(); - return TPResult::True(); // '...' is a sign of a function declarator. + if (Tok.is(tok::r_paren)) + return TPResult::True(); // '...)' is a sign of a function declarator. + else + return TPResult::False(); } if (Tok.isNot(tok::comma)) diff --git a/test/Parser/cxx0x-ambig.cpp b/test/Parser/cxx0x-ambig.cpp index d4cbfeab75..98757b48c7 100644 --- a/test/Parser/cxx0x-ambig.cpp +++ b/test/Parser/cxx0x-ambig.cpp @@ -100,3 +100,28 @@ namespace trailing_return { } } } + +namespace ellipsis { + template + struct S { + void e(S::S()); + void f(S(...args[sizeof(T)])); // expected-note {{here}} + void f(S(...args)[sizeof(T)]); // expected-error {{redeclared}} expected-note {{here}} + void f(S ...args[sizeof(T)]); // expected-error {{redeclared}} + void g(S(...[sizeof(T)])); // expected-note {{here}} + void g(S(...)[sizeof(T)]); // expected-error {{function cannot return array type}} + void g(S ...[sizeof(T)]); // expected-error {{redeclared}} + void h(T(...)); // function type, expected-error {{unexpanded parameter pack}} + void h(T...); // pack expansion, ok + void i(int(T...)); // expected-note {{here}} + void i(int(T...a)); // expected-error {{redeclared}} + void i(int(T, ...)); // function type, expected-error {{unexpanded parameter pack}} + void i(int(T, ...a)); // expected-error {{expected ')'}} expected-note {{to match}} expected-error {{unexpanded parameter pack}} + void j(int(int...)); // function type, ok + void j(int(int...a)); // expected-error {{does not contain any unexpanded parameter packs}} + void j(T(int...)); // expected-error {{unexpanded parameter pack}} + void j(T(T...)); // expected-error {{unexpanded parameter pack}} + void k(int(...)(T)); // expected-error {{cannot return function type}} + void k(int ...(T)); + }; +} -- 2.40.0