blob: 00fd234a0c09ccec7235a7d0815d91fd619876fa [file] [log] [blame]
Patrick Beardb2f68202012-04-06 18:12:22 +00001// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -verify -Wno-objc-root-class %s
John McCallf85e1932011-06-15 23:02:42 +00002
3@interface Test0
4- (void) setBlock: (void(^)(void)) block;
5- (void) addBlock: (void(^)(void)) block;
6- (void) actNow;
7@end
8void test0(Test0 *x) {
9 [x setBlock: // expected-note {{block will be retained by the captured object}}
10 ^{ [x actNow]; }]; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}
11 x.block = // expected-note {{block will be retained by the captured object}}
12 ^{ [x actNow]; }; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}
13
14 [x addBlock: // expected-note {{block will be retained by the captured object}}
15 ^{ [x actNow]; }]; // expected-warning {{capturing 'x' strongly in this block is likely to lead to a retain cycle}}
16
17 // These actually don't cause retain cycles.
18 __weak Test0 *weakx = x;
19 [x addBlock: ^{ [weakx actNow]; }];
20 [x setBlock: ^{ [weakx actNow]; }];
21 x.block = ^{ [weakx actNow]; };
22
23 // These do cause retain cycles, but we're not clever enough to figure that out.
24 [weakx addBlock: ^{ [x actNow]; }];
25 [weakx setBlock: ^{ [x actNow]; }];
26 weakx.block = ^{ [x actNow]; };
27}
28
29@interface BlockOwner
Fariborz Jahanian528a4992011-09-14 18:03:46 +000030@property (retain) void (^strong)(void); // expected-warning {{retain'ed block property does not copy the block - use copy attribute instead}}
John McCallf85e1932011-06-15 23:02:42 +000031@end
32
33@interface Test1 {
34@public
35 BlockOwner *owner;
36};
37@property (retain) BlockOwner *owner;
38@property (assign) __strong BlockOwner *owner2; // expected-error {{unsafe_unretained property 'owner2' may not also be declared __strong}}
39@property (assign) BlockOwner *owner3;
40@end
41void test1(Test1 *x) {
42 x->owner.strong = ^{ (void) x; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
43 x.owner.strong = ^{ (void) x; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
44 x.owner2.strong = ^{ (void) x; };
45 x.owner3.strong = ^{ (void) x; };
46}
47
48@implementation Test1 {
49 BlockOwner * __unsafe_unretained owner3ivar;
50 __weak BlockOwner *weakowner;
51}
52@dynamic owner;
53@dynamic owner2;
54@synthesize owner3 = owner3ivar;
55
56- (id) init {
57 self.owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
58 self.owner2.strong = ^{ (void) owner; };
59
60 // TODO: should we warn here? What's the story with this kind of mismatch?
61 self.owner3.strong = ^{ (void) owner; };
62
63 owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
64
65 owner.strong = ^{ ^{ (void) owner; }(); }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
66
67 owner.strong = ^{ (void) sizeof(self); // expected-note {{block will be retained by an object strongly retained by the captured object}}
68 (void) owner; }; // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}
69
70 weakowner.strong = ^{ (void) owner; };
71
72 return self;
73}
74- (void) foo {
75 owner.strong = ^{ (void) owner; }; // expected-warning {{retain cycle}} expected-note {{block will be retained by an object strongly retained by the captured object}}
76}
77@end
78
79void test2_helper(id);
80@interface Test2 {
81 void (^block)(void);
82 id x;
83}
84@end
85@implementation Test2
86- (void) test {
87 block = ^{ // expected-note {{block will be retained by an object strongly retained by the captured object}}
88 test2_helper(x); // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}
89 };
90}
91@end
Ted Kremenek968a0ee2011-12-01 00:59:21 +000092
93
94@interface NSOperationQueue {}
95- (void)addOperationWithBlock:(void (^)(void))block;
96- (void)addSomethingElse:(void (^)(void))block;
97
98@end
99
100@interface Test3 {
101 NSOperationQueue *myOperationQueue;
102 unsigned count;
103}
104@end
105void doSomething(unsigned v);
106@implementation Test3
107- (void) test {
108 // 'addOperationWithBlock:' is specifically whitelisted.
109 [myOperationQueue addOperationWithBlock:^() { // no-warning
110 if (count > 20) {
111 doSomething(count);
112 }
113 }];
114}
115- (void) test_positive {
116 // Sanity check that we are really whitelisting 'addOperationWithBlock:' and not doing
117 // something funny.
118 [myOperationQueue addSomethingElse:^() { // expected-note {{block will be retained by an object strongly retained by the captured object}}
119 if (count > 20) { // expected-warning {{capturing 'self' strongly in this block is likely to lead to a retain cycle}}
120 doSomething(count);
121 }
122 }];
123}
124@end
125