forked from OSchip/llvm-project
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
This commit is contained in:
parent
1d3ae27f01
commit
35f9421c55
|
@ -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<
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -94,5 +94,4 @@ void testFundef5() __attribute__(()) { }
|
|||
|
||||
__attribute__((pure)) int testFundef6(int a) { return a; }
|
||||
|
||||
|
||||
|
||||
void deprecatedTestFun(void) __attribute__((deprecated()));
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue