1// RUN: %clang_cc1 -fsyntax-only -fobjc-nonfragile-abi -fobjc-runtime-has-weak -fobjc-arc -fblocks -verify %s 2 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 30@property (retain) void (^strong)(void); 31@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 92