diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-10 01:32:12 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-04-10 01:32:12 +0000 |
commit | 7bdcc4a9da8ccbafb15872083f551366cdaf3b51 (patch) | |
tree | bb52354737aeaa0e413fe20cb96e321ba9e47aac /clang/lib/Parse/ParseDeclCXX.cpp | |
parent | 076b3041c0706a957766f7e5e885f05b2eaf255e (diff) | |
download | bcm5719-llvm-7bdcc4a9da8ccbafb15872083f551366cdaf3b51.tar.gz bcm5719-llvm-7bdcc4a9da8ccbafb15872083f551366cdaf3b51.zip |
Disambiguation of '[[':
* In C++11, '[[' is ill-formed unless it starts an attribute-specifier. Reject
array sizes and array indexes which begin with a lambda-expression. Recover by
parsing the lambda as a lambda.
* In Objective-C++11, either '[' could be the start of a message-send.
Fully disambiguate this case: it turns out that the grammars of message-sends,
lambdas and attributes do not actually overlap. Accept any occurrence of '[['
where either '[' starts a message send, but reject a lambda in an array index
just like in C++11 mode.
Implement a couple of changes to the attribute wording which occurred after our
attributes implementation landed:
* In a function-declaration, the attributes go after the exception specification,
not after the right paren.
* A reference type can have attributes applied.
* An 'identifier' in an attribute can also be a keyword. Support for alternative
tokens (iso646 keywords) in attributes to follow.
And some bug fixes:
* Parse attributes after declarator-ids, even if they are not simple identifiers.
* Do not accept attributes after a parenthesized declarator.
* Accept attributes after an array size in a new-type-id.
* Partially disamiguate 'delete' followed by a lambda. More work is required
here for the case where the lambda-introducer is '[]'.
llvm-svn: 154369
Diffstat (limited to 'clang/lib/Parse/ParseDeclCXX.cpp')
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 39 |
1 files changed, 23 insertions, 16 deletions
diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index 9321c137fba..10ed3b1516e 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -2736,38 +2736,38 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) { Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope(); } -/// ParseCXX0XAttributeSpecifier - Parse a C++0x attribute-specifier. Currently +/// ParseCXX0XAttributeSpecifier - Parse a C++11 attribute-specifier. Currently /// only parses standard attributes. /// -/// [C++0x] attribute-specifier: +/// [C++11] attribute-specifier: /// '[' '[' attribute-list ']' ']' /// alignment-specifier /// -/// [C++0x] attribute-list: +/// [C++11] attribute-list: /// attribute[opt] /// attribute-list ',' attribute[opt] /// -/// [C++0x] attribute: +/// [C++11] attribute: /// attribute-token attribute-argument-clause[opt] /// -/// [C++0x] attribute-token: +/// [C++11] attribute-token: /// identifier /// attribute-scoped-token /// -/// [C++0x] attribute-scoped-token: +/// [C++11] attribute-scoped-token: /// attribute-namespace '::' identifier /// -/// [C++0x] attribute-namespace: +/// [C++11] attribute-namespace: /// identifier /// -/// [C++0x] attribute-argument-clause: +/// [C++11] attribute-argument-clause: /// '(' balanced-token-seq ')' /// -/// [C++0x] balanced-token-seq: +/// [C++11] balanced-token-seq: /// balanced-token /// balanced-token-seq balanced-token /// -/// [C++0x] balanced-token: +/// [C++11] balanced-token: /// '(' balanced-token-seq ')' /// '[' balanced-token-seq ']' /// '{' balanced-token-seq '}' @@ -2781,7 +2781,7 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, } assert(Tok.is(tok::l_square) && NextToken().is(tok::l_square) - && "Not a C++0x attribute list"); + && "Not a C++11 attribute list"); Diag(Tok.getLocation(), diag::warn_cxx98_compat_attribute); @@ -2793,7 +2793,11 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, ConsumeToken(); } - while (Tok.is(tok::identifier) || Tok.is(tok::comma)) { + // C++11 [dcl.attr.grammar]p3: If a keyword or an alternative token that + // satisfies the syntactic requirements of an identifier is contained in an + // attribute-token, it is considered an identifier. + // FIXME: Support alternative tokens here. + while (Tok.getIdentifierInfo() || Tok.is(tok::comma)) { // attribute not present if (Tok.is(tok::comma)) { ConsumeToken(); @@ -2807,7 +2811,7 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, if (Tok.is(tok::coloncolon)) { ConsumeToken(); - if (!Tok.is(tok::identifier)) { + if (!Tok.getIdentifierInfo()) { Diag(Tok.getLocation(), diag::err_expected_ident); SkipUntil(tok::r_square, tok::comma, true, true); continue; @@ -2824,8 +2828,7 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, // No scoped names are supported; ideally we could put all non-standard // attributes into namespaces. if (!ScopeName) { - switch(AttributeList::getKind(AttrName)) - { + switch (AttributeList::getKind(AttrName)) { // No arguments case AttributeList::AT_carries_dependency: case AttributeList::AT_noreturn: { @@ -2852,6 +2855,9 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs, // SkipUntil maintains the balancedness of tokens. SkipUntil(tok::r_paren, false); } + + if (Tok.is(tok::ellipsis)) + ConsumeToken(); } if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare)) @@ -2874,7 +2880,7 @@ void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs, do { ParseCXX0XAttributeSpecifier(attrs, endLoc); - } while (isCXX0XAttributeSpecifier()); + } while (isCXX11AttributeSpecifier()); attrs.Range = SourceRange(StartLoc, *endLoc); } @@ -2892,6 +2898,7 @@ void Parser::ParseMicrosoftAttributes(ParsedAttributes &attrs, assert(Tok.is(tok::l_square) && "Not a Microsoft attribute list"); while (Tok.is(tok::l_square)) { + // FIXME: If this is actually a C++11 attribute, parse it as one. ConsumeBracket(); SkipUntil(tok::r_square, true, true); if (endLoc) *endLoc = Tok.getLocation(); |