aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Parse/ParseDecl.cpp23
-rw-r--r--lib/Parse/ParseDeclCXX.cpp65
-rw-r--r--lib/Sema/SemaStmtAttr.cpp9
3 files changed, 58 insertions, 39 deletions
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 674cd2d22f..e90d0eb9fe 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -154,7 +154,8 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
Eof.setLocation(Tok.getLocation());
LA->Toks.push_back(Eof);
} else {
- ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc);
+ ParseGNUAttributeArgs(AttrName, AttrNameLoc, attrs, endLoc,
+ 0, AttrNameLoc, AttributeList::AS_GNU);
}
} else {
attrs.addNew(AttrName, AttrNameLoc, 0, AttrNameLoc,
@@ -173,11 +174,15 @@ void Parser::ParseGNUAttributes(ParsedAttributes &attrs,
}
-/// Parse the arguments to a parameterized GNU attribute
+/// Parse the arguments to a parameterized GNU attribute or
+/// a C++11 attribute in "gnu" namespace.
void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
SourceLocation AttrNameLoc,
ParsedAttributes &Attrs,
- SourceLocation *EndLoc) {
+ SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName,
+ SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax) {
assert(Tok.is(tok::l_paren) && "Attribute arg list not starting with '('");
@@ -278,9 +283,9 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName,
SourceLocation RParen = Tok.getLocation();
if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) {
AttributeList *attr =
- Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen), 0, AttrNameLoc,
- ParmName, ParmLoc, ArgExprs.data(), ArgExprs.size(),
- AttributeList::AS_GNU);
+ Attrs.addNew(AttrName, SourceRange(AttrNameLoc, RParen),
+ ScopeName, ScopeLoc, ParmName, ParmLoc,
+ ArgExprs.data(), ArgExprs.size(), Syntax);
if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection)
Diag(Tok, diag::err_iboutletcollection_builtintype);
}
@@ -923,7 +928,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
if (HasFunScope)
Actions.ActOnReenterFunctionContext(Actions.CurScope, D);
- ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
+ ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
+ 0, LA.AttrNameLoc, AttributeList::AS_GNU);
if (HasFunScope) {
Actions.ActOnExitFunctionContext();
@@ -935,7 +941,8 @@ void Parser::ParseLexedAttribute(LateParsedAttribute &LA,
} else {
// If there are multiple decls, then the decl cannot be within the
// function scope.
- ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc);
+ ParseGNUAttributeArgs(&LA.AttrName, LA.AttrNameLoc, Attrs, &endLoc,
+ 0, LA.AttrNameLoc, AttributeList::AS_GNU);
}
} else {
Diag(Tok, diag::warn_attribute_no_decl) << LA.AttrName.getName();
diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp
index 6fee37dc02..7e1e8ce10e 100644
--- a/lib/Parse/ParseDeclCXX.cpp
+++ b/lib/Parse/ParseDeclCXX.cpp
@@ -2879,6 +2879,21 @@ IdentifierInfo *Parser::TryParseCXX11AttributeIdentifier(SourceLocation &Loc) {
}
}
+static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName,
+ IdentifierInfo *ScopeName) {
+ switch (AttributeList::getKind(AttrName, ScopeName,
+ AttributeList::AS_CXX11)) {
+ case AttributeList::AT_CarriesDependency:
+ case AttributeList::AT_FallThrough:
+ case AttributeList::AT_NoReturn: {
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
/// ParseCXX11AttributeSpecifier - Parse a C++11 attribute-specifier. Currently
/// only parses standard attributes.
///
@@ -2963,46 +2978,38 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs,
}
}
+ bool StandardAttr = IsBuiltInOrStandardCXX11Attribute(AttrName,ScopeName);
bool AttrParsed = false;
- switch (AttributeList::getKind(AttrName, ScopeName,
- AttributeList::AS_CXX11)) {
- // No arguments
- case AttributeList::AT_CarriesDependency:
- // FIXME: implement generic support of attributes with C++11 syntax
- // see Parse/ParseDecl.cpp: ParseGNUAttributes
- case AttributeList::AT_FallThrough:
- case AttributeList::AT_NoReturn: {
- if (Tok.is(tok::l_paren)) {
- Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
- << AttrName->getName();
- break;
+
+ // Parse attribute arguments
+ if (Tok.is(tok::l_paren)) {
+ if (ScopeName && ScopeName->getName() == "gnu") {
+ ParseGNUAttributeArgs(AttrName, AttrLoc, attrs, endLoc,
+ ScopeName, ScopeLoc, AttributeList::AS_CXX11);
+ AttrParsed = true;
+ } else {
+ if (StandardAttr)
+ Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments)
+ << AttrName->getName();
+
+ // FIXME: handle other formats of c++11 attribute arguments
+ ConsumeParen();
+ SkipUntil(tok::r_paren, false);
}
+ }
+ if (!AttrParsed)
attrs.addNew(AttrName,
SourceRange(ScopeLoc.isValid() ? ScopeLoc : AttrLoc,
AttrLoc),
ScopeName, ScopeLoc, 0,
SourceLocation(), 0, 0, AttributeList::AS_CXX11);
- AttrParsed = true;
- break;
- }
-
- // Silence warnings
- default: break;
- }
-
- // Skip the entire parameter clause, if any
- if (!AttrParsed && Tok.is(tok::l_paren)) {
- ConsumeParen();
- // SkipUntil maintains the balancedness of tokens.
- SkipUntil(tok::r_paren, false);
- }
if (Tok.is(tok::ellipsis)) {
- if (AttrParsed)
- Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
- << AttrName->getName();
ConsumeToken();
+
+ Diag(Tok, diag::err_cxx11_attribute_forbids_ellipsis)
+ << AttrName->getName();
}
}
diff --git a/lib/Sema/SemaStmtAttr.cpp b/lib/Sema/SemaStmtAttr.cpp
index 3c15b7a8af..b268b4502c 100644
--- a/lib/Sema/SemaStmtAttr.cpp
+++ b/lib/Sema/SemaStmtAttr.cpp
@@ -48,11 +48,16 @@ static Attr *handleFallThroughAttr(Sema &S, Stmt *St, const AttributeList &A,
static Attr *ProcessStmtAttribute(Sema &S, Stmt *St, const AttributeList &A,
SourceRange Range) {
switch (A.getKind()) {
+ case AttributeList::UnknownAttribute:
+ S.Diag(A.getLoc(), A.isDeclspecAttribute() ?
+ diag::warn_unhandled_ms_attribute_ignored :
+ diag::warn_unknown_attribute_ignored) << A.getName();
+ return 0;
case AttributeList::AT_FallThrough:
return handleFallThroughAttr(S, St, A, Range);
default:
- // if we're here, then we parsed an attribute, but didn't recognize it as a
- // statement attribute => it is declaration attribute
+ // if we're here, then we parsed a known attribute, but didn't recognize
+ // it as a statement attribute => it is declaration attribute
S.Diag(A.getRange().getBegin(), diag::warn_attribute_invalid_on_stmt)
<< A.getName()->getName() << St->getLocStart();
return 0;