зеркало из https://github.com/microsoft/clang-1.git
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:
Родитель
b49a29f7e4
Коммит
2259286fc5
|
@ -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));
|
||||
};
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче