]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/SemaObjC/arc-repeated-weak.mm
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3
[FreeBSD/FreeBSD.git] / test / SemaObjC / arc-repeated-weak.mm
1 // 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
2
3 @interface Test {
4 @public
5   Test *ivar;
6   __weak id weakIvar;
7 }
8 @property(weak) Test *weakProp;
9 @property(strong) Test *strongProp;
10
11 - (__weak id)implicitProp;
12
13 + (__weak id)weakProp;
14 @end
15
16 extern void use(id);
17 extern id get();
18 extern bool condition();
19 #define nil ((id)0)
20
21 void sanity(Test *a) {
22   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}}
23   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
31 void singleUse(Test *a) {
32   use(a.weakProp); // no-warning
33   use(a.strongProp); // no-warning
34 }
35
36 void assignsOnly(Test *a) {
37   a.weakProp = get(); // no-warning
38
39   id next = get();
40   if (next)
41     a.weakProp = next; // no-warning
42
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
53 }
54
55 void assignThenRead(Test *a) {
56   a.weakProp = get(); // expected-note{{also accessed here}}
57   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
58 }
59
60 void twoVariables(Test *a, Test *b) {
61   use(a.weakProp); // no-warning
62   use(b.weakProp); // no-warning
63 }
64
65 void doubleLevelAccess(Test *a) {
66   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}}
67   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
68 }
69
70 void doubleLevelAccessIvar(Test *a) {
71   use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
72   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
73 }
74
75 void implicitProperties(Test *a) {
76   use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
77   use(a.implicitProp); // expected-note{{also accessed here}}
78 }
79
80 void classProperties() {
81   use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
82   use(Test.weakProp); // expected-note{{also accessed here}}
83 }
84
85 void classPropertiesAreDifferent(Test *a) {
86   use(Test.weakProp); // no-warning
87   use(a.weakProp); // no-warning
88   use(a.strongProp.weakProp); // no-warning
89 }
90
91 void 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
96 void 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
102 void 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
107 void messageSetter(Test *a) {
108   [a setWeakProp:get()]; // no-warning
109   [a setWeakProp:get()]; // no-warning
110 }
111
112 void 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
117 void 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
125
126 void assignToStrongWrongInit(Test *a) {
127   id val = a.weakProp; // expected-note{{also accessed here}}
128   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
129 }
130
131 void assignToStrongWrong(Test *a) {
132   id val;
133   val = a.weakProp; // expected-note{{also accessed here}}
134   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
135 }
136
137 void 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
142 void 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}}
146 }
147
148 void 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
159 void assignToStrongConditional(Test *a) {
160   id val = (condition() ? a.weakProp : a.weakProp); // no-warning
161   id val2 = a.implicitProp ?: a.implicitProp; // no-warning
162 }
163
164 void testBlock(Test *a) {
165   use(a.weakProp); // no-warning
166
167   use(^{
168     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
169     use(a.weakProp); // expected-note{{also accessed here}}
170   });
171 }
172
173 void 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
184 void 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
196 void 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
202 void readOnceWriteMany(Test *a) {
203   if (!a.weakProp) { // no-warning
204     a.weakProp = get(); // no-warning
205     a.weakProp = get(); // no-warning
206   }
207 }
208
209 void 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
216 void 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
254 void 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
260 void readInIterationLoop() {
261   for (Test *a in get())
262     use(a.weakProp); // no-warning
263 }
264
265 void readDoubleLevelAccessInLoop() {
266   for (Test *a in get()) {
267     use(a.strongProp.weakProp); // no-warning
268   }
269 }
270
271 void 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
278 void 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
286 void doWhileLoop(Test *a) {
287   do {
288     use(a.weakProp); // no-warning
289   } while(0);
290 }
291
292
293 @interface Test (Methods)
294 @end
295
296 @implementation Test (Methods)
297 - (void)sanity {
298   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}}
299   use(self.weakProp); // expected-note{{also accessed here}}
300 }
301
302 - (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
307 - (void)doubleLevelAccessForSelf {
308   use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
309   use(self.strongProp.weakProp); // expected-note{{also accessed here}}
310
311   use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
312   use(self->ivar.weakProp); // expected-note{{also accessed here}}
313
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}}
316 }
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
324
325   use(self.strongProp->weakIvar); // no-warning
326   use(other.strongProp->weakIvar); // no-warning
327 }
328 @end
329
330 @interface Base1
331 @end
332 @interface Sub1 : Base1
333 @end
334 @interface Sub1(cat)
335 -(id)prop;
336 @end
337
338 void 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
347 void test2(Sub1 *s) {
348   // 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]);
354 }
355
356
357 class Wrapper {
358   Test *a;
359
360 public:
361   void fields() {
362     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}}
363     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) {
373     use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
374     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
385 void assignNil(Test *a) {
386   if (condition())
387     a.weakProp = nil; // expected-note{{also accessed here}}
388
389   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
390 }
391
392 void branch(Test *a) {
393   if (condition())
394     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
395   else
396     use(a.weakProp); // expected-note{{also accessed here}}
397 }
398
399 void doubleLevelAccess(Test *a, Test *b) {
400   use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
401   use(b.strongProp.weakProp); // expected-note{{also accessed here}}
402
403   use(a.weakProp.weakProp); // no-warning
404 }
405
406 void doubleLevelAccessIvar(Test *a, Test *b) {
407   use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
408   use(b->ivar.weakProp); // expected-note{{also accessed here}}
409
410   use(a.strongProp.weakProp); // no-warning
411 }
412