summaryrefslogtreecommitdiffstats
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
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
-rw-r--r--clang/include/clang/Basic/DiagnosticParseKinds.td4
-rw-r--r--clang/include/clang/Parse/Parser.h14
-rw-r--r--clang/lib/Parse/ParseDecl.cpp6
-rw-r--r--clang/lib/Parse/ParseDeclCXX.cpp38
-rw-r--r--clang/test/Parser/attributes.c3
-rw-r--r--clang/test/Parser/cxx0x-attributes.cpp7
6 files changed, 51 insertions, 21 deletions
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 04f4e5e1fc1..86078027dfc 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -526,7 +526,9 @@ def warn_cxx98_compat_attribute : Warning<
"C++11 attribute syntax is incompatible with C++98">,
InGroup<CXX98Compat>, DefaultIgnore;
def err_cxx11_attribute_forbids_arguments : Error<
- "attribute '%0' cannot have an argument list">;
+ "attribute %0 cannot have an argument list">;
+def err_attribute_requires_arguements : Error<
+ "attribute %0 requires a nonempty argument list">;
def err_cxx11_attribute_forbids_ellipsis : Error<
"attribute '%0' cannot be used as an attribute pack">;
def err_cxx11_attribute_repeated : Error<
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 2d71a0403dc..5c72b91bde1 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -2012,13 +2012,13 @@ private:
/// \brief Parses syntax-generic attribute arguments for attributes which are
/// known to the implementation, and adds them to the given ParsedAttributes
- /// list with the given attribute syntax.
- void ParseAttributeArgsCommon(IdentifierInfo *AttrName,
- SourceLocation AttrNameLoc,
- ParsedAttributes &Attrs, SourceLocation *EndLoc,
- IdentifierInfo *ScopeName,
- SourceLocation ScopeLoc,
- AttributeList::Syntax Syntax);
+ /// list with the given attribute syntax. Returns the number of arguments
+ /// parsed for the attribute.
+ unsigned
+ ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc,
+ ParsedAttributes &Attrs, SourceLocation *EndLoc,
+ IdentifierInfo *ScopeName, SourceLocation ScopeLoc,
+ AttributeList::Syntax Syntax);
void MaybeParseGNUAttributes(Declarator &D,
LateParsedAttrList *LateAttrs = 0) {
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,
diff --git a/clang/test/Parser/attributes.c b/clang/test/Parser/attributes.c
index 8d7e5fe503a..3d69c72c322 100644
--- a/clang/test/Parser/attributes.c
+++ b/clang/test/Parser/attributes.c
@@ -94,5 +94,4 @@ void testFundef5() __attribute__(()) { }
__attribute__((pure)) int testFundef6(int a) { return a; }
-
-
+void deprecatedTestFun(void) __attribute__((deprecated()));
diff --git a/clang/test/Parser/cxx0x-attributes.cpp b/clang/test/Parser/cxx0x-attributes.cpp
index 1b9e477004a..777a40a4e8a 100644
--- a/clang/test/Parser/cxx0x-attributes.cpp
+++ b/clang/test/Parser/cxx0x-attributes.cpp
@@ -322,3 +322,10 @@ namespace GccASan {
[[gnu::no_address_safety_analysis]] void f3();
[[gnu::no_sanitize_address]] void f4();
}
+
+namespace {
+ [[deprecated]] void bar();
+ [[deprecated("hello")]] void baz();
+ [[deprecated()]] void foo(); // expected-error {{attribute 'deprecated' requires a nonempty argument list}}
+ [[gnu::deprecated()]] void quux();
+}
OpenPOWER on IntegriCloud