зеркало из https://github.com/microsoft/clang-1.git
Support C++11 attributes at the start of a parameter-declaration.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154476 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
9793428697
Коммит
6ce48a70ac
|
@ -4038,7 +4038,8 @@ void Parser::ParseParenDeclarator(Declarator &D) {
|
|||
} else if (Tok.is(tok::r_paren) || // 'int()' is a function.
|
||||
(getLangOpts().CPlusPlus && Tok.is(tok::ellipsis) &&
|
||||
NextToken().is(tok::r_paren)) || // C++ int(...)
|
||||
isDeclarationSpecifier()) { // 'int(int)' is a function.
|
||||
isDeclarationSpecifier() || // 'int(int)' is a function.
|
||||
isCXX11AttributeSpecifier()) { // '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.
|
||||
isGrouping = false;
|
||||
|
@ -4318,9 +4319,9 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
|
|||
/// after the opening parenthesis. This function will not parse a K&R-style
|
||||
/// identifier list.
|
||||
///
|
||||
/// D is the declarator being parsed. If attrs is non-null, then the caller
|
||||
/// parsed those arguments immediately after the open paren - they should be
|
||||
/// considered to be the first argument of a parameter.
|
||||
/// D is the declarator being parsed. If FirstArgAttrs is non-null, then the
|
||||
/// caller parsed those arguments immediately after the open paren - they should
|
||||
/// be considered to be part of the first parameter.
|
||||
///
|
||||
/// After returning, ParamInfo will hold the parsed parameters. EllipsisLoc will
|
||||
/// be the location of the ellipsis, if any was parsed.
|
||||
|
@ -4343,15 +4344,18 @@ void Parser::ParseFunctionDeclaratorIdentifierList(
|
|||
/// [C++] declaration-specifiers abstract-declarator[opt]
|
||||
/// '=' assignment-expression
|
||||
/// [GNU] declaration-specifiers abstract-declarator[opt] attributes
|
||||
/// [C++11] attribute-specifier-seq parameter-declaration
|
||||
///
|
||||
void Parser::ParseParameterDeclarationClause(
|
||||
Declarator &D,
|
||||
ParsedAttributes &attrs,
|
||||
ParsedAttributes &FirstArgAttrs,
|
||||
SmallVector<DeclaratorChunk::ParamInfo, 16> &ParamInfo,
|
||||
SourceLocation &EllipsisLoc) {
|
||||
|
||||
while (1) {
|
||||
if (Tok.is(tok::ellipsis)) {
|
||||
// FIXME: Issue a diagnostic if we parsed an attribute-specifier-seq
|
||||
// before deciding this was a parameter-declaration-clause.
|
||||
EllipsisLoc = ConsumeToken(); // Consume the ellipsis.
|
||||
break;
|
||||
}
|
||||
|
@ -4360,6 +4364,9 @@ void Parser::ParseParameterDeclarationClause(
|
|||
// Just use the ParsingDeclaration "scope" of the declarator.
|
||||
DeclSpec DS(AttrFactory);
|
||||
|
||||
// Parse any C++11 attributes.
|
||||
MaybeParseCXX0XAttributes(DS.getAttributes());
|
||||
|
||||
// Skip any Microsoft attributes before a param.
|
||||
if (getLangOpts().MicrosoftExt && Tok.is(tok::l_square))
|
||||
ParseMicrosoftAttributes(DS.getAttributes());
|
||||
|
@ -4368,12 +4375,10 @@ void Parser::ParseParameterDeclarationClause(
|
|||
|
||||
// If the caller parsed attributes for the first argument, add them now.
|
||||
// Take them so that we only apply the attributes to the first parameter.
|
||||
// FIXME: If we saw an ellipsis first, this code is not reached. Are the
|
||||
// attributes lost? Should they even be allowed?
|
||||
// FIXME: If we can leave the attributes in the token stream somehow, we can
|
||||
// get rid of a parameter (attrs) and this statement. It might be too much
|
||||
// hassle.
|
||||
DS.takeAttributesFrom(attrs);
|
||||
// get rid of a parameter (FirstArgAttrs) and this statement. It might be
|
||||
// too much hassle.
|
||||
DS.takeAttributesFrom(FirstArgAttrs);
|
||||
|
||||
ParseDeclarationSpecifiers(DS);
|
||||
|
||||
|
|
|
@ -1322,6 +1322,11 @@ Parser::TPResult Parser::TryParseParameterDeclarationClause() {
|
|||
return TPResult::False();
|
||||
}
|
||||
|
||||
// An attribute-specifier-seq here is a sign of a function declarator.
|
||||
if (isCXX11AttributeSpecifier(/*Disambiguate*/false,
|
||||
/*OuterMightBeMessageSend*/true))
|
||||
return TPResult::True();
|
||||
|
||||
ParsedAttributes attrs(AttrFactory);
|
||||
MaybeParseMicrosoftAttributes(attrs);
|
||||
|
||||
|
|
|
@ -71,6 +71,10 @@ void foo () {
|
|||
(void)s.arr[ [] { return 0; }() ]; // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}}
|
||||
int n = __builtin_offsetof(S, arr[ [] { return 0; }() ]); // expected-error {{C++11 only allows consecutive left square brackets when introducing an attribute}}
|
||||
|
||||
void bar [[noreturn]] ([[]] int i, [[]] int j);
|
||||
using FuncType = void ([[]] int);
|
||||
void baz([[]]...); // expected-error {{expected parameter declarator}}
|
||||
|
||||
[[]] return;
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,18 @@ void f(X *noreturn) {
|
|||
[[int(), noreturn]];
|
||||
[[class, test(foo 'x' bar),,,]];
|
||||
[[bitand, noreturn]];
|
||||
|
||||
[[noreturn]]int(e)();
|
||||
|
||||
// A function taking a noreturn function.
|
||||
int(f)([[noreturn]] int());
|
||||
f(e);
|
||||
|
||||
// Variables initialized by a message send.
|
||||
int(g)([[noreturn getSelf] getSize]);
|
||||
int(h)([[noreturn]{return noreturn;}() getSize]);
|
||||
|
||||
int i = g + h;
|
||||
}
|
||||
|
||||
template<typename...Ts> void f(Ts ...x) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче