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