diff options
author | Ted Kremenek <kremenek@apple.com> | 2009-04-24 17:50:11 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2009-04-24 17:50:11 +0000 |
commit | de4d5339e0811c8c8226aee8e00dc9a25bd5ebcf (patch) | |
tree | 32c569530b28b22af872f1fee7793d3b18488110 /lib/Analysis/CFRefCount.cpp | |
parent | 524fa13fd81e88533c7a1d4b1232c0de2c97dc7c (diff) |
retain/release checker:
- Fix summary lookup for class methods to now use the (optional)
ObjCInterfaceDecl associated with a message expression. This removes a
long-standing FIXME.
- Partial fix for <rdar://problem/6062730> by stop tracking objects that
are passed to [NSObject performSelector]. These methods are often used
for delegates, which the analyzer doesn't reason about well yet.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@69982 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r-- | lib/Analysis/CFRefCount.cpp | 89 |
1 files changed, 68 insertions, 21 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index b63078b691..564f15bf5b 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -659,34 +659,51 @@ private: Selector S = GetNullarySelector(nullaryName, Ctx); ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; } - - void addInstMethSummary(const char* Cls, RetainSummary* Summ, va_list argp) { - - IdentifierInfo* ClsII = &Ctx.Idents.get(Cls); + + Selector generateSelector(va_list argp) { llvm::SmallVector<IdentifierInfo*, 10> II; - + while (const char* s = va_arg(argp, const char*)) II.push_back(&Ctx.Idents.get(s)); - - Selector S = Ctx.Selectors.getSelector(II.size(), &II[0]); - ObjCMethodSummaries[ObjCSummaryKey(ClsII, S)] = Summ; + + return Ctx.Selectors.getSelector(II.size(), &II[0]); + } + + void addMethodSummary(IdentifierInfo *ClsII, ObjCMethodSummariesTy& Summaries, + RetainSummary* Summ, va_list argp) { + Selector S = generateSelector(argp); + Summaries[ObjCSummaryKey(ClsII, S)] = Summ; } void addInstMethSummary(const char* Cls, RetainSummary* Summ, ...) { va_list argp; va_start(argp, Summ); - addInstMethSummary(Cls, Summ, argp); + addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp); va_end(argp); } - + + void addClsMethSummary(const char* Cls, RetainSummary* Summ, ...) { + va_list argp; + va_start(argp, Summ); + addMethodSummary(&Ctx.Idents.get(Cls),ObjCClassMethodSummaries, Summ, argp); + va_end(argp); + } + + void addClsMethSummary(IdentifierInfo *II, RetainSummary* Summ, ...) { + va_list argp; + va_start(argp, Summ); + addMethodSummary(II, ObjCClassMethodSummaries, Summ, argp); + va_end(argp); + } + void addPanicSummary(const char* Cls, ...) { RetainSummary* Summ = getPersistentSummary(0, RetEffect::MakeNoRet(), DoNothing, DoNothing, true); va_list argp; va_start (argp, Cls); - addInstMethSummary(Cls, Summ, argp); + addMethodSummary(&Ctx.Idents.get(Cls), ObjCMethodSummaries, Summ, argp); va_end(argp); - } + } public: @@ -1100,23 +1117,30 @@ RetainSummaryManager::getMethodSummary(ObjCMessageExpr* ME, } RetainSummary* -RetainSummaryManager::getClassMethodSummary(ObjCMessageExpr* ME) { - - // FIXME: Eventually we should properly do class method summaries, but - // it requires us being able to walk the type hierarchy. Unfortunately, - // we cannot do this with just an IdentifierInfo* for the class name. - IdentifierInfo* ClsName = ME->getClassName(); +RetainSummaryManager::getClassMethodSummary(ObjCMessageExpr *ME) { + Selector S = ME->getSelector(); + ObjCMethodSummariesTy::iterator I; + + if (ObjCInterfaceDecl *ID = ME->getClassInfo().first) { + // Lookup the method using the decl for the class @interface. + I = ObjCClassMethodSummaries.find(ID, S); + } + else { + // Fallback to using the class name. + IdentifierInfo *ClsName = ME->getClassName(); - // Look up a summary in our cache of Selectors -> Summaries. - ObjCMethodSummariesTy::iterator I = ObjCClassMethodSummaries.find(ClsName, S); + // Look up a summary in our cache of Selectors -> Summaries. + I = ObjCClassMethodSummaries.find(ClsName, S); + } if (I != ObjCClassMethodSummaries.end()) return I->second; RetainSummary* Summ = getCommonMethodSummary(ME, S.getIdentifierInfoForSlot(0)->getName()); - ObjCClassMethodSummaries[ObjCSummaryKey(ClsName, S)] = Summ; + + ObjCClassMethodSummaries[ObjCSummaryKey(ME->getClassName(), S)] = Summ; return Summ; } @@ -1146,6 +1170,28 @@ void RetainSummaryManager::InitializeClassMethodSummaries() { GetUnarySelector("addObject", Ctx), getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, Autorelease)); + + // Create the summaries for [NSObject performSelector...]. We treat + // these as 'stop tracking' for the arguments because they are often + // used for delegates that can release the object. When we have better + // inter-procedural analysis we can potentially do something better. This + // workaround is to remove false positives. + Summ = getPersistentSummary(RetEffect::MakeNoRet(), DoNothing, StopTracking); + IdentifierInfo *NSObjectII = &Ctx.Idents.get("NSObject"); + addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject", + "afterDelay", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelector", "withObject", + "afterDelay", "inModes", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread", + "withObject", "waitUntilDone", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelectorOnMainThread", + "withObject", "waitUntilDone", "modes", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread", + "withObject", "waitUntilDone", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelector", "onThread", + "withObject", "waitUntilDone", "modes", NULL); + addClsMethSummary(NSObjectII, Summ, "performSelectorInBackground", + "withObject", NULL); } void RetainSummaryManager::InitializeMethodSummaries() { @@ -2012,6 +2058,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<GRState>& Dst, else Summ = Summaries.getClassMethodSummary(ME); + EvalSummary(Dst, Eng, Builder, ME, ME->getReceiver(), Summ, ME->arg_begin(), ME->arg_end(), Pred); } |