summaryrefslogtreecommitdiffstats
path: root/test/Analysis/inlining/RetainCountExamples.m
diff options
context:
space:
mode:
Diffstat (limited to 'test/Analysis/inlining/RetainCountExamples.m')
-rw-r--r--test/Analysis/inlining/RetainCountExamples.m96
1 files changed, 95 insertions, 1 deletions
diff --git a/test/Analysis/inlining/RetainCountExamples.m b/test/Analysis/inlining/RetainCountExamples.m
index 2b682c2..276ab52 100644
--- a/test/Analysis/inlining/RetainCountExamples.m
+++ b/test/Analysis/inlining/RetainCountExamples.m
@@ -15,6 +15,7 @@ typedef struct objc_object {
-(id)copy;
- (Class)class;
-(id)retain;
+- (oneway void)release;
@end
@interface SelfStaysLive : NSObject
@@ -30,4 +31,97 @@ typedef struct objc_object {
void selfStaysLive() {
SelfStaysLive *foo = [[SelfStaysLive alloc] init];
[foo release];
-} \ No newline at end of file
+}
+
+// Test that retain release checker warns on leaks and use-after-frees when
+// self init is not enabled.
+// radar://12115830
+@interface ParentOfCell : NSObject
+- (id)initWithInt: (int)inInt;
+@end
+@interface Cell : ParentOfCell{
+ int x;
+}
+- (id)initWithInt: (int)inInt;
++ (void)testOverRelease;
++ (void)testLeak;
+@property int x;
+@end
+@implementation Cell
+@synthesize x;
+- (id) initWithInt: (int)inInt {
+ [super initWithInt: inInt];
+ self.x = inInt; // no-warning
+ return self; // Self Init checker would produce a warning here.
+}
++ (void) testOverRelease {
+ Cell *sharedCell3 = [[Cell alloc] initWithInt: 3];
+ [sharedCell3 release];
+ [sharedCell3 release]; // expected-warning {{Reference-counted object is used after it is released}}
+}
++ (void) testLeak {
+ Cell *sharedCell4 = [[Cell alloc] initWithInt: 3]; // expected-warning {{leak}}
+}
+@end
+
+// We should stop tracking some objects even when we inline the call.
+// Specialically, the objects passed into calls with delegate and callback
+// parameters.
+@class DelegateTest;
+typedef void (*ReleaseCallbackTy) (DelegateTest *c);
+
+@interface Delegate : NSObject
+@end
+
+@interface DelegateTest : NSObject {
+ Delegate *myDel;
+}
+// Object initialized with a delagate which could potentially release it.
+- (id)initWithDelegate: (id) d;
+
+- (void) setDelegate: (id) d;
+
+// Releases object through callback.
++ (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc;
+
++ (void)test: (Delegate *)d;
+
+@property (assign) Delegate* myDel;
+@end
+
+void releaseObj(DelegateTest *c);
+
+// Releases object through callback.
+void updateObject(DelegateTest *c, ReleaseCallbackTy rel) {
+ rel(c);
+}
+
+@implementation DelegateTest
+@synthesize myDel;
+
+- (id) initWithDelegate: (id) d {
+ if ((self = [super init]))
+ myDel = d;
+ return self;
+}
+
+- (void) setDelegate: (id) d {
+ myDel = d;
+}
+
++ (void)updateObject:(DelegateTest*)obj WithCallback:(ReleaseCallbackTy)rc {
+ rc(obj);
+}
+
++ (void) test: (Delegate *)d {
+ DelegateTest *obj1 = [[DelegateTest alloc] initWithDelegate: d]; // no-warning
+ DelegateTest *obj2 = [[DelegateTest alloc] init]; // no-warning
+ DelegateTest *obj3 = [[DelegateTest alloc] init]; // no-warning
+ updateObject(obj2, releaseObj);
+ [DelegateTest updateObject: obj3
+ WithCallback: releaseObj];
+ DelegateTest *obj4 = [[DelegateTest alloc] init]; // no-warning
+ [obj4 setDelegate: d];
+}
+@end
+
OpenPOWER on IntegriCloud