[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / SemaObjC / arc-repeated-weak.mm
blobaaf8256d314eec8061a2860a2ee46e98a3e220e8
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
4 @interface Test {
5 @public
6   Test *ivar;
7   __weak id weakIvar;
9 @property(weak) Test *weakProp;
10 @property(strong) Test *strongProp;
12 - (__weak id)implicitProp;
14 + (__weak id)weakProp;
15 @end
17 extern void use(id);
18 extern id get();
19 extern bool condition();
20 #define nil ((id)0)
22 void basicCorrectnessTest(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}}
26   use(a.strongProp);
27   use(a.strongProp); // no-warning
29   use(a.weakProp); // expected-note{{also accessed here}}
32 void singleUse(Test *a) {
33   use(a.weakProp); // no-warning
34   use(a.strongProp); // no-warning
37 void assignsOnly(Test *a) {
38   a.weakProp = get(); // no-warning
40   id next = get();
41   if (next)
42     a.weakProp = next; // no-warning
44   a->weakIvar = get(); // no-warning
45   next = get();
46   if (next)
47     a->weakIvar = next; // no-warning
49   extern __weak id x;
50   x = get(); // no-warning
51   next = get();
52   if (next)
53     x = next; // no-warning
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}}
61 void twoVariables(Test *a, Test *b) {
62   use(a.weakProp); // no-warning
63   use(b.weakProp); // no-warning
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}}
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}}
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}}
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}}
86 void classPropertiesAreDifferent(Test *a) {
87   use(Test.weakProp); // no-warning
88   use(a.weakProp); // no-warning
89   use(a.strongProp.weakProp); // no-warning
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}}
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}}
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}}
108 void messageSetter(Test *a) {
109   [a setWeakProp:get()]; // no-warning
110   [a setWeakProp:get()]; // no-warning
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}}
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}}
122   use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
123   use(b.weakProp); // expected-note{{also accessed here}}
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}}
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}}
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}}
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}}
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   }
160 void assignToStrongConditional(Test *a) {
161   id val = (condition() ? a.weakProp : a.weakProp); // no-warning
162   id val2 = a.implicitProp ?: a.implicitProp; // no-warning
165 void testBlock(Test *a) {
166   use(a.weakProp); // no-warning
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   });
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   }
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   }
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
203 void readOnceWriteMany(Test *a) {
204   if (!a.weakProp) { // no-warning
205     a.weakProp = get(); // no-warning
206     a.weakProp = get(); // no-warning
207   }
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   }
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   }
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());
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   }
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   }
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   }
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   }
261 void readInIterationLoop() {
262   for (Test *a in get())
263     use(a.weakProp); // no-warning
266 void readDoubleLevelAccessInLoop() {
267   for (Test *a in get()) {
268     use(a.strongProp.weakProp); // no-warning
269   }
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   }
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   }
287 void doWhileLoop(Test *a) {
288   do {
289     use(a.weakProp); // no-warning
290   } while(0);
293 struct S {
294   int a;
295   id b;
298 @interface C
299 @property S p;
300 @end
302 void test_list_init(C *c) {
303   c.p = {0, c.p.b};
306 @interface Test (Methods)
307 @end
309 @implementation Test (Methods)
310 - (void)basicCorrectnessTest {
311   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}}
312   use(self.weakProp); // expected-note{{also accessed here}}
315 - (void)ivars {
316   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}}
317   use(weakIvar); // expected-note{{also accessed here}}
320 - (void)doubleLevelAccessForSelf {
321   use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
322   use(self.strongProp.weakProp); // expected-note{{also accessed here}}
324   use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
325   use(self->ivar.weakProp); // expected-note{{also accessed here}}
327   use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}}
328   use(self->ivar->weakIvar); // expected-note{{also accessed here}}
331 - (void)distinctFromOther:(Test *)other {
332   use(self.strongProp.weakProp); // no-warning
333   use(other.strongProp.weakProp); // no-warning
335   use(self->ivar.weakProp); // no-warning
336   use(other->ivar.weakProp); // no-warning
338   use(self.strongProp->weakIvar); // no-warning
339   use(other.strongProp->weakIvar); // no-warning
341 @end
343 @interface Base1
344 @end
345 @interface Sub1 : Base1
346 @end
347 @interface Sub1(cat)
348 -(id)prop;
349 @end
351 void test1(Sub1 *s) {
352   use([s prop]);
353   use([s prop]);
356 @interface Base1(cat)
357 @property (weak) id prop;
358 @end
360 void test2(Sub1 *s) {
361   // This does not warn because the "prop" in "Base1(cat)" was introduced
362   // after the method declaration and we don't find it as overridden.
363   // Always looking for overridden methods after the method declaration is expensive
364   // and it's not clear it is worth it currently.
365   use([s prop]);
366   use([s prop]);
370 class Wrapper {
371   Test *a;
373 public:
374   void fields() {
375     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}}
376     use(a.weakProp); // expected-note{{also accessed here}}
377   }
379   void distinctFromOther(Test *b, const Wrapper &w) {
380     use(a.weakProp); // no-warning
381     use(b.weakProp); // no-warning
382     use(w.a.weakProp); // no-warning
383   }
385   static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) {
386     use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
387     use(y.a.weakProp); // expected-note{{also accessed here}}
388   }
392 // -----------------------
393 // False positives
394 // -----------------------
396 // Most of these would require flow-sensitive analysis to silence correctly.
398 void assignNil(Test *a) {
399   if (condition())
400     a.weakProp = nil; // expected-note{{also accessed here}}
402   use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
405 void branch(Test *a) {
406   if (condition())
407     use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
408   else
409     use(a.weakProp); // expected-note{{also accessed here}}
412 void doubleLevelAccess(Test *a, Test *b) {
413   use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
414   use(b.strongProp.weakProp); // expected-note{{also accessed here}}
416   use(a.weakProp.weakProp); // no-warning
419 void doubleLevelAccessIvar(Test *a, Test *b) {
420   use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
421   use(b->ivar.weakProp); // expected-note{{also accessed here}}
423   use(a.strongProp.weakProp); // no-warning
426 @interface X
427 @end
429 @implementation X
430 - (int) warningAboutWeakVariableInsideTypeof {
431     __typeof__(self) __weak weakSelf = self;
432     ^(){
433         __typeof__(weakSelf) blockSelf = weakSelf;
434         use(blockSelf);
435     }();
436     return sizeof(weakSelf);
438 @end
440 @interface NSNull
441 + (NSNull *)null;
442 @end
444 @interface INTF @end
446 @implementation INTF
447 - (void) Meth : (id) data
449   data = data ?: NSNull.null;
451 @end
453 // This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was
454 // called on an ObjCPropertyRefExpr object whose receiver was an interface.
456 @class NSString;
457 @interface NSBundle
458 +(NSBundle *)foo;
459 @property (class, strong) NSBundle *foo2;
460 @property (strong) NSString *prop;
461 @property(weak) NSString *weakProp;
462 @end
464 @interface NSBundle2 : NSBundle
465 @end
467 void foo() {
468   NSString * t = NSBundle.foo.prop;
469   use(NSBundle.foo.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
470   use(NSBundle2.foo.weakProp); // expected-note{{also accessed here}}
472   NSString * t2 = NSBundle.foo2.prop;
473   use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
474   use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
475   decltype([NSBundle2.foo2 weakProp]) t3;
476   decltype(NSBundle2.foo2.weakProp) t4;
477   __typeof__(NSBundle2.foo2.weakProp) t5;
480 // This used to crash in the constructor of WeakObjectProfileTy when a
481 // DeclRefExpr was passed that didn't reference a VarDecl.
483 typedef INTF * INTFPtrTy;
485 enum E {
486   e1
489 void foo1() {
490   INTFPtrTy tmp = (INTFPtrTy)e1;
491 #if __has_feature(objc_arc)
492 // expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
493 #endif
496 @class NSString;
497 static NSString* const kGlobal = @"";
499 @interface NSDictionary
500 - (id)objectForKeyedSubscript:(id)key;
501 @end
503 @interface WeakProp
504 @property (weak) NSDictionary *nd;
505 @end
507 @implementation WeakProp
508 -(void)m {
509   (void)self.nd[@""]; // no warning
511 @end