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