diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Parse/ParseDecl.cpp | 23 | ||||
-rw-r--r-- | lib/Parse/ParseDeclCXX.cpp | 65 | ||||
-rw-r--r-- | lib/Sema/SemaStmtAttr.cpp | 9 |
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; |