aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/CFRefCount.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis/CFRefCount.cpp')
-rw-r--r--lib/Analysis/CFRefCount.cpp23
1 files changed, 21 insertions, 2 deletions
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 8be76d8289..1021574de6 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1076,9 +1076,28 @@ RetainSummaryManager::getInitMethodSummary(ObjCMessageExpr* ME) {
RetainSummary*
RetainSummaryManager::getCommonMethodSummary(ObjCMessageExpr* ME, const char *s)
{
+ if (ObjCMethodDecl *MD = ME->getMethodDecl()) {
+ // Scan the method decl for 'void*' arguments. These should be treated
+ // as 'StopTracking' because they are often used with delegates.
+ // Delegates are a frequent form of false positives with the retain
+ // count checker.
+ unsigned i = 0;
+ for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
+ E = MD->param_end(); I != E; ++I, ++i)
+ if (ParmVarDecl *PD = *I) {
+ QualType Ty = Ctx.getCanonicalType(PD->getType());
+ if (Ty.getUnqualifiedType() == Ctx.VoidPtrTy)
+ ScratchArgs.push_back(std::make_pair(i, StopTracking));
+ }
+ }
+
// Look for methods that return an owned object.
- if (!isTrackedObjectType(ME->getType()))
- return 0;
+ if (!isTrackedObjectType(ME->getType())) {
+ if (ScratchArgs.empty())
+ return 0;
+
+ return getPersistentSummary(RetEffect::MakeNoRet());
+ }
// EXPERIMENTAL: Assume the Cocoa conventions for all objects returned
// by instance methods.