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
16extern void use(id);
17extern id get();
18extern bool condition();
19#define nil ((id)0)
20
21void 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
31void singleUse(Test *a) {
32  use(a.weakProp); // no-warning
33  use(a.strongProp); // no-warning
34}
35
36void 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
55void 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
60void twoVariables(Test *a, Test *b) {
61  use(a.weakProp); // no-warning
62  use(b.weakProp); // no-warning
63}
64
65void 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
70void 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
75void 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
80void 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
85void classPropertiesAreDifferent(Test *a) {
86  use(Test.weakProp); // no-warning
87  use(a.weakProp); // no-warning
88  use(a.strongProp.weakProp); // no-warning
89}
90
91void 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
96void 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
102void 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
107void messageSetter(Test *a) {
108  [a setWeakProp:get()]; // no-warning
109  [a setWeakProp:get()]; // no-warning
110}
111
112void 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
117void 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
126void 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
131void 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
137void 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
142void 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
148void 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
159void assignToStrongConditional(Test *a) {
160  id val = (condition() ? a.weakProp : a.weakProp); // no-warning
161  id val2 = a.implicitProp ?: a.implicitProp; // no-warning
162}
163
164void 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
173void 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
184void 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
196void 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
202void readOnceWriteMany(Test *a) {
203  if (!a.weakProp) { // no-warning
204    a.weakProp = get(); // no-warning
205    a.weakProp = get(); // no-warning
206  }
207}
208
209void 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
216void 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
254void 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
260void readInIterationLoop() {
261  for (Test *a in get())
262    use(a.weakProp); // no-warning
263}
264
265void readDoubleLevelAccessInLoop() {
266  for (Test *a in get()) {
267    use(a.strongProp.weakProp); // no-warning
268  }
269}
270
271void 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
278void 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
286void 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
338void 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
347void 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
357class Wrapper {
358  Test *a;
359
360public:
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
385void 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
392void 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
399void 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
406void 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
413// rdar://13942025
414@interface X
415@end
416
417@implementation X
418- (int) warningAboutWeakVariableInsideTypeof {
419    __typeof__(self) __weak weakSelf = self;
420    ^(){
421        __typeof__(weakSelf) blockSelf = weakSelf;
422        use(blockSelf);
423    }();
424    return sizeof(weakSelf);
425}
426@end
427
428// rdar://19053620
429@interface NSNull
430+ (NSNull *)null;
431@end
432
433@interface INTF @end
434
435@implementation INTF
436- (void) Meth : (id) data
437{
438  data = data ?: NSNull.null;
439}
440@end
441
442// This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was
443// called on an ObjCPropertyRefExpr object whose receiver was an interface.
444
445@class NSString;
446@interface NSBundle
447+(NSBundle *)foo;
448@property (class) NSBundle *foo2;
449@property NSString *prop;
450@property(weak) NSString *weakProp;
451@end
452
453@interface NSBundle2 : NSBundle
454@end
455
456void foo() {
457  NSString * t = NSBundle.foo.prop;
458  use(NSBundle.foo.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
459  use(NSBundle2.foo.weakProp); // expected-note{{also accessed here}}
460
461  NSString * t2 = NSBundle.foo2.prop;
462  use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
463  use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}}
464}
465