]> granicus.if.org Git - clang/commitdiff
retain/release checker: Hook up attributes 'objc_ownership_retain' and
authorTed Kremenek <kremenek@apple.com>
Thu, 30 Apr 2009 20:00:31 +0000 (20:00 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 30 Apr 2009 20:00:31 +0000 (20:00 +0000)
'objc_ownership_release' to the effects on receivers.

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

lib/Analysis/CFRefCount.cpp
test/Analysis/retain-release.m

index eb7d04a3425392fbaca5260624d0cc28e7ea9c98..7ea462a1bb8bec3cb3369df26c9c2429f785e5c6 100644 (file)
@@ -1139,14 +1139,14 @@ RetainSummaryManager::getMethodSummaryFromAnnotations(const ObjCMethodDecl *MD){
   assert(ScratchArgs.empty());
   
   // Determine if there is a special return effect for this method.
-  bool hasRetEffect = false;
+  bool hasEffect = false;
   RetEffect RE = RetEffect::MakeNoRet();
   
   if (isTrackedObjectType(MD->getResultType())) {
     if (MD->getAttr<ObjCOwnershipReturnsAttr>()) {
       RE = isGCEnabled() ? RetEffect::MakeGCNotOwned()
                          : RetEffect::MakeOwned(RetEffect::ObjC, true);
-      hasRetEffect = true;
+      hasEffect = true;
     }
     else {
       // Default to 'not owned'.
@@ -1155,36 +1155,46 @@ RetainSummaryManager::getMethodSummaryFromAnnotations(const ObjCMethodDecl *MD){
   }
   
   // Determine if there are any arguments with a specific ArgEffect.
-  bool hasArgEffect = false;
   unsigned i = 0;
   for (ObjCMethodDecl::param_iterator I = MD->param_begin(),
        E = MD->param_end(); I != E; ++I, ++i) {
     if ((*I)->getAttr<ObjCOwnershipRetainAttr>()) {
       ScratchArgs.push_back(std::make_pair(i, IncRefMsg));
-      hasArgEffect = true;
+      hasEffect = true;
     }
     else if ((*I)->getAttr<ObjCOwnershipCFRetainAttr>()) {
       ScratchArgs.push_back(std::make_pair(i, IncRef));
-      hasArgEffect = true;
+      hasEffect = true;
     }
     else if ((*I)->getAttr<ObjCOwnershipReleaseAttr>()) {
       ScratchArgs.push_back(std::make_pair(i, DecRefMsg));
-      hasArgEffect = true;
+      hasEffect = true;
     }
     else if ((*I)->getAttr<ObjCOwnershipCFReleaseAttr>()) {
       ScratchArgs.push_back(std::make_pair(i, DecRef));
-      hasArgEffect = true;
+      hasEffect = true;
     }
     else if ((*I)->getAttr<ObjCOwnershipMakeCollectableAttr>()) {
       ScratchArgs.push_back(std::make_pair(i, MakeCollectable));
-      hasArgEffect = true;
+      hasEffect = true;
     }    
   }
   
-  if (!hasRetEffect && !hasArgEffect)
+  // Determine any effects on the receiver.
+  ArgEffect ReceiverEff = DoNothing;
+  if (MD->getAttr<ObjCOwnershipRetainAttr>()) {
+    ReceiverEff = IncRefMsg;
+    hasEffect = true;
+  }
+  else if (MD->getAttr<ObjCOwnershipReleaseAttr>()) {
+    ReceiverEff = DecRefMsg;
+    hasEffect = true;
+  }  
+  
+  if (!hasEffect)
     return 0;
 
-  return getPersistentSummary(RE);
+  return getPersistentSummary(RE, ReceiverEff);
 }
 
 RetainSummary*
index d36f985e3ad01f0117abd1acd797d6854edfb97e..c01da9cabb6303812274362695cde39a0dec9a78 100644 (file)
@@ -511,6 +511,21 @@ void test_attr_5c(TestOwnershipAttr *X) {
   [X myCFRelease:str];
 }
 
+void test_attr_6a() {
+  TestOwnershipAttr *X = [TestOwnershipAttr alloc]; // expected-warning{{leak}}
+}
+
+void test_attr_6b() {
+  TestOwnershipAttr *X = [TestOwnershipAttr alloc]; // no-warning
+  [X myRelease];
+}
+
+void test_attr_6c() {
+  TestOwnershipAttr *X = [TestOwnershipAttr alloc]; // expected-warning{{leak}}
+  [X myRetain];
+  [X myRelease];
+}
+
 //===----------------------------------------------------------------------===//
 // <rdar://problem/6833332>
 // One build of the analyzer accidentally stopped tracking the allocated