[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