]> granicus.if.org Git - clang/commitdiff
[analyzer] RetainCount: don't track objects init'd with a delegate
authorJordan Rose <jordan_rose@apple.com>
Fri, 15 Jun 2012 18:19:52 +0000 (18:19 +0000)
committerJordan Rose <jordan_rose@apple.com>
Fri, 15 Jun 2012 18:19:52 +0000 (18:19 +0000)
We already didn't track objects that have delegates or callbacks or
objects that are passed through void * "context pointers". It's a
not-uncommon pattern to release the object in its callback, and so
the leak message we give is not very helpful.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@158532 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp
test/Analysis/delegates.m

index 99243d2b14106a813029608ace74e40c7db1b65e..fc21a1ba7d7c7a33e0695909cc750be4273eae25 100644 (file)
@@ -1351,10 +1351,15 @@ RetainSummaryManager::getStandardMethodSummary(const ObjCMethodDecl *MD,
   // because the reference count is quite possibly handled by a delegate
   // method.
   if (S.isKeywordSelector()) {
-    const std::string &str = S.getAsString();
-    assert(!str.empty());
-    if (StrInStrNoCase(str, "delegate:") != StringRef::npos)
-      ReceiverEff = StopTracking;
+    for (unsigned i = 0, e = S.getNumArgs(); i != e; ++i) {
+      StringRef Slot = S.getNameForSlot(i);
+      if (Slot.substr(Slot.size() - 8).equals_lower("delegate")) {
+        if (ResultEff == ObjCInitRetE)
+          ResultEff = RetEffect::MakeNoRet();
+        else
+          ReceiverEff = StopTracking;
+      }
+    }
   }
 
   if (ScratchArgs.isEmpty() && ReceiverEff == DoNothing &&
index 8f42b83b0eeb6dc31c5ab29985ad6852ccacdb7e..7a86671a2f60e4552cc34472324f536e202e26a1 100644 (file)
@@ -111,3 +111,21 @@ extern void *_NSConstantStringClassReference;
 }
 @end
 
+
+@interface ObjectThatRequiresDelegate : NSObject
+- (id)initWithDelegate:(id)delegate;
+- (id)initWithNumber:(int)num delegate:(id)delegate;
+@end
+
+
+@interface DelegateRequirerTest
+@end
+@implementation DelegateRequirerTest
+
+- (void)test {
+  (void)[[ObjectThatRequiresDelegate alloc] initWithDelegate:self];
+  (void)[[ObjectThatRequiresDelegate alloc] initWithNumber:0 delegate:self];
+  // no leak warnings -- these objects could be released in callback methods
+}
+
+@end