[llvm-branch-commits] [cfe-branch] r71622 - in /cfe/branches/Apple/Dib: lib/Analysis/CFRefCount.cpp test/Analysis/retain-release.m

Mike Stump mrs at apple.com
Tue May 12 20:07:34 PDT 2009


Author: mrs
Date: Tue May 12 22:07:34 2009
New Revision: 71622

URL: http://llvm.org/viewvc/llvm-project?rev=71622&view=rev
Log:
Merge in 71579:

Fix: <rdar://problem/6320065> false positive - init method returns an object owned by caller

Now 'init' methods are treated by the retain/release checker as
claiming their receiver and allocating a new object.

Modified:
    cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp
    cfe/branches/Apple/Dib/test/Analysis/retain-release.m

Modified: cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp?rev=71622&r1=71621&r2=71622&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/branches/Apple/Dib/lib/Analysis/CFRefCount.cpp Tue May 12 22:07:34 2009
@@ -279,7 +279,8 @@
 class VISIBILITY_HIDDEN RetEffect {
 public:
   enum Kind { NoRet, Alias, OwnedSymbol, OwnedAllocatedSymbol,
-              NotOwnedSymbol, GCNotOwnedSymbol, ReceiverAlias };
+              NotOwnedSymbol, GCNotOwnedSymbol, ReceiverAlias,
+              OwnedWhenTrackedReceiver };
     
   enum ObjKind { CF, ObjC, AnyObj };  
 
@@ -302,9 +303,14 @@
   }
   
   bool isOwned() const {
-    return K == OwnedSymbol || K == OwnedAllocatedSymbol;
+    return K == OwnedSymbol || K == OwnedAllocatedSymbol ||
+           K == OwnedWhenTrackedReceiver;
   }
     
+  static RetEffect MakeOwnedWhenTrackedReceiver() {
+    return RetEffect(OwnedWhenTrackedReceiver, ObjC);
+  }
+  
   static RetEffect MakeAlias(unsigned Idx) {
     return RetEffect(Alias, Idx);
   }
@@ -635,6 +641,8 @@
   enum UnaryFuncKind { cfretain, cfrelease, cfmakecollectable };  
   
 public:
+  RetEffect getObjAllocRetEffect() const { return ObjCAllocRetE; }
+
   RetainSummary *getDefaultSummary() {
     RetainSummary *Summ = (RetainSummary*) BPAlloc.Allocate<RetainSummary>();
     return new (Summ) RetainSummary(DefaultSummary);
@@ -1127,12 +1135,14 @@
 
 RetainSummary*
 RetainSummaryManager::getInitMethodSummary(QualType RetTy) {
-  assert(ScratchArgs.isEmpty());
-    
-  // 'init' methods only return an alias if the return type is a location type.
-  return getPersistentSummary(Loc::IsLocType(RetTy)
-                              ? RetEffect::MakeReceiverAlias()
-                              : RetEffect::MakeNoRet());
+  assert(ScratchArgs.isEmpty());    
+  // 'init' methods conceptually return a newly allocated object and claim
+  // the receiver.  
+  if (isTrackedObjCObjectType(RetTy) || isTrackedCFObjectType(RetTy))
+    return getPersistentSummary(RetEffect::MakeOwnedWhenTrackedReceiver(),
+                                DecRefMsg);
+  
+  return getDefaultSummary();
 }
 
 void
@@ -1333,9 +1343,9 @@
   
   // Create the "init" selector.  It just acts as a pass-through for the
   // receiver.
-  RetainSummary* InitSumm =
-    getPersistentSummary(RetEffect::MakeReceiverAlias());
-  addNSObjectMethSummary(GetNullarySelector("init", Ctx), InitSumm);
+  addNSObjectMethSummary(GetNullarySelector("init", Ctx),
+                 getPersistentSummary(RetEffect::MakeOwnedWhenTrackedReceiver(),
+                 DecRefMsg));
   
   // The next methods are allocators.
   RetainSummary* Summ = getPersistentSummary(ObjCAllocRetE);  
@@ -1378,33 +1388,33 @@
   //  Thus, we need to track an NSWindow's display status.
   //  This is tracked in <rdar://problem/6062711>.
   //  See also http://llvm.org/bugs/show_bug.cgi?id=3714.
-  RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet());
+  RetainSummary *NoTrackYet = getPersistentSummary(RetEffect::MakeNoRet(),
+                                                   StopTracking,
+                                                   StopTracking);
   
   addClassMethSummary("NSWindow", "alloc", NoTrackYet);
 
-
 #if 0
-  RetainSummary *NSWindowSumm =
-    getPersistentSummary(RetEffect::MakeReceiverAlias(), StopTracking);
-  
-  addInstMethSummary("NSWindow", NSWindowSumm, "initWithContentRect",
+  addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
                      "styleMask", "backing", "defer", NULL);
   
-  addInstMethSummary("NSWindow", NSWindowSumm, "initWithContentRect",
+  addInstMethSummary("NSWindow", NoTrackYet, "initWithContentRect",
                      "styleMask", "backing", "defer", "screen", NULL);
 #endif
-    
+  
   // For NSPanel (which subclasses NSWindow), allocated objects are not
   //  self-owned.
   // FIXME: For now we don't track NSPanels. object for the same reason
   //   as for NSWindow objects.
   addClassMethSummary("NSPanel", "alloc", NoTrackYet);
   
-  addInstMethSummary("NSPanel", InitSumm, "initWithContentRect",
+#if 0
+  addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
                      "styleMask", "backing", "defer", NULL);
   
-  addInstMethSummary("NSPanel", InitSumm, "initWithContentRect",
+  addInstMethSummary("NSPanel", NoTrackYet, "initWithContentRect",
                      "styleMask", "backing", "defer", "screen", NULL);
+#endif
 
   // Create NSAssertionHandler summaries.
   addPanicSummary("NSAssertionHandler", "handleFailureInFunction", "file",
@@ -2788,6 +2798,20 @@
   // Consult the summary for the return value.  
   RetEffect RE = Summ.getRetEffect();
   
+  if (RE.getKind() == RetEffect::OwnedWhenTrackedReceiver) {
+    assert(Receiver);
+    SVal V = state.GetSValAsScalarOrLoc(Receiver);
+    bool found = false;
+    if (SymbolRef Sym = V.getAsLocSymbol())
+      if (state.get<RefBindings>(Sym)) {
+        found = true;
+        RE = Summaries.getObjAllocRetEffect();
+      }
+
+    if (!found)
+      RE = RetEffect::MakeNoRet();
+  } 
+  
   switch (RE.getKind()) {
     default:
       assert (false && "Unhandled RetEffect."); break;
@@ -3033,7 +3057,7 @@
   // Change the reference count.  
   RefVal X = *T;  
   
-  switch (X.getKind()) {      
+  switch (X.getKind()) { 
     case RefVal::Owned: { 
       unsigned cnt = X.getCount();
       assert (cnt > 0);

Modified: cfe/branches/Apple/Dib/test/Analysis/retain-release.m
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/Dib/test/Analysis/retain-release.m?rev=71622&r1=71621&r2=71622&view=diff

==============================================================================
--- cfe/branches/Apple/Dib/test/Analysis/retain-release.m (original)
+++ cfe/branches/Apple/Dib/test/Analysis/retain-release.m Tue May 12 22:07:34 2009
@@ -550,6 +550,49 @@
 @end
 
 //===----------------------------------------------------------------------===//
+//<rdar://problem/6320065> false positive - init method returns an object owned by caller
+//===----------------------------------------------------------------------===//
+
+ at interface RDar6320065 : NSObject {
+  NSString *_foo;
+}
+- (id)initReturningNewClass;
+- (id)initReturningNewClassBad;
+- (id)initReturningNewClassBad2;
+ at end
+
+ at interface RDar6320065Subclass : RDar6320065
+ at end
+
+ at implementation RDar6320065
+- (id)initReturningNewClass {
+  [self release];
+  self = [[RDar6320065Subclass alloc] init]; // no-warning
+  return self;
+}
+- (id)initReturningNewClassBad {
+  [self release];
+  [[RDar6320065Subclass alloc] init]; // expected-warning {{leak}}
+  return self;
+}
+- (id)initReturningNewClassBad2 {
+  [self release];
+  self = [[RDar6320065Subclass alloc] init];
+  return [self autorelease]; // expected-warning{{Object with +0 retain counts returned to caller where a +1 (owning) retain count is expected}}
+}
+
+ at end
+
+ at implementation RDar6320065Subclass
+ at end
+
+int RDar6320065_test() {
+  RDar6320065 *test = [[RDar6320065 alloc] init]; // no-warning
+  [test release];
+  return 0;
+}
+
+//===----------------------------------------------------------------------===//
 // Tests of ownership attributes.
 //===----------------------------------------------------------------------===//
 





More information about the llvm-branch-commits mailing list