[llvm-branch-commits] [cfe-branch] r71731 - in /cfe/branches/Apple/Dib: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/SemaDeclAttr.cpp test/Analysis/retain-release.m
Mike Stump
mrs at apple.com
Wed May 13 14:51:35 PDT 2009
Author: mrs
Date: Wed May 13 16:51:32 2009
New Revision: 71731
URL: http://llvm.org/viewvc/llvm-project?rev=71731&view=rev
Log:
Merge in 71718:
Add some basic type checking for attributes ns_returns_retained and
cf_returns_retained. Currently this attribute can now be applied to any
Objective-C method or C function that returns a pointer or Objective-C object
type.
Modify the tablegen definition of diagnostic 'warn_attribute_wrong_decl_type' to
expect that the diagnostics infrastructure will add quotes around the attribute
name when appropriate. Alonq with this change, I modified the places where this
warning is issued to passed the attribute's IdentifierInfo* instead of having a
hard-coded C constant string.
Modified:
cfe/branches/Apple/Dib/include/clang/Basic/DiagnosticSemaKinds.td
cfe/branches/Apple/Dib/lib/Sema/SemaDeclAttr.cpp
cfe/branches/Apple/Dib/test/Analysis/retain-release.m
Modified: cfe/branches/Apple/Dib/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/include/clang/Basic/DiagnosticSemaKinds.td?rev=71731&r1=71730&r2=71731&view=diff
==============================================================================
--- cfe/branches/Apple/Dib/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/branches/Apple/Dib/include/clang/Basic/DiagnosticSemaKinds.td Wed May 13 16:51:32 2009
@@ -412,7 +412,7 @@
def warn_attribute_weak_import_invalid_on_definition : Warning<
"'weak_import' attribute cannot be specified on a definition">;
def warn_attribute_wrong_decl_type : Warning<
- "'%0' attribute only applies to %select{function|union|"
+ "%0 attribute only applies to %select{function|union|"
"variable and function|function or method|parameter|parameter or Objective-C method}1 types">;
def warn_gnu_inline_attribute_requires_inline : Warning<
"'gnu_inline' attribute requires function to be marked 'inline',"
@@ -488,6 +488,9 @@
"previous overload of function is here">;
def err_attribute_overloadable_no_prototype : Error<
"'overloadable' function %0 must have a prototype">;
+def warn_ns_attribute_wrong_return_type : Warning<
+ "%0 attribute only applies to functions or methods that "
+ "return a pointer or Objective-C object">;
// Function Parameter Semantic Analysis.
def err_param_with_void_type : Error<"argument may not have 'void' type">;
Modified: cfe/branches/Apple/Dib/lib/Sema/SemaDeclAttr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/lib/Sema/SemaDeclAttr.cpp?rev=71731&r1=71730&r2=71731&view=diff
==============================================================================
--- cfe/branches/Apple/Dib/lib/Sema/SemaDeclAttr.cpp (original)
+++ cfe/branches/Apple/Dib/lib/Sema/SemaDeclAttr.cpp Wed May 13 16:51:32 2009
@@ -295,7 +295,7 @@
// 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;
}
@@ -395,7 +395,7 @@
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "always_inline" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -403,7 +403,7 @@
}
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;
@@ -414,7 +414,7 @@
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;
}
}
@@ -423,13 +423,13 @@
}
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());
}
@@ -442,7 +442,7 @@
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;
}
@@ -463,7 +463,7 @@
}
} 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;
}
@@ -492,7 +492,7 @@
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "constructor" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -521,7 +521,7 @@
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "destructor" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -722,7 +722,7 @@
}
} else {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "sentinel" << 3 /*function or method*/;
+ << Attr.getName() << 3 /*function or method*/;
return;
}
@@ -740,7 +740,7 @@
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;
}
@@ -757,7 +757,7 @@
// 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;
}
@@ -782,7 +782,7 @@
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;
}
@@ -813,7 +813,7 @@
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;
}
@@ -858,7 +858,7 @@
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;
}
@@ -903,7 +903,7 @@
// 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;
}
@@ -926,7 +926,7 @@
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "fastcall" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -1045,7 +1045,7 @@
if (!isFunctionOrMethod(d) || !hasFunctionProto(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "format" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -1190,7 +1190,7 @@
if (!RD || !RD->isUnion()) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "transparent_union" << 1 /*union*/;
+ << Attr.getName() << 1 /*union*/;
return;
}
@@ -1464,7 +1464,7 @@
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "nodebug" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -1480,7 +1480,7 @@
if (!isa<FunctionDecl>(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "noinline" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -1497,7 +1497,7 @@
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;
}
@@ -1518,7 +1518,7 @@
if (!isFunctionOrMethod(d)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)
- << "regparm" << 0 /*function*/;
+ << Attr.getName() << 0 /*function*/;
return;
}
@@ -1552,24 +1552,24 @@
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");
Modified: cfe/branches/Apple/Dib/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/test/Analysis/retain-release.m?rev=71731&r1=71730&r2=71731&view=diff
==============================================================================
--- cfe/branches/Apple/Dib/test/Analysis/retain-release.m (original)
+++ cfe/branches/Apple/Dib/test/Analysis/retain-release.m Wed May 13 16:51:32 2009
@@ -596,11 +596,17 @@
// Tests of ownership attributes.
//===----------------------------------------------------------------------===//
+typedef NSString* MyStringTy;
+
@interface TestOwnershipAttr : NSObject
-- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained));
-- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained));
+- (NSString*) returnsAnOwnedString __attribute__((ns_returns_retained)); // no-warning
+- (NSString*) returnsAnOwnedCFString __attribute__((cf_returns_retained)); // no-warning
+- (MyStringTy) returnsAnOwnedTypedString __attribute__((ns_returns_retained)); // no-warning
+- (int) returnsAnOwnedInt __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to functions or methods that return a pointer or Objective-C object}}
@end
+static int ownership_attribute_doesnt_go_here __attribute__((ns_returns_retained)); // expected-warning{{'ns_returns_retained' attribute only applies to function or method types}}
+
void test_attr_1(TestOwnershipAttr *X) {
NSString *str = [X returnsAnOwnedString]; // expected-warning{{leak}}
}
More information about the llvm-branch-commits
mailing list