aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-04-24 17:50:11 +0000
committerTed Kremenek <kremenek@apple.com>2009-04-24 17:50:11 +0000
commitde4d5339e0811c8c8226aee8e00dc9a25bd5ebcf (patch)
tree32c569530b28b22af872f1fee7793d3b18488110 /lib/Analysis/CFRefCount.cpp
parent524fa13fd81e88533c7a1d4b1232c0de2c97dc7c (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.cpp89
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);
}