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
This commit is contained in:
Richard Smith 2012-03-27 23:05:05 +00:00
Родитель b49a29f7e4
Коммит 2259286fc5
3 изменённых файлов: 42 добавлений и 7 удалений

Просмотреть файл

@ -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.

Просмотреть файл

@ -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))

Просмотреть файл

@ -100,3 +100,28 @@ namespace trailing_return {
}
}
}
namespace ellipsis {
template<typename...T>
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));
};
}