[cfe-commits] r70429 - in /cfe/trunk: lib/Analysis/CFRefCount.cpp test/Analysis/retain-release.m
Ted Kremenek
kremenek at apple.com
Wed Apr 29 16:03:22 PDT 2009
Author: kremenek
Date: Wed Apr 29 18:03:22 2009
New Revision: 70429
URL: http://llvm.org/viewvc/llvm-project?rev=70429&view=rev
Log:
retain/release checker: When determining whether an analyzed method can return
an owned object, consult its summary instead of inspecting the selector. This
picks up annotations, and is just more general.
Modified:
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/test/Analysis/retain-release.m
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=70429&r1=70428&r2=70429&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Wed Apr 29 18:03:22 2009
@@ -149,9 +149,14 @@
return deriveNamingConvention(s) == CreateRule;
}
-static bool followsReturnRule(const char* s) {
- NamingConvention C = deriveNamingConvention(s);
- return C == CreateRule || C == InitRule;
+static const ObjCMethodDecl*
+ResolveToInterfaceMethodDecl(const ObjCMethodDecl *MD, ASTContext &Context) {
+ ObjCInterfaceDecl *ID =
+ const_cast<ObjCInterfaceDecl*>(MD->getClassInterface());
+
+ return MD->isInstanceMethod()
+ ? ID->lookupInstanceMethod(Context, MD->getSelector())
+ : ID->lookupClassMethod(Context, MD->getSelector());
}
//===----------------------------------------------------------------------===//
@@ -269,6 +274,10 @@
return index;
}
+ bool isOwned() const {
+ return K == OwnedSymbol || K == OwnedAllocatedSymbol;
+ }
+
static RetEffect MakeAlias(unsigned Idx) {
return RetEffect(Alias, Idx);
}
@@ -399,7 +408,7 @@
ObjCSummaryKey(IdentifierInfo* ii, Selector s)
: II(ii), S(s) {}
- ObjCSummaryKey(ObjCInterfaceDecl* d, Selector s)
+ ObjCSummaryKey(const ObjCInterfaceDecl* d, Selector s)
: II(d ? d->getIdentifier() : 0), S(s) {}
ObjCSummaryKey(Selector s)
@@ -452,14 +461,14 @@
typedef MapTy::iterator iterator;
- iterator find(ObjCInterfaceDecl* D, IdentifierInfo *ClsName, Selector S) {
+ iterator find(const ObjCInterfaceDecl* D, IdentifierInfo *ClsName,
+ Selector S) {
// Lookup the method using the decl for the class @interface. If we
// have no decl, lookup using the class name.
return D ? find(D, S) : find(ClsName, S);
}
- iterator find(ObjCInterfaceDecl* D, Selector S) {
-
+ iterator find(const ObjCInterfaceDecl* D, Selector S) {
// Do a lookup with the (D,S) pair. If we find a match return
// the iterator.
ObjCSummaryKey K(D, S);
@@ -730,18 +739,21 @@
RetainSummary* getSummary(FunctionDecl* FD);
- RetainSummary* getInstanceMethodSummary(ObjCMessageExpr* ME, ObjCInterfaceDecl* ID) {
+ RetainSummary* getInstanceMethodSummary(ObjCMessageExpr* ME,
+ const ObjCInterfaceDecl* ID) {
return getInstanceMethodSummary(ME->getSelector(), ME->getClassName(),
ID, ME->getMethodDecl(), ME->getType());
}
RetainSummary* getInstanceMethodSummary(Selector S, IdentifierInfo *ClsName,
- ObjCInterfaceDecl* ID,
- ObjCMethodDecl *MD, QualType RetTy);
+ const ObjCInterfaceDecl* ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy);
RetainSummary *getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
- ObjCInterfaceDecl *ID,
- ObjCMethodDecl *MD, QualType RetTy);
+ const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy);
RetainSummary *getClassMethodSummary(ObjCMessageExpr *ME) {
return getClassMethodSummary(ME->getSelector(), ME->getClassName(),
@@ -751,9 +763,12 @@
/// getMethodSummary - This version of getMethodSummary is used to query
/// the summary for the current method being analyzed.
- RetainSummary *getMethodSummary(ObjCMethodDecl *MD) {
+ RetainSummary *getMethodSummary(const ObjCMethodDecl *MD) {
+ // FIXME: Eventually this should be unneeded.
+ MD = ResolveToInterfaceMethodDecl(MD, Ctx);
+
Selector S = MD->getSelector();
- ObjCInterfaceDecl *ID = MD->getClassInterface();
+ const ObjCInterfaceDecl *ID = MD->getClassInterface();
IdentifierInfo *ClsName = ID->getIdentifier();
QualType ResultTy = MD->getResultType();
@@ -763,9 +778,10 @@
return getClassMethodSummary(S, ClsName, ID, MD, ResultTy);
}
- RetainSummary* getCommonMethodSummary(ObjCMethodDecl* MD, Selector S,
- QualType RetTy);
- RetainSummary* getMethodSummaryFromAnnotations(ObjCMethodDecl *MD);
+ RetainSummary* getCommonMethodSummary(const ObjCMethodDecl* MD,
+ Selector S, QualType RetTy);
+
+ RetainSummary* getMethodSummaryFromAnnotations(const ObjCMethodDecl *MD);
bool isGCEnabled() const { return GCEnabled; }
};
@@ -1113,7 +1129,7 @@
}
RetainSummary*
-RetainSummaryManager::getMethodSummaryFromAnnotations(ObjCMethodDecl *MD) {
+RetainSummaryManager::getMethodSummaryFromAnnotations(const ObjCMethodDecl *MD){
if (!MD)
return 0;
@@ -1169,8 +1185,8 @@
}
RetainSummary*
-RetainSummaryManager::getCommonMethodSummary(ObjCMethodDecl* MD, Selector S,
- QualType RetTy) {
+RetainSummaryManager::getCommonMethodSummary(const ObjCMethodDecl* MD,
+ Selector S, QualType RetTy) {
if (MD) {
// Scan the method decl for 'void*' arguments. These should be treated
@@ -1224,8 +1240,8 @@
RetainSummary*
RetainSummaryManager::getInstanceMethodSummary(Selector S,
IdentifierInfo *ClsName,
- ObjCInterfaceDecl* ID,
- ObjCMethodDecl *MD,
+ const ObjCInterfaceDecl* ID,
+ const ObjCMethodDecl *MD,
QualType RetTy) {
// Look up a summary in our summary cache.
@@ -1255,8 +1271,9 @@
RetainSummary*
RetainSummaryManager::getClassMethodSummary(Selector S, IdentifierInfo *ClsName,
- ObjCInterfaceDecl *ID,
- ObjCMethodDecl *MD, QualType RetTy){
+ const ObjCInterfaceDecl *ID,
+ const ObjCMethodDecl *MD,
+ QualType RetTy) {
assert(ClsName && "Class name must be specified.");
ObjCMethodSummariesTy::iterator I =
@@ -2448,7 +2465,7 @@
// to the caller for NS objects.
ObjCMethodDecl& MD = cast<ObjCMethodDecl>(BR.getGraph().getCodeDecl());
os << " is returned from a method whose name ('"
- << MD.getSelector().getAsString()
+ << MD.getSelector().getAsString()
<< "') does not contain 'copy' or otherwise starts with"
" 'new' or 'alloc'. This violates the naming convention rules given"
" in the Memory Management Guide for Cocoa (object leaked)";
@@ -2992,13 +3009,11 @@
if (X.isReturnedOwned() && X.getCount() == 0) {
const Decl *CD = &Eng.getStateManager().getCodeDecl();
- if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
- std::string s = MD->getSelector().getAsString();
- // FIXME: Use method summary.
- if (!followsReturnRule(s.c_str())) {
+ if (const ObjCMethodDecl* MD = dyn_cast<ObjCMethodDecl>(CD)) {
+ RetainSummary *Summ = Summaries.getMethodSummary(MD);
+ if (!GetRetEffect(Summ).isOwned()) {
static int ReturnOwnLeakTag = 0;
state = state.set<RefBindings>(Sym, X ^ RefVal::ErrorLeakReturned);
-
// Generate an error node.
ExplodedNode<GRState> *N =
Builder.generateNode(PostStmt(S, &ReturnOwnLeakTag), state, Pred);
Modified: cfe/trunk/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/retain-release.m?rev=70429&r1=70428&r2=70429&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/retain-release.m (original)
+++ cfe/trunk/test/Analysis/retain-release.m Wed Apr 29 18:03:22 2009
@@ -440,13 +440,16 @@
@interface TestAttrHelper : NSObject
- (NSString*) createString:(TestOwnershipAttr*)X;
+- (NSString*) createStringAttr:(TestOwnershipAttr*)X __attribute__((objc_ownership_returns));
@end
@implementation TestAttrHelper
- (NSString*) createString:(TestOwnershipAttr*)X {
return [X returnsAnOwnedString]; // expected-warning{{leak}}
}
-
+- (NSString*) createStringAttr:(TestOwnershipAttr*)X {
+ return [X returnsAnOwnedString]; // no-warning
+}
@end
void test_attr_1(TestOwnershipAttr *X) {
More information about the cfe-commits
mailing list