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