blob: 37b2123ec1c42ca8a54cee1729a9388c4739124c [file] [log] [blame]
Jordan Rose76831c62012-10-11 16:10:19 +00001// 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
Brian Kelleycafd9122017-03-29 17:55:11 +00002// 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
Jordan Rosed3934582012-09-28 22:21:30 +00003
4@interface Test {
5@public
6 Test *ivar;
Jordan Rose657b5f42012-09-28 22:21:35 +00007 __weak id weakIvar;
Jordan Rosed3934582012-09-28 22:21:30 +00008}
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) {
Jordan Rose657b5f42012-09-28 22:21:35 +000023 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}}
Jordan Rosed3934582012-09-28 22:21:30 +000024 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
Jordan Rose657b5f42012-09-28 22:21:35 +000043
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
Jordan Rosed3934582012-09-28 22:21:30 +000054}
55
56void assignThenRead(Test *a) {
57 a.weakProp = get(); // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +000058 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000059}
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) {
Jordan Rose657b5f42012-09-28 22:21:35 +000067 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}}
Jordan Rosed3934582012-09-28 22:21:30 +000068 use(a.strongProp.weakProp); // expected-note{{also accessed here}}
69}
70
71void doubleLevelAccessIvar(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000072 use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000073 use(a.strongProp.weakProp); // expected-note{{also accessed here}}
74}
75
76void implicitProperties(Test *a) {
Jordan Rose657b5f42012-09-28 22:21:35 +000077 use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000078 use(a.implicitProp); // expected-note{{also accessed here}}
79}
80
81void classProperties() {
Jordan Rose657b5f42012-09-28 22:21:35 +000082 use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +000083 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
Jordan Rose657b5f42012-09-28 22:21:35 +000092void 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
Jordan Rose22487652012-10-11 16:06:21 +0000103void 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
Jordan Rosed3934582012-09-28 22:21:30 +0000126
127void assignToStrongWrongInit(Test *a) {
128 id val = a.weakProp; // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000129 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000130}
131
132void assignToStrongWrong(Test *a) {
133 id val;
134 val = a.weakProp; // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000135 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}}
Jordan Rosed3934582012-09-28 22:21:30 +0000147}
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(^{
Jordan Rose657b5f42012-09-28 22:21:35 +0000169 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}}
Jordan Rosed3934582012-09-28 22:21:30 +0000170 use(a.weakProp); // expected-note{{also accessed here}}
171 });
172}
173
Jordan Rosee723a272012-10-10 16:43:06 +0000174void 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
Jordan Roseb1e3e5f2012-10-11 17:02:00 +0000185void 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
Jordan Rose76831c62012-10-11 16:10:19 +0000197void 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
Jordan Rose25c0ea82012-10-29 17:46:47 +0000261void 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
Jordan Rosed3934582012-09-28 22:21:30 +0000293
294@interface Test (Methods)
295@end
296
297@implementation Test (Methods)
298- (void)sanity {
Jordan Rose657b5f42012-09-28 22:21:35 +0000299 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}}
Jordan Rosed3934582012-09-28 22:21:30 +0000300 use(self.weakProp); // expected-note{{also accessed here}}
301}
302
Jordan Rose657b5f42012-09-28 22:21:35 +0000303- (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
Jordan Rosed3934582012-09-28 22:21:30 +0000308- (void)doubleLevelAccessForSelf {
Jordan Rose657b5f42012-09-28 22:21:35 +0000309 use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000310 use(self.strongProp.weakProp); // expected-note{{also accessed here}}
311
Jordan Rose657b5f42012-09-28 22:21:35 +0000312 use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000313 use(self->ivar.weakProp); // expected-note{{also accessed here}}
Jordan Rose657b5f42012-09-28 22:21:35 +0000314
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}}
Jordan Rosed3934582012-09-28 22:21:30 +0000317}
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
Jordan Rose657b5f42012-09-28 22:21:35 +0000325
326 use(self.strongProp->weakIvar); // no-warning
327 use(other.strongProp->weakIvar); // no-warning
Jordan Rosed3934582012-09-28 22:21:30 +0000328}
329@end
330
Argyrios Kyrtzidisfe7a59d2013-04-15 18:47:22 +0000331@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) {
Argyrios Kyrtzidisc2091d52013-04-17 00:09:08 +0000349 // 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]);
Argyrios Kyrtzidisfe7a59d2013-04-15 18:47:22 +0000355}
356
Jordan Rosed3934582012-09-28 22:21:30 +0000357
358class Wrapper {
359 Test *a;
360
361public:
362 void fields() {
Jordan Rose657b5f42012-09-28 22:21:35 +0000363 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}}
Jordan Rosed3934582012-09-28 22:21:30 +0000364 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) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000374 use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000375 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
Jordan Rosed3934582012-09-28 22:21:30 +0000386void assignNil(Test *a) {
387 if (condition())
388 a.weakProp = nil; // expected-note{{also accessed here}}
389
Jordan Rose657b5f42012-09-28 22:21:35 +0000390 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000391}
392
393void branch(Test *a) {
394 if (condition())
Jordan Rose657b5f42012-09-28 22:21:35 +0000395 use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000396 else
397 use(a.weakProp); // expected-note{{also accessed here}}
398}
399
400void doubleLevelAccess(Test *a, Test *b) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000401 use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000402 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) {
Jordan Rose657b5f42012-09-28 22:21:35 +0000408 use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}}
Jordan Rosed3934582012-09-28 22:21:30 +0000409 use(b->ivar.weakProp); // expected-note{{also accessed here}}
410
411 use(a.strongProp.weakProp); // no-warning
412}
Jordan Rose25c0ea82012-10-29 17:46:47 +0000413
Fariborz Jahanian6f829e32013-05-21 21:20:26 +0000414// 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
Fariborz Jahanianac1c5122014-11-21 21:12:11 +0000429// 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
Akira Hatanaka4c62c7c2016-03-18 19:03:50 +0000443// 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;
Brian Kelleycafd9122017-03-29 17:55:11 +0000449@property (class, strong) NSBundle *foo2;
450@property (strong) NSString *prop;
Akira Hatanaka7e2c82d2016-03-22 05:00:21 +0000451@property(weak) NSString *weakProp;
452@end
453
454@interface NSBundle2 : NSBundle
Akira Hatanaka4c62c7c2016-03-18 19:03:50 +0000455@end
456
457void foo() {
458 NSString * t = NSBundle.foo.prop;
Akira Hatanaka7e2c82d2016-03-22 05:00:21 +0000459 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}}
Akira Hatanaka4c62c7c2016-03-18 19:03:50 +0000465}
Akira Hatanaka034c6332017-02-01 20:22:26 +0000466
467// This used to crash in the constructor of WeakObjectProfileTy when a
468// DeclRefExpr was passed that didn't reference a VarDecl.
469
470typedef INTF * INTFPtrTy;
471
472enum E {
473 e1
474};
475
476void foo1() {
Brian Kelleycafd9122017-03-29 17:55:11 +0000477 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
Akira Hatanaka034c6332017-02-01 20:22:26 +0000481}