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