• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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