// prototypes, so we ignore it as well
if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "nonnull" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "always_inline" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
}
static bool HandleCommonNoReturnAttr(Decl *d, const AttributeList &Attr,
- Sema &S, const char *attrName) {
+ Sema &S) {
// check the attribute arguments.
if (Attr.getNumArgs() != 0) {
S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;
ValueDecl *VD = dyn_cast<ValueDecl>(d);
if (VD == 0 || !VD->getType()->isBlockPointerType()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << attrName << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return false;
}
}
}
static void HandleNoReturnAttr(Decl *d, const AttributeList &Attr, Sema &S) {
- if (HandleCommonNoReturnAttr(d, Attr, S, "noreturn"))
+ if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) NoReturnAttr());
}
static void HandleAnalyzerNoReturnAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
- if (HandleCommonNoReturnAttr(d, Attr, S, "analyzer_noreturn"))
+ if (HandleCommonNoReturnAttr(d, Attr, S))
d->addAttr(::new (S.Context) AnalyzerNoReturnAttr());
}
if (!isa<VarDecl>(d) && !isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "unused" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
}
} else if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "used" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "constructor" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "destructor" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
}
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "sentinel" << 3 /*function or method*/;
+ << Attr.getName() << 3 /*function or method*/;
return;
}
FunctionDecl *Fn = dyn_cast<FunctionDecl>(D);
if (!Fn) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "warn_unused_result" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
// TODO: could also be applied to methods?
if (!isa<FunctionDecl>(D) && !isa<VarDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "weak" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
return;
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "weak_import" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "dllimport" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
FunctionDecl *FD = dyn_cast<FunctionDecl>(D);
if (!FD) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "dllexport" << 2 /*variable and function*/;
+ << Attr.getName() << 2 /*variable and function*/;
return;
}
// Attribute can be applied only to functions.
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "stdcall" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "fastcall" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "format" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!RD || !RD->isUnion()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "transparent_union" << 1 /*union*/;
+ << Attr.getName() << 1 /*union*/;
return;
}
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "nodebug" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "noinline" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
FunctionDecl *Fn = dyn_cast<FunctionDecl>(d);
if (Fn == 0) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "gnu_inline" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "regparm" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
static void HandleNSReturnsRetainedAttr(Decl *d, const AttributeList &Attr,
Sema &S) {
- if (!isa<ObjCMethodDecl>(d) && !isa<FunctionDecl>(d)) {
- const char *name;
-
- switch (Attr.getKind()) {
- default:
- assert(0 && "invalid ownership attribute");
- return;
- case AttributeList::AT_cf_returns_retained:
- name = "cf_returns_retained"; break;
- case AttributeList::AT_ns_returns_retained:
- name = "ns_returns_retained"; break;
- };
-
- S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
- name << 3 /* function or method */;
+ QualType RetTy;
+
+ if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(d))
+ RetTy = MD->getResultType();
+ else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(d))
+ RetTy = FD->getResultType();
+ else {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
+ << Attr.getName() << 3 /* function or method */;
return;
}
+ if (!(S.Context.isObjCNSObjectType(RetTy) || RetTy->getAsPointerType())) {
+ S.Diag(Attr.getLoc(), diag::warn_ns_attribute_wrong_return_type)
+ << Attr.getName();
+ return;
+ }
+
switch (Attr.getKind()) {
default:
assert(0 && "invalid ownership attribute");