xref: /llvm-project/clang/test/SemaObjC/arc-repeated-weak.mm (revision 0f1c1be1968076d6f96f8a7bcc4a15cf195ecd97)
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
17extern void use(id);
18extern id get();
19extern bool condition();
20#define nil ((id)0)
21
22void 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}}
25
26  use(a.strongProp);
27  use(a.strongProp); // no-warning
28
29  use(a.weakProp); // expected-note{{also accessed here}}
30}
31
32void singleUse(Test *a) {
33  use(a.weakProp); // no-warning
34  use(a.strongProp); // no-warning
35}
36
37void 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
56void 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
61void twoVariables(Test *a, Test *b) {
62  use(a.weakProp); // no-warning
63  use(b.weakProp); // no-warning
64}
65
66void 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
71void 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
76void 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
81void 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
86void classPropertiesAreDifferent(Test *a) {
87  use(Test.weakProp); // no-warning
88  use(a.weakProp); // no-warning
89  use(a.strongProp.weakProp); // no-warning
90}
91
92void 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
97void 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
103void 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
108void messageSetter(Test *a) {
109  [a setWeakProp:get()]; // no-warning
110  [a setWeakProp:get()]; // no-warning
111}
112
113void 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
118void 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
127void 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
132void 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
138void 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
143void 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
149void 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
160void assignToStrongConditional(Test *a) {
161  id val = (condition() ? a.weakProp : a.weakProp); // no-warning
162  id val2 = a.implicitProp ?: a.implicitProp; // no-warning
163}
164
165void 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
174void 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
185void 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
197void 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
203void readOnceWriteMany(Test *a) {
204  if (!a.weakProp) { // no-warning
205    a.weakProp = get(); // no-warning
206    a.weakProp = get(); // no-warning
207  }
208}
209
210void 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
217void 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
255void 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
261void readInIterationLoop() {
262  for (Test *a in get())
263    use(a.weakProp); // no-warning
264}
265
266void readDoubleLevelAccessInLoop() {
267  for (Test *a in get()) {
268    use(a.strongProp.weakProp); // no-warning
269  }
270}
271
272void 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
279void 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
287void doWhileLoop(Test *a) {
288  do {
289    use(a.weakProp); // no-warning
290  } while(0);
291}
292
293struct S {
294  int a;
295  id b;
296};
297
298@interface C
299@property S p;
300@end
301
302void test_list_init(C *c) {
303  c.p = {0, c.p.b};
304}
305
306@interface Test (Methods)
307@end
308
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}}
313}
314
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}}
318}
319
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}}
323
324  use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
325  use(self->ivar.weakProp); // expected-note{{also accessed here}}
326
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}}
329}
330
331- (void)distinctFromOther:(Test *)other {
332  use(self.strongProp.weakProp); // no-warning
333  use(other.strongProp.weakProp); // no-warning
334
335  use(self->ivar.weakProp); // no-warning
336  use(other->ivar.weakProp); // no-warning
337
338  use(self.strongProp->weakIvar); // no-warning
339  use(other.strongProp->weakIvar); // no-warning
340}
341@end
342
343@interface Base1
344@end
345@interface Sub1 : Base1
346@end
347@interface Sub1(cat)
348-(id)prop;
349@end
350
351void test1(Sub1 *s) {
352  use([s prop]);
353  use([s prop]);
354}
355
356@interface Base1(cat)
357@property (weak) id prop;
358@end
359
360void 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]);
367}
368
369
370class Wrapper {
371  Test *a;
372
373public:
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  }
378
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  }
384
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  }
389};
390
391
392// -----------------------
393// False positives
394// -----------------------
395
396// Most of these would require flow-sensitive analysis to silence correctly.
397
398void assignNil(Test *a) {
399  if (condition())
400    a.weakProp = nil; // expected-note{{also accessed here}}
401
402  use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
403}
404
405void 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}}
410}
411
412void 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}}
415
416  use(a.weakProp.weakProp); // no-warning
417}
418
419void 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}}
422
423  use(a.strongProp.weakProp); // no-warning
424}
425
426@interface X
427@end
428
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);
437}
438@end
439
440@interface NSNull
441+ (NSNull *)null;
442@end
443
444@interface INTF @end
445
446@implementation INTF
447- (void) Meth : (id) data
448{
449  data = data ?: NSNull.null;
450}
451@end
452
453// This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was
454// called on an ObjCPropertyRefExpr object whose receiver was an interface.
455
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
463
464@interface NSBundle2 : NSBundle
465@end
466
467void 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}}
471
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;
478}
479
480// This used to crash in the constructor of WeakObjectProfileTy when a
481// DeclRefExpr was passed that didn't reference a VarDecl.
482
483typedef INTF * INTFPtrTy;
484
485enum E {
486  e1
487};
488
489void 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
494}
495
496@class NSString;
497static NSString* const kGlobal = @"";
498
499@interface NSDictionary
500- (id)objectForKeyedSubscript:(id)key;
501@end
502
503@interface WeakProp
504@property (weak) NSDictionary *nd;
505@end
506
507@implementation WeakProp
508-(void)m {
509  (void)self.nd[@""]; // no warning
510}
511@end
512