summaryrefslogtreecommitdiffstats
path: root/lib/Parse
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-04-10 03:25:07 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-04-10 03:25:07 +0000
commitc56298d87a9df507805a548d7d515e8b511df2c0 (patch)
treebd9d2feb4342dc9d8f7dc063b99b0e6be9ab29d0 /lib/Parse
parent6ee326af4e77e6f05973486097884d7431f2108d (diff)
Parsing of C++11 attributes:
* Alternative tokens (such as 'compl') are treated as identifiers in attribute names. * An attribute-list can start with a comma. * An ellipsis may not be used with either of our currently-supported C++11 attributes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@154381 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Parse')
-rw-r--r--lib/Parse/ParseDecl.cpp6
-rw-r--r--lib/Parse/ParseDeclCXX.cpp94
-rw-r--r--lib/Parse/ParseTentative.cpp7
3 files changed, 74 insertions, 33 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 9bafa92d7f..969e0b21b0 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -3486,11 +3486,11 @@ bool Parser::isConstructorDeclarator() {
///
void Parser::ParseTypeQualifierListOpt(DeclSpec &DS,
bool VendorAttributesAllowed,
- bool CXX0XAttributesAllowed) {
- if (getLangOpts().CPlusPlus0x && CXX0XAttributesAllowed &&
+ bool CXX11AttributesAllowed) {
+ if (getLangOpts().CPlusPlus0x && CXX11AttributesAllowed &&
isCXX11AttributeSpecifier()) {
ParsedAttributesWithRange attrs(AttrFactory);
- ParseCXX0XAttributes(attrs);
+ ParseCXX11Attributes(attrs);
DS.takeAttributesFrom(attrs);
}
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 10ed3b1516..b2a65ff0f3 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -2736,7 +2736,49 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
Victim->TemplateScope = getCurScope()->getParent()->isTemplateParamScope();
}
-/// ParseCXX0XAttributeSpecifier - Parse a C++11 attribute-specifier. Currently
+/// \brief Try to parse an 'identifier' which appears within an attribute-token.
+///
+/// \return the parsed identifier on success, and 0 if the next token is not an
+/// attribute-token.
+///
+/// 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.
+IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
+ switch (Tok.getKind()) {
+ default:
+ // Identifiers and keywords have identifier info attached.
+ if (IdentifierInfo *II = Tok.getIdentifierInfo()) {
+ Loc = ConsumeToken();
+ return II;
+ }
+ return 0;
+
+ case tok::ampamp: // 'and'
+ case tok::pipe: // 'bitor'
+ case tok::pipepipe: // 'or'
+ case tok::caret: // 'xor'
+ case tok::tilde: // 'compl'
+ case tok::amp: // 'bitand'
+ case tok::ampequal: // 'and_eq'
+ case tok::pipeequal: // 'or_eq'
+ case tok::caretequal: // 'xor_eq'
+ case tok::exclaim: // 'not'
+ case tok::exclaimequal: // 'not_eq'
+ // Alternative tokens do not have identifier info, but their spelling
+ // starts with an alphabetical character.
+ llvm::SmallString<8> SpellingBuf;
+ StringRef Spelling = PP.getSpelling(Tok.getLocation(), SpellingBuf);
+ if (std::isalpha(Spelling[0])) {
+ Loc = ConsumeToken();
+ return &PP.getIdentifierTable().get(Spelling.data());
+ }
+ return 0;
+ }
+}
+
+/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
/// only parses standard attributes.
///
/// [C++11] attribute-specifier:
@@ -2746,6 +2788,8 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
/// [C++11] attribute-list:
/// attribute[opt]
/// attribute-list ',' attribute[opt]
+/// attribute '...'
+/// attribute-list ',' attribute '...'
///
/// [C++11] attribute:
/// attribute-token attribute-argument-clause[opt]
@@ -2772,7 +2816,7 @@ void Parser::PopParsingClass(Sema::ParsingClassState state) {
/// '[' balanced-token-seq ']'
/// '{' balanced-token-seq '}'
/// any token but '(', ')', '[', ']', '{', or '}'
-void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
+void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
SourceLocation *endLoc) {
if (Tok.is(tok::kw_alignas)) {
Diag(Tok.getLocation(), diag::warn_cxx98_compat_alignas);
@@ -2788,40 +2832,34 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
ConsumeBracket();
ConsumeBracket();
- if (Tok.is(tok::comma)) {
- Diag(Tok.getLocation(), diag::err_expected_ident);
- ConsumeToken();
- }
-
- // 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)) {
+ while (Tok.isNot(tok::r_square)) {
// attribute not present
if (Tok.is(tok::comma)) {
ConsumeToken();
continue;
}
- IdentifierInfo *ScopeName = 0, *AttrName = Tok.getIdentifierInfo();
- SourceLocation ScopeLoc, AttrLoc = ConsumeToken();
+ SourceLocation ScopeLoc, AttrLoc;
+ IdentifierInfo *ScopeName = 0, *AttrName = 0;
+
+ AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
+ if (!AttrName)
+ // Break out to the "expected ']'" diagnostic.
+ break;
// scoped attribute
if (Tok.is(tok::coloncolon)) {
ConsumeToken();
- if (!Tok.getIdentifierInfo()) {
+ ScopeName = AttrName;
+ ScopeLoc = AttrLoc;
+
+ AttrName = TryParseCXX11AttributeIdentifier(AttrLoc);
+ if (!AttrName) {
Diag(Tok.getLocation(), diag::err_expected_ident);
SkipUntil(tok::r_square, tok::comma, true, true);
continue;
}
-
- ScopeName = AttrName;
- ScopeLoc = AttrLoc;
-
- AttrName = Tok.getIdentifierInfo();
- AttrLoc = ConsumeToken();
}
bool AttrParsed = false;
@@ -2833,7 +2871,7 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
case AttributeList::AT_carries_dependency:
case AttributeList::AT_noreturn: {
if (Tok.is(tok::l_paren)) {
- Diag(Tok.getLocation(), diag::err_cxx0x_attribute_forbids_arguments)
+ Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
<< AttrName->getName();
break;
}
@@ -2856,8 +2894,12 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
SkipUntil(tok::r_paren, false);
}
- if (Tok.is(tok::ellipsis))
+ if (Tok.is(tok::ellipsis)) {
+ if (AttrParsed)
+ Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
+ << AttrName->getName();
ConsumeToken();
+ }
}
if (ExpectAndConsume(tok::r_square, diag::err_expected_rsquare))
@@ -2868,18 +2910,18 @@ void Parser::ParseCXX0XAttributeSpecifier(ParsedAttributes &attrs,
SkipUntil(tok::r_square, false);
}
-/// ParseCXX0XAttributes - Parse a C++0x attribute-specifier-seq.
+/// ParseCXX11Attributes - Parse a C++0x attribute-specifier-seq.
///
/// attribute-specifier-seq:
/// attribute-specifier-seq[opt] attribute-specifier
-void Parser::ParseCXX0XAttributes(ParsedAttributesWithRange &attrs,
+void Parser::ParseCXX11Attributes(ParsedAttributesWithRange &attrs,
SourceLocation *endLoc) {
SourceLocation StartLoc = Tok.getLocation(), Loc;
if (!endLoc)
endLoc = &Loc;
do {
- ParseCXX0XAttributeSpecifier(attrs, endLoc);
+ ParseCXX11AttributeSpecifier(attrs, endLoc);
} while (isCXX11AttributeSpecifier());
attrs.Range = SourceRange(StartLoc, *endLoc);
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 18bc0ddc5b..5ce6b2b91c 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -485,18 +485,17 @@ Parser::isCXX11AttributeSpecifier(bool Disambiguate,
// 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.
- if (!Tok.getIdentifierInfo()) {
+ SourceLocation Loc;
+ if (!TryParseCXX11AttributeIdentifier(Loc)) {
IsAttribute = false;
break;
}
- ConsumeToken();
if (Tok.is(tok::coloncolon)) {
ConsumeToken();
- if (!Tok.getIdentifierInfo()) {
+ if (!TryParseCXX11AttributeIdentifier(Loc)) {
IsAttribute = false;
break;
}
- ConsumeToken();
}
// Parse the attribute-argument-clause, if present.