blob: b5d9002130d216b5b2f16b4dc09ac61a54583992 [file] [log] [blame]
Jordan Rose76831c62012-10-11 16:10:19 +00001// RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-arc -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
Jordan Rosed3934582012-09-28 22:21:30 +00002
3@interface Test {
4@public
5 Test *ivar;
Jordan Rose657b5f42012-09-28 22:21:35 +00006 __weak id weakIvar;
Jordan Rosed3934582012-09-28 22:21:30 +00007}
8@property(weak) Test *weakProp;
9@property(strong) Test *strongProp;
10
11- (__weak id)implicitProp;
12
13+ (__weak id)weakProp;
14@end
15
16extern void use(id);
17extern id get();
18extern bool condition();
19#define nil ((id)0)
20
21void sanity(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000022 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
Jordan Rosed3934582012-09-28 22:21:30 +000023 use(a.weakProp); // expected-note{{also accessed here}}
24
25 use(a.strongProp);
26 use(a.strongProp); // no-warning
27
28 use(a.weakProp); // expected-note{{also accessed here}}
29}
30
31void singleUse(Test *a) {
32 use(a.weakProp); // no-warning
33 use(a.strongProp); // no-warning
34}
35
36void assignsOnly(Test *a) {
37 a.weakProp = get(); // no-warning
38
39 id next = get();
40 if (next)
41 a.weakProp = next; // no-warning
Jordan Rose657b5f42012-09-28 22:21:35 +000042
43 a->weakIvar = get(); // no-warning
44 next = get();
45 if (next)
46 a->weakIvar = next; // no-warning
47
48 extern __weak id x;
49 x = get(); // no-warning
50 next = get();
51 if (next)
52 x = next; // no-warning
Jordan Rosed3934582012-09-28 22:21:30 +000053}
54
55void assignThenRead(Test *a) {
56 a.weakProp = get(); // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +000057 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000058}
59
60void twoVariables(Test *a, Test *b) {
61 use(a.weakProp); // no-warning
62 use(b.weakProp); // no-warning
63}
64
65void doubleLevelAccess(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000066 use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times in this function and may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
Jordan Rosed3934582012-09-28 22:21:30 +000067 use(a.strongProp.weakProp); // expected-note{{also accessed here}}
68}
69
70void doubleLevelAccessIvar(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000071 use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000072 use(a.strongProp.weakProp); // expected-note{{also accessed here}}
73}
74
75void implicitProperties(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000076 use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000077 use(a.implicitProp); // expected-note{{also accessed here}}
78}
79
80void classProperties() {
Jordan Rose657b5f42012-09-28 22:21:35 +000081 use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000082 use(Test.weakProp); // expected-note{{also accessed here}}
83}
84
85void classPropertiesAreDifferent(Test *a) {
86 use(Test.weakProp); // no-warning
87 use(a.weakProp); // no-warning
88 use(a.strongProp.weakProp); // no-warning
89}
90
Jordan Rose657b5f42012-09-28 22:21:35 +000091void ivars(Test *a) {
92 use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
93 use(a->weakIvar); // expected-note{{also accessed here}}
94}
95
96void globals() {
97 extern __weak id a;
98 use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
99 use(a); // expected-note{{also accessed here}}
100}
101
Jordan Rose22487652012-10-11 16:06:21 +0000102void messageGetter(Test *a) {
103 use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
104 use([a weakProp]); // expected-note{{also accessed here}}
105}
106
107void messageSetter(Test *a) {
108 [a setWeakProp:get()]; // no-warning
109 [a setWeakProp:get()]; // no-warning
110}
111
112void messageSetterAndGetter(Test *a) {
113 [a setWeakProp:get()]; // expected-note{{also accessed here}}
114 use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
115}
116
117void mixDotAndMessageSend(Test *a, Test *b) {
118 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
119 use([a weakProp]); // expected-note{{also accessed here}}
120
121 use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
122 use(b.weakProp); // expected-note{{also accessed here}}
123}
124
Jordan Rosed3934582012-09-28 22:21:30 +0000125
126void assignToStrongWrongInit(Test *a) {
127 id val = a.weakProp; // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000128 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000129}
130
131void assignToStrongWrong(Test *a) {
132 id val;
133 val = a.weakProp; // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000134 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
135}
136
137void assignToIvarWrong(Test *a) {
138 a->weakIvar = get(); // expected-note{{also accessed here}}
139 use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
140}
141
142void assignToGlobalWrong() {
143 extern __weak id a;
144 a = get(); // expected-note{{also accessed here}}
145 use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000146}
147
148void assignToStrongOK(Test *a) {
149 if (condition()) {
150 id val = a.weakProp; // no-warning
151 (void)val;
152 } else {
153 id val;
154 val = a.weakProp; // no-warning
155 (void)val;
156 }
157}
158
159void assignToStrongConditional(Test *a) {
160 id val = (condition() ? a.weakProp : a.weakProp); // no-warning
161 id val2 = a.implicitProp ?: a.implicitProp; // no-warning
162}
163
164void testBlock(Test *a) {
165 use(a.weakProp); // no-warning
166
167 use(^{
Jordan Rose657b5f42012-09-28 22:21:35 +0000168 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
Jordan Rosed3934582012-09-28 22:21:30 +0000169 use(a.weakProp); // expected-note{{also accessed here}}
170 });
171}
172
Jordan Rosee723a272012-10-10 16:43:06 +0000173void assignToStrongWithCasts(Test *a) {
174 if (condition()) {
175 Test *val = (Test *)a.weakProp; // no-warning
176 (void)val;
177 } else {
178 id val;
179 val = (Test *)a.weakProp; // no-warning
180 (void)val;
181 }
182}
183
Jordan Roseb1e3e5f2012-10-11 17:02:00 +0000184void assignToStrongWithMessages(Test *a) {
185 if (condition()) {
186 id val = [a weakProp]; // no-warning
187 (void)val;
188 } else {
189 id val;
190 val = [a weakProp]; // no-warning
191 (void)val;
192 }
193}
194
195
Jordan Rose76831c62012-10-11 16:10:19 +0000196void assignAfterRead(Test *a) {
197 // Special exception for a single read before any writes.
198 if (!a.weakProp) // no-warning
199 a.weakProp = get(); // no-warning
200}
201
202void readOnceWriteMany(Test *a) {
203 if (!a.weakProp) { // no-warning
204 a.weakProp = get(); // no-warning
205 a.weakProp = get(); // no-warning
206 }
207}
208
209void readOnceAfterWrite(Test *a) {
210 a.weakProp = get(); // expected-note{{also accessed here}}
211 if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
212 a.weakProp = get(); // expected-note{{also accessed here}}
213 }
214}
215
216void readOnceWriteManyLoops(Test *a, Test *b, Test *c, Test *d, Test *e) {
217 while (condition()) {
218 if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
219 a.weakProp = get(); // expected-note{{also accessed here}}
220 a.weakProp = get(); // expected-note{{also accessed here}}
221 }
222 }
223
224 do {
225 if (!b.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
226 b.weakProp = get(); // expected-note{{also accessed here}}
227 b.weakProp = get(); // expected-note{{also accessed here}}
228 }
229 } while (condition());
230
231 for (id x = get(); x; x = get()) {
232 if (!c.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
233 c.weakProp = get(); // expected-note{{also accessed here}}
234 c.weakProp = get(); // expected-note{{also accessed here}}
235 }
236 }
237
238 for (id x in get()) {
239 if (!d.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
240 d.weakProp = get(); // expected-note{{also accessed here}}
241 d.weakProp = get(); // expected-note{{also accessed here}}
242 }
243 }
244
245 int array[] = { 1, 2, 3 };
246 for (int i : array) {
247 if (!e.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
248 e.weakProp = get(); // expected-note{{also accessed here}}
249 e.weakProp = get(); // expected-note{{also accessed here}}
250 }
251 }
252}
253
254void readOnlyLoop(Test *a) {
255 while (condition()) {
256 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
257 }
258}
259
Jordan Rose25c0ea82012-10-29 17:46:47 +0000260void readInIterationLoop() {
261 for (Test *a in get())
262 use(a.weakProp); // no-warning
263}
264
265void readDoubleLevelAccessInLoop() {
266 for (Test *a in get()) {
267 use(a.strongProp.weakProp); // no-warning
268 }
269}
270
271void readParameterInLoop(Test *a) {
272 for (id unused in get()) {
273 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
274 (void)unused;
275 }
276}
277
278void readGlobalInLoop() {
279 static __weak id a;
280 for (id unused in get()) {
281 use(a); // expected-warning{{weak variable 'a' is accessed multiple times in this function}}
282 (void)unused;
283 }
284}
285
286void doWhileLoop(Test *a) {
287 do {
288 use(a.weakProp); // no-warning
289 } while(0);
290}
291
Jordan Rosed3934582012-09-28 22:21:30 +0000292
293@interface Test (Methods)
294@end
295
296@implementation Test (Methods)
297- (void)sanity {
Jordan Rose657b5f42012-09-28 22:21:35 +0000298 use(self.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
Jordan Rosed3934582012-09-28 22:21:30 +0000299 use(self.weakProp); // expected-note{{also accessed here}}
300}
301
Jordan Rose657b5f42012-09-28 22:21:35 +0000302- (void)ivars {
303 use(weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times in this method but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
304 use(weakIvar); // expected-note{{also accessed here}}
305}
306
Jordan Rosed3934582012-09-28 22:21:30 +0000307- (void)doubleLevelAccessForSelf {
Jordan Rose657b5f42012-09-28 22:21:35 +0000308 use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000309 use(self.strongProp.weakProp); // expected-note{{also accessed here}}
310
Jordan Rose657b5f42012-09-28 22:21:35 +0000311 use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000312 use(self->ivar.weakProp); // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000313
314 use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
315 use(self->ivar->weakIvar); // expected-note{{also accessed here}}
Jordan Rosed3934582012-09-28 22:21:30 +0000316}
317
318- (void)distinctFromOther:(Test *)other {
319 use(self.strongProp.weakProp); // no-warning
320 use(other.strongProp.weakProp); // no-warning
321
322 use(self->ivar.weakProp); // no-warning
323 use(other->ivar.weakProp); // no-warning
Jordan Rose657b5f42012-09-28 22:21:35 +0000324
325 use(self.strongProp->weakIvar); // no-warning
326 use(other.strongProp->weakIvar); // no-warning
Jordan Rosed3934582012-09-28 22:21:30 +0000327}
328@end
329
Argyrios Kyrtzidisfe7a59d2013-04-15 18:47:22 +0000330@interface Base1
331@end
332@interface Sub1 : Base1
333@end
334@interface Sub1(cat)
335-(id)prop;
336@end
337
338void test1(Sub1 *s) {
339 use([s prop]);
340 use([s prop]);
341}
342
343@interface Base1(cat)
344@property (weak) id prop;
345@end
346
347void test2(Sub1 *s) {
Argyrios Kyrtzidisc2091d52013-04-17 00:09:08 +0000348 // This does not warn because the "prop" in "Base1(cat)" was introduced
349 // after the method declaration and we don't find it as overridden.
350 // Always looking for overridden methods after the method declaration is expensive
351 // and it's not clear it is worth it currently.
352 use([s prop]);
353 use([s prop]);
Argyrios Kyrtzidisfe7a59d2013-04-15 18:47:22 +0000354}
355
Jordan Rosed3934582012-09-28 22:21:30 +0000356
357class Wrapper {
358 Test *a;
359
360public:
361 void fields() {
Jordan Rose657b5f42012-09-28 22:21:35 +0000362 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function but may be unpredictably set to nil; assign to a strong variable to keep the object alive}}
Jordan Rosed3934582012-09-28 22:21:30 +0000363 use(a.weakProp); // expected-note{{also accessed here}}
364 }
365
366 void distinctFromOther(Test *b, const Wrapper &w) {
367 use(a.weakProp); // no-warning
368 use(b.weakProp); // no-warning
369 use(w.a.weakProp); // no-warning
370 }
371
372 static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000373 use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000374 use(y.a.weakProp); // expected-note{{also accessed here}}
375 }
376};
377
378
379// -----------------------
380// False positives
381// -----------------------
382
383// Most of these would require flow-sensitive analysis to silence correctly.
384
Jordan Rosed3934582012-09-28 22:21:30 +0000385void assignNil(Test *a) {
386 if (condition())
387 a.weakProp = nil; // expected-note{{also accessed here}}
388
Jordan Rose657b5f42012-09-28 22:21:35 +0000389 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000390}
391
392void branch(Test *a) {
393 if (condition())
Jordan Rose657b5f42012-09-28 22:21:35 +0000394 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000395 else
396 use(a.weakProp); // expected-note{{also accessed here}}
397}
398
399void doubleLevelAccess(Test *a, Test *b) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000400 use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000401 use(b.strongProp.weakProp); // expected-note{{also accessed here}}
402
403 use(a.weakProp.weakProp); // no-warning
404}
405
406void doubleLevelAccessIvar(Test *a, Test *b) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000407 use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000408 use(b->ivar.weakProp); // expected-note{{also accessed here}}
409
410 use(a.strongProp.weakProp); // no-warning
411}
Jordan Rose25c0ea82012-10-29 17:46:47 +0000412