return false;
}
+ SourceLocation OpenParenLoc = Tok.getLocation();
+
if (AttrName->getName() == "property") {
// The property declspec is more complex in that it can take one or two
// assignment expressions as a parameter, but the lhs of the assignment
return !HasInvalidAccessor;
}
- ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
- SourceLocation(), AttributeList::AS_Declspec);
+ unsigned NumArgs =
+ ParseAttributeArgsCommon(AttrName, AttrNameLoc, Attrs, nullptr, nullptr,
+ SourceLocation(), AttributeList::AS_Declspec);
+
+ // If this attribute's args were parsed, and it was expected to have
+ // arguments but none were provided, emit a diagnostic.
+ const AttributeList *Attr = Attrs.getList();
+ if (Attr && Attr->getMaxArgs() && !NumArgs) {
+ Diag(OpenParenLoc, diag::err_attribute_requires_arguements) << AttrName;
+ return false;
+ }
return true;
}
struct __declspec(12) S2 {}; /* expected-error {{__declspec attributes must be an identifier or string literal}} */
struct __declspec("testing") S3 {}; /* expected-warning {{__declspec attribute '"testing"' is not supported}} */
+/* declspecs with arguments cannot have an empty argument list, even if the
+ arguments are optional. */
+__declspec(deprecated()) void dep_func_test(void); /* expected-error {{attribute 'deprecated' requires a nonempty argument list}} */
+__declspec(deprecated) void dep_func_test2(void);
+__declspec(deprecated("")) void dep_func_test3(void);
+
/* Ensure multiple declspec attributes are supported */
struct __declspec(align(8) deprecated) S4 {};