512 lines · plain
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 %s2// 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 %s3 4@interface Test {5@public6 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@end16 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-warning28 29 use(a.weakProp); // expected-note{{also accessed here}}30}31 32void singleUse(Test *a) {33 use(a.weakProp); // no-warning34 use(a.strongProp); // no-warning35}36 37void assignsOnly(Test *a) {38 a.weakProp = get(); // no-warning39 40 id next = get();41 if (next)42 a.weakProp = next; // no-warning43 44 a->weakIvar = get(); // no-warning45 next = get();46 if (next)47 a->weakIvar = next; // no-warning48 49 extern __weak id x;50 x = get(); // no-warning51 next = get();52 if (next)53 x = next; // no-warning54}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-warning63 use(b.weakProp); // no-warning64}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-warning88 use(a.weakProp); // no-warning89 use(a.strongProp.weakProp); // no-warning90}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-warning110 [a setWeakProp:get()]; // no-warning111}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-warning152 (void)val;153 } else {154 id val;155 val = a.weakProp; // no-warning156 (void)val;157 }158}159 160void assignToStrongConditional(Test *a) {161 id val = (condition() ? a.weakProp : a.weakProp); // no-warning162 id val2 = a.implicitProp ?: a.implicitProp; // no-warning163}164 165void testBlock(Test *a) {166 use(a.weakProp); // no-warning167 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-warning177 (void)val;178 } else {179 id val;180 val = (Test *)a.weakProp; // no-warning181 (void)val;182 }183}184 185void assignToStrongWithMessages(Test *a) {186 if (condition()) {187 id val = [a weakProp]; // no-warning188 (void)val;189 } else {190 id val;191 val = [a weakProp]; // no-warning192 (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-warning200 a.weakProp = get(); // no-warning201}202 203void readOnceWriteMany(Test *a) {204 if (!a.weakProp) { // no-warning205 a.weakProp = get(); // no-warning206 a.weakProp = get(); // no-warning207 }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-warning264}265 266void readDoubleLevelAccessInLoop() {267 for (Test *a in get()) {268 use(a.strongProp.weakProp); // no-warning269 }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-warning290 } while(0);291}292 293struct S {294 int a;295 id b;296};297 298@interface C299@property S p;300@end301 302void test_list_init(C *c) {303 c.p = {0, c.p.b};304}305 306@interface Test (Methods)307@end308 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-warning333 use(other.strongProp.weakProp); // no-warning334 335 use(self->ivar.weakProp); // no-warning336 use(other->ivar.weakProp); // no-warning337 338 use(self.strongProp->weakIvar); // no-warning339 use(other.strongProp->weakIvar); // no-warning340}341@end342 343@interface Base1344@end345@interface Sub1 : Base1346@end347@interface Sub1(cat)348-(id)prop;349@end350 351void test1(Sub1 *s) {352 use([s prop]);353 use([s prop]);354}355 356@interface Base1(cat)357@property (weak) id prop;358@end359 360void test2(Sub1 *s) {361 // This does not warn because the "prop" in "Base1(cat)" was introduced362 // after the method declaration and we don't find it as overridden.363 // Always looking for overridden methods after the method declaration is expensive364 // 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-warning381 use(b.weakProp); // no-warning382 use(w.a.weakProp); // no-warning383 }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 positives394// -----------------------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 else409 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-warning417}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-warning424}425 426@interface X427@end428 429@implementation X430- (int) warningAboutWeakVariableInsideTypeof {431 __typeof__(self) __weak weakSelf = self;432 ^(){433 __typeof__(weakSelf) blockSelf = weakSelf;434 use(blockSelf);435 }();436 return sizeof(weakSelf);437}438@end439 440@interface NSNull441+ (NSNull *)null;442@end443 444@interface INTF @end445 446@implementation INTF447- (void) Meth : (id) data448{449 data = data ?: NSNull.null;450}451@end452 453// This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was454// called on an ObjCPropertyRefExpr object whose receiver was an interface.455 456@class NSString;457@interface NSBundle458+(NSBundle *)foo;459@property (class, strong) NSBundle *foo2;460@property (strong) NSString *prop;461@property(weak) NSString *weakProp;462@end463 464@interface NSBundle2 : NSBundle465@end466 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 a481// DeclRefExpr was passed that didn't reference a VarDecl.482 483typedef INTF * INTFPtrTy;484 485enum E {486 e1487};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#endif494}495 496@class NSString;497static NSString* const kGlobal = @"";498 499@interface NSDictionary500- (id)objectForKeyedSubscript:(id)key;501@end502 503@interface WeakProp504@property (weak) NSDictionary *nd;505@end506 507@implementation WeakProp508-(void)m {509 (void)self.nd[@""]; // no warning510}511@end512