diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2014-04-14 16:03:22 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2014-04-14 16:03:22 +0000 |
commit | 35f9421c55aca8b5805e40e006c203246e7f873f (patch) | |
tree | 2baf0f134b1378c880e62911a1d1d6d63d0ead9b /clang/lib | |
parent | 1d3ae27f011d9216b058e82f21f4e4e7e4c0df84 (diff) | |
download | bcm5719-llvm-35f9421c55aca8b5805e40e006c203246e7f873f.tar.gz bcm5719-llvm-35f9421c55aca8b5805e40e006c203246e7f873f.zip |
Properly diagnose standard C++ attributes which have optional argument lists when the arguments are elided. eg)
[[deprecated()]] // error
[[deprecated]] // OK
[[deprecated("")]] // OK
[[gnu::deprecated()]] // OK
llvm-svn: 206186
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 6 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDeclCXX.cpp | 38 |
2 files changed, 33 insertions, 11 deletions
diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 331c5e42fdb..720a68c5ba1 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -261,7 +261,7 @@ void Parser::ParseAttributeWithTypeArg(IdentifierInfo &AttrName, 0, AttrNameLoc, 0, 0, AttributeList::AS_GNU); } -void Parser::ParseAttributeArgsCommon( +unsigned Parser::ParseAttributeArgsCommon( IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, AttributeList::Syntax Syntax) { @@ -302,7 +302,7 @@ void Parser::ParseAttributeArgsCommon( ExprResult ArgExpr(ParseAssignmentExpression()); if (ArgExpr.isInvalid()) { SkipUntil(tok::r_paren, StopAtSemi); - return; + return 0; } ArgExprs.push_back(ArgExpr.release()); // Eat the comma, move to the next argument @@ -318,6 +318,8 @@ void Parser::ParseAttributeArgsCommon( if (EndLoc) *EndLoc = RParen; + + return static_cast<unsigned>(ArgExprs.size()); } /// Parse the arguments to a parameterized GNU attribute or diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index a04b33c6270..94d46eff1df 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -3194,6 +3194,7 @@ static bool IsBuiltInOrStandardCXX11Attribute(IdentifierInfo *AttrName, switch (AttributeList::getKind(AttrName, ScopeName, AttributeList::AS_CXX11)) { case AttributeList::AT_CarriesDependency: + case AttributeList::AT_Deprecated: case AttributeList::AT_FallThrough: case AttributeList::AT_CXX11NoReturn: { return true; @@ -3225,6 +3226,7 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, IdentifierInfo *ScopeName, SourceLocation ScopeLoc) { assert(Tok.is(tok::l_paren) && "Not a C++11 attribute argument list"); + SourceLocation LParenLoc = Tok.getLocation(); // If the attribute isn't known, we will not attempt to parse any // arguments. @@ -3241,9 +3243,32 @@ bool Parser::ParseCXX11AttributeArgs(IdentifierInfo *AttrName, // behaviors. ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, ScopeLoc, AttributeList::AS_CXX11, 0); - else - ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, ScopeName, - ScopeLoc, AttributeList::AS_CXX11); + else { + unsigned NumArgs = + ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, EndLoc, + ScopeName, ScopeLoc, AttributeList::AS_CXX11); + + const AttributeList *Attr = Attrs.getList(); + if (Attr && IsBuiltInOrStandardCXX11Attribute(AttrName, ScopeName)) { + // If the attribute is a standard or built-in attribute and we are + // parsing an argument list, we need to determine whether this attribute + // was allowed to have an argument list (such as [[deprecated]]), and how + // many arguments were parsed (so we can diagnose on [[deprecated()]]). + if (Attr->getMaxArgs() && !NumArgs) { + // The attribute was allowed to have arguments, but none were provided + // even though the attribute parsed successfully. This is an error. + Diag(LParenLoc, diag::err_attribute_requires_arguements) << AttrName; + return false; + } else if (!Attr->getMaxArgs()) { + // The attribute parsed successfully, but was not allowed to have any + // arguments. It doesn't matter whether any were provided -- the + // presence of the argument list (even if empty) is diagnosed. + Diag(LParenLoc, diag::err_cxx11_attribute_forbids_arguments) + << AttrName; + return false; + } + } + } return true; } @@ -3324,14 +3349,9 @@ void Parser::ParseCXX11AttributeSpecifier(ParsedAttributes &attrs, << AttrName << SourceRange(SeenAttrs[AttrName]); // Parse attribute arguments - if (Tok.is(tok::l_paren)) { - if (StandardAttr) - Diag(Tok.getLocation(), diag::err_cxx11_attribute_forbids_arguments) - << AttrName->getName(); - + if (Tok.is(tok::l_paren)) AttrParsed = ParseCXX11AttributeArgs(AttrName, AttrLoc, attrs, endLoc, ScopeName, ScopeLoc); - } if (!AttrParsed) attrs.addNew(AttrName, |