summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAaron Ballman <aaron@aaronballman.com>2014-04-14 16:03:22 +0000
committerAaron Ballman <aaron@aaronballman.com>2014-04-14 16:03:22 +0000
commit35f9421c55aca8b5805e40e006c203246e7f873f (patch)
tree2baf0f134b1378c880e62911a1d1d6d63d0ead9b /clang/lib
parent1d3ae27f011d9216b058e82f21f4e4e7e4c0df84 (diff)
downloadbcm5719-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.cpp6
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp38
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,
OpenPOWER on IntegriCloud