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 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
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
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
339void 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
348void 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
358class Wrapper {
359  Test *a;
360
361public:
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
386void 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
393void 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
400void 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
407void 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
457void 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  decltype([NSBundle2.foo2 weakProp]) t3;
466  decltype(NSBundle2.foo2.weakProp) t4;
467  __typeof__(NSBundle2.foo2.weakProp) t5;
468}
469
470// This used to crash in the constructor of WeakObjectProfileTy when a
471// DeclRefExpr was passed that didn't reference a VarDecl.
472
473typedef INTF * INTFPtrTy;
474
475enum E {
476  e1
477};
478
479void foo1() {
480  INTFPtrTy tmp = (INTFPtrTy)e1;
481#if __has_feature(objc_arc)
482// expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}}
483#endif
484}
485
486@class NSString;
487static NSString* const kGlobal = @"";
488
489@interface NSDictionary
490- (id)objectForKeyedSubscript:(id)key;
491@end
492
493@interface WeakProp
494@property (weak) NSDictionary *nd;
495@end
496
497@implementation WeakProp
498-(void)m {
499  (void)self.nd[@""]; // no warning
500}
501@end
502