]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/SemaObjC/arc-repeated-weak.mm
Vendor import of clang trunk r300422:
[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 // RUN: %clang_cc1 -fsyntax-only -fobjc-runtime-has-weak -fobjc-weak -fblocks -Wno-objc-root-class -std=c++11 -Warc-repeated-use-of-weak -verify %s
3
4 @interface Test {
5 @public
6   Test *ivar;
7   __weak id weakIvar;
8 }
9 @property(weak) Test *weakProp;
10 @property(strong) Test *strongProp;
11
12 - (__weak id)implicitProp;
13
14 + (__weak id)weakProp;
15 @end
16
17 extern void use(id);
18 extern id get();
19 extern bool condition();
20 #define nil ((id)0)
21
22 void sanity(Test *a) {
23   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}}
24   use(a.weakProp); // expected-note{{also accessed here}}
25
26   use(a.strongProp);
27   use(a.strongProp); // no-warning
28
29   use(a.weakProp); // expected-note{{also accessed here}}
30 }
31
32 void singleUse(Test *a) {
33   use(a.weakProp); // no-warning
34   use(a.strongProp); // no-warning
35 }
36
37 void assignsOnly(Test *a) {
38   a.weakProp = get(); // no-warning
39
40   id next = get();
41   if (next)
42     a.weakProp = next; // no-warning
43
44   a->weakIvar = get(); // no-warning
45   next = get();
46   if (next)
47     a->weakIvar = next; // no-warning
48
49   extern __weak id x;
50   x = get(); // no-warning
51   next = get();
52   if (next)
53     x = next; // no-warning
54 }
55
56 void assignThenRead(Test *a) {
57   a.weakProp = get(); // expected-note{{also accessed here}}
58   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
59 }
60
61 void twoVariables(Test *a, Test *b) {
62   use(a.weakProp); // no-warning
63   use(b.weakProp); // no-warning
64 }
65
66 void doubleLevelAccess(Test *a) {
67   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}}
68   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
69 }
70
71 void doubleLevelAccessIvar(Test *a) {
72   use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
73   use(a.strongProp.weakProp); // expected-note{{also accessed here}}
74 }
75
76 void implicitProperties(Test *a) {
77   use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
78   use(a.implicitProp); // expected-note{{also accessed here}}
79 }
80
81 void classProperties() {
82   use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
83   use(Test.weakProp); // expected-note{{also accessed here}}
84 }
85
86 void classPropertiesAreDifferent(Test *a) {
87   use(Test.weakProp); // no-warning
88   use(a.weakProp); // no-warning
89   use(a.strongProp.weakProp); // no-warning
90 }
91
92 void ivars(Test *a) {
93   use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
94   use(a->weakIvar); // expected-note{{also accessed here}}
95 }
96
97 void globals() {
98   extern __weak id a;
99   use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
100   use(a); // expected-note{{also accessed here}}
101 }
102
103 void messageGetter(Test *a) {
104   use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
105   use([a weakProp]); // expected-note{{also accessed here}}
106 }
107
108 void messageSetter(Test *a) {
109   [a setWeakProp:get()]; // no-warning
110   [a setWeakProp:get()]; // no-warning
111 }
112
113 void messageSetterAndGetter(Test *a) {
114   [a setWeakProp:get()]; // expected-note{{also accessed here}}
115   use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
116 }
117
118 void mixDotAndMessageSend(Test *a, Test *b) {
119   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
120   use([a weakProp]); // expected-note{{also accessed here}}
121
122   use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
123   use(b.weakProp); // expected-note{{also accessed here}}
124 }
125
126
127 void assignToStrongWrongInit(Test *a) {
128   id val = a.weakProp; // expected-note{{also accessed here}}
129   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
130 }
131
132 void assignToStrongWrong(Test *a) {
133   id val;
134   val = a.weakProp; // expected-note{{also accessed here}}
135   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
136 }
137
138 void assignToIvarWrong(Test *a) {
139   a->weakIvar = get(); // expected-note{{also accessed here}}
140   use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
141 }
142
143 void assignToGlobalWrong() {
144   extern __weak id a;
145   a = get(); // expected-note{{also accessed here}}
146   use(a); // expected-warning{{weak variable 'a' is accessed multiple times}}
147 }
148
149 void assignToStrongOK(Test *a) {
150   if (condition()) {
151     id val = a.weakProp; // no-warning
152     (void)val;
153   } else {
154     id val;
155     val = a.weakProp; // no-warning
156     (void)val;
157   }
158 }
159
160 void assignToStrongConditional(Test *a) {
161   id val = (condition() ? a.weakProp : a.weakProp); // no-warning
162   id val2 = a.implicitProp ?: a.implicitProp; // no-warning
163 }
164
165 void testBlock(Test *a) {
166   use(a.weakProp); // no-warning
167
168   use(^{
169     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
170     use(a.weakProp); // expected-note{{also accessed here}}
171   });
172 }
173
174 void assignToStrongWithCasts(Test *a) {
175   if (condition()) {
176     Test *val = (Test *)a.weakProp; // no-warning
177     (void)val;
178   } else {
179     id val;
180     val = (Test *)a.weakProp; // no-warning
181     (void)val;
182   }
183 }
184
185 void assignToStrongWithMessages(Test *a) {
186   if (condition()) {
187     id val = [a weakProp]; // no-warning
188     (void)val;
189   } else {
190     id val;
191     val = [a weakProp]; // no-warning
192     (void)val;
193   }
194 }
195
196
197 void assignAfterRead(Test *a) {
198   // Special exception for a single read before any writes.
199   if (!a.weakProp) // no-warning
200     a.weakProp = get(); // no-warning
201 }
202
203 void readOnceWriteMany(Test *a) {
204   if (!a.weakProp) { // no-warning
205     a.weakProp = get(); // no-warning
206     a.weakProp = get(); // no-warning
207   }
208 }
209
210 void readOnceAfterWrite(Test *a) {
211   a.weakProp = get(); // expected-note{{also accessed here}}
212   if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
213     a.weakProp = get(); // expected-note{{also accessed here}}
214   }
215 }
216
217 void readOnceWriteManyLoops(Test *a, Test *b, Test *c, Test *d, Test *e) {
218   while (condition()) {
219     if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
220       a.weakProp = get(); // expected-note{{also accessed here}}
221       a.weakProp = get(); // expected-note{{also accessed here}}
222     }
223   }
224
225   do {
226     if (!b.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
227       b.weakProp = get(); // expected-note{{also accessed here}}
228       b.weakProp = get(); // expected-note{{also accessed here}}
229     }
230   } while (condition());
231
232   for (id x = get(); x; x = get()) {
233     if (!c.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
234       c.weakProp = get(); // expected-note{{also accessed here}}
235       c.weakProp = get(); // expected-note{{also accessed here}}
236     }
237   }
238
239   for (id x in get()) {
240     if (!d.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
241       d.weakProp = get(); // expected-note{{also accessed here}}
242       d.weakProp = get(); // expected-note{{also accessed here}}
243     }
244   }
245
246   int array[] = { 1, 2, 3 };
247   for (int i : array) {
248     if (!e.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
249       e.weakProp = get(); // expected-note{{also accessed here}}
250       e.weakProp = get(); // expected-note{{also accessed here}}
251     }
252   }
253 }
254
255 void readOnlyLoop(Test *a) {
256   while (condition()) {
257     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
258   }
259 }
260
261 void readInIterationLoop() {
262   for (Test *a in get())
263     use(a.weakProp); // no-warning
264 }
265
266 void readDoubleLevelAccessInLoop() {
267   for (Test *a in get()) {
268     use(a.strongProp.weakProp); // no-warning
269   }
270 }
271
272 void readParameterInLoop(Test *a) {
273   for (id unused in get()) {
274     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}}
275     (void)unused;
276   }
277 }
278
279 void readGlobalInLoop() {
280   static __weak id a;
281   for (id unused in get()) {
282     use(a); // expected-warning{{weak variable 'a' is accessed multiple times in this function}}
283     (void)unused;
284   }
285 }
286
287 void doWhileLoop(Test *a) {
288   do {
289     use(a.weakProp); // no-warning
290   } while(0);
291 }
292
293
294 @interface Test (Methods)
295 @end
296
297 @implementation Test (Methods)
298 - (void)sanity {
299   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}}
300   use(self.weakProp); // expected-note{{also accessed here}}
301 }
302
303 - (void)ivars {
304   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}}
305   use(weakIvar); // expected-note{{also accessed here}}
306 }
307
308 - (void)doubleLevelAccessForSelf {
309   use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
310   use(self.strongProp.weakProp); // expected-note{{also accessed here}}
311
312   use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
313   use(self->ivar.weakProp); // expected-note{{also accessed here}}
314
315   use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
316   use(self->ivar->weakIvar); // expected-note{{also accessed here}}
317 }
318
319 - (void)distinctFromOther:(Test *)other {
320   use(self.strongProp.weakProp); // no-warning
321   use(other.strongProp.weakProp); // no-warning
322
323   use(self->ivar.weakProp); // no-warning
324   use(other->ivar.weakProp); // no-warning
325
326   use(self.strongProp->weakIvar); // no-warning
327   use(other.strongProp->weakIvar); // no-warning
328 }
329 @end
330
331 @interface Base1
332 @end
333 @interface Sub1 : Base1
334 @end
335 @interface Sub1(cat)
336 -(id)prop;
337 @end
338
339 void test1(Sub1 *s) {
340   use([s prop]);
341   use([s prop]);
342 }
343
344 @interface Base1(cat)
345 @property (weak) id prop;
346 @end
347
348 void test2(Sub1 *s) {
349   // This does not warn because the "prop" in "Base1(cat)" was introduced
350   // after the method declaration and we don't find it as overridden.
351   // Always looking for overridden methods after the method declaration is expensive
352   // and it's not clear it is worth it currently.
353   use([s prop]);
354   use([s prop]);
355 }
356
357
358 class Wrapper {
359   Test *a;
360
361 public:
362   void fields() {
363     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}}
364     use(a.weakProp); // expected-note{{also accessed here}}
365   }
366
367   void distinctFromOther(Test *b, const Wrapper &w) {
368     use(a.weakProp); // no-warning
369     use(b.weakProp); // no-warning
370     use(w.a.weakProp); // no-warning
371   }
372
373   static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
374     use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
375     use(y.a.weakProp); // expected-note{{also accessed here}}
376   }
377 };
378
379
380 // -----------------------
381 // False positives
382 // -----------------------
383
384 // Most of these would require flow-sensitive analysis to silence correctly.
385
386 void assignNil(Test *a) {
387   if (condition())
388     a.weakProp = nil; // expected-note{{also accessed here}}
389
390   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
391 }
392
393 void branch(Test *a) {
394   if (condition())
395     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
396   else
397     use(a.weakProp); // expected-note{{also accessed here}}
398 }
399
400 void doubleLevelAccess(Test *a, Test *b) {
401   use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
402   use(b.strongProp.weakProp); // expected-note{{also accessed here}}
403
404   use(a.weakProp.weakProp); // no-warning
405 }
406
407 void doubleLevelAccessIvar(Test *a, Test *b) {
408   use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
409   use(b->ivar.weakProp); // expected-note{{also accessed here}}
410
411   use(a.strongProp.weakProp); // no-warning
412 }
413
414 // rdar://13942025
415 @interface X
416 @end
417
418 @implementation X
419 - (int) warningAboutWeakVariableInsideTypeof {
420     __typeof__(self) __weak weakSelf = self;
421     ^(){
422         __typeof__(weakSelf) blockSelf = weakSelf;
423         use(blockSelf);
424     }();
425     return sizeof(weakSelf);
426 }
427 @end
428
429 // rdar://19053620
430 @interface NSNull
431 + (NSNull *)null;
432 @end
433
434 @interface INTF @end
435
436 @implementation INTF
437 - (void) Meth : (id) data
438 {
439   data = data ?: NSNull.null;
440 }
441 @end
442
443 // This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was
444 // called on an ObjCPropertyRefExpr object whose receiver was an interface.
445
446 @class NSString;
447 @interface NSBundle
448 +(NSBundle *)foo;
449 @property (class, strong) NSBundle *foo2;
450 @property (strong) NSString *prop;
451 @property(weak) NSString *weakProp;
452 @end
453
454 @interface NSBundle2 : NSBundle
455 @end
456
457 void foo() {
458   NSString * t = NSBundle.foo.prop;
459   use(NSBundle.foo.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
460   use(NSBundle2.foo.weakProp); // expected-note{{also accessed here}}
461
462   NSString * t2 = NSBundle.foo2.prop;
463   use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
464   use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
465 }
466
467 // This used to crash in the constructor of WeakObjectProfileTy when a
468 // DeclRefExpr was passed that didn't reference a VarDecl.
469
470 typedef INTF * INTFPtrTy;
471
472 enum E {
473   e1
474 };
475
476 void foo1() {
477   INTFPtrTy tmp = (INTFPtrTy)e1;
478 #if __has_feature(objc_arc)
479 // expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
480 #endif
481 }