// 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 // 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 @interface Test { @public Test *ivar; __weak id weakIvar; } @property(weak) Test *weakProp; @property(strong) Test *strongProp; - (__weak id)implicitProp; + (__weak id)weakProp; @end extern void use(id); extern id get(); extern bool condition(); #define nil ((id)0) void sanity(Test *a) { 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}} use(a.weakProp); // expected-note{{also accessed here}} use(a.strongProp); use(a.strongProp); // no-warning use(a.weakProp); // expected-note{{also accessed here}} } void singleUse(Test *a) { use(a.weakProp); // no-warning use(a.strongProp); // no-warning } void assignsOnly(Test *a) { a.weakProp = get(); // no-warning id next = get(); if (next) a.weakProp = next; // no-warning a->weakIvar = get(); // no-warning next = get(); if (next) a->weakIvar = next; // no-warning extern __weak id x; x = get(); // no-warning next = get(); if (next) x = next; // no-warning } void assignThenRead(Test *a) { a.weakProp = get(); // expected-note{{also accessed here}} use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} } void twoVariables(Test *a, Test *b) { use(a.weakProp); // no-warning use(b.weakProp); // no-warning } void doubleLevelAccess(Test *a) { 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}} use(a.strongProp.weakProp); // expected-note{{also accessed here}} } void doubleLevelAccessIvar(Test *a) { use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(a.strongProp.weakProp); // expected-note{{also accessed here}} } void implicitProperties(Test *a) { use(a.implicitProp); // expected-warning{{weak implicit property 'implicitProp' is accessed multiple times}} use(a.implicitProp); // expected-note{{also accessed here}} } void classProperties() { use(Test.weakProp); // expected-warning{{weak implicit property 'weakProp' is accessed multiple times}} use(Test.weakProp); // expected-note{{also accessed here}} } void classPropertiesAreDifferent(Test *a) { use(Test.weakProp); // no-warning use(a.weakProp); // no-warning use(a.strongProp.weakProp); // no-warning } void ivars(Test *a) { use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}} use(a->weakIvar); // expected-note{{also accessed here}} } void globals() { extern __weak id a; use(a); // expected-warning{{weak variable 'a' is accessed multiple times}} use(a); // expected-note{{also accessed here}} } void messageGetter(Test *a) { use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} use([a weakProp]); // expected-note{{also accessed here}} } void messageSetter(Test *a) { [a setWeakProp:get()]; // no-warning [a setWeakProp:get()]; // no-warning } void messageSetterAndGetter(Test *a) { [a setWeakProp:get()]; // expected-note{{also accessed here}} use([a weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} } void mixDotAndMessageSend(Test *a, Test *b) { use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} use([a weakProp]); // expected-note{{also accessed here}} use([b weakProp]); // expected-warning{{weak property 'weakProp' is accessed multiple times}} use(b.weakProp); // expected-note{{also accessed here}} } void assignToStrongWrongInit(Test *a) { id val = a.weakProp; // expected-note{{also accessed here}} use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} } void assignToStrongWrong(Test *a) { id val; val = a.weakProp; // expected-note{{also accessed here}} use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} } void assignToIvarWrong(Test *a) { a->weakIvar = get(); // expected-note{{also accessed here}} use(a->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}} } void assignToGlobalWrong() { extern __weak id a; a = get(); // expected-note{{also accessed here}} use(a); // expected-warning{{weak variable 'a' is accessed multiple times}} } void assignToStrongOK(Test *a) { if (condition()) { id val = a.weakProp; // no-warning (void)val; } else { id val; val = a.weakProp; // no-warning (void)val; } } void assignToStrongConditional(Test *a) { id val = (condition() ? a.weakProp : a.weakProp); // no-warning id val2 = a.implicitProp ?: a.implicitProp; // no-warning } void testBlock(Test *a) { use(a.weakProp); // no-warning use(^{ use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this block}} use(a.weakProp); // expected-note{{also accessed here}} }); } void assignToStrongWithCasts(Test *a) { if (condition()) { Test *val = (Test *)a.weakProp; // no-warning (void)val; } else { id val; val = (Test *)a.weakProp; // no-warning (void)val; } } void assignToStrongWithMessages(Test *a) { if (condition()) { id val = [a weakProp]; // no-warning (void)val; } else { id val; val = [a weakProp]; // no-warning (void)val; } } void assignAfterRead(Test *a) { // Special exception for a single read before any writes. if (!a.weakProp) // no-warning a.weakProp = get(); // no-warning } void readOnceWriteMany(Test *a) { if (!a.weakProp) { // no-warning a.weakProp = get(); // no-warning a.weakProp = get(); // no-warning } } void readOnceAfterWrite(Test *a) { a.weakProp = get(); // expected-note{{also accessed here}} if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} a.weakProp = get(); // expected-note{{also accessed here}} } } void readOnceWriteManyLoops(Test *a, Test *b, Test *c, Test *d, Test *e) { while (condition()) { if (!a.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} a.weakProp = get(); // expected-note{{also accessed here}} a.weakProp = get(); // expected-note{{also accessed here}} } } do { if (!b.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} b.weakProp = get(); // expected-note{{also accessed here}} b.weakProp = get(); // expected-note{{also accessed here}} } } while (condition()); for (id x = get(); x; x = get()) { if (!c.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} c.weakProp = get(); // expected-note{{also accessed here}} c.weakProp = get(); // expected-note{{also accessed here}} } } for (id x in get()) { if (!d.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} d.weakProp = get(); // expected-note{{also accessed here}} d.weakProp = get(); // expected-note{{also accessed here}} } } int array[] = { 1, 2, 3 }; for (int i : array) { if (!e.weakProp) { // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} e.weakProp = get(); // expected-note{{also accessed here}} e.weakProp = get(); // expected-note{{also accessed here}} } } } void readOnlyLoop(Test *a) { while (condition()) { use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} } } void readInIterationLoop() { for (Test *a in get()) use(a.weakProp); // no-warning } void readDoubleLevelAccessInLoop() { for (Test *a in get()) { use(a.strongProp.weakProp); // no-warning } } void readParameterInLoop(Test *a) { for (id unused in get()) { use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times in this function}} (void)unused; } } void readGlobalInLoop() { static __weak id a; for (id unused in get()) { use(a); // expected-warning{{weak variable 'a' is accessed multiple times in this function}} (void)unused; } } void doWhileLoop(Test *a) { do { use(a.weakProp); // no-warning } while(0); } @interface Test (Methods) @end @implementation Test (Methods) - (void)sanity { 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}} use(self.weakProp); // expected-note{{also accessed here}} } - (void)ivars { 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}} use(weakIvar); // expected-note{{also accessed here}} } - (void)doubleLevelAccessForSelf { use(self.strongProp.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} use(self.strongProp.weakProp); // expected-note{{also accessed here}} use(self->ivar.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} use(self->ivar.weakProp); // expected-note{{also accessed here}} use(self->ivar->weakIvar); // expected-warning{{weak instance variable 'weakIvar' is accessed multiple times}} use(self->ivar->weakIvar); // expected-note{{also accessed here}} } - (void)distinctFromOther:(Test *)other { use(self.strongProp.weakProp); // no-warning use(other.strongProp.weakProp); // no-warning use(self->ivar.weakProp); // no-warning use(other->ivar.weakProp); // no-warning use(self.strongProp->weakIvar); // no-warning use(other.strongProp->weakIvar); // no-warning } @end @interface Base1 @end @interface Sub1 : Base1 @end @interface Sub1(cat) -(id)prop; @end void test1(Sub1 *s) { use([s prop]); use([s prop]); } @interface Base1(cat) @property (weak) id prop; @end void test2(Sub1 *s) { // This does not warn because the "prop" in "Base1(cat)" was introduced // after the method declaration and we don't find it as overridden. // Always looking for overridden methods after the method declaration is expensive // and it's not clear it is worth it currently. use([s prop]); use([s prop]); } class Wrapper { Test *a; public: void fields() { 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}} use(a.weakProp); // expected-note{{also accessed here}} } void distinctFromOther(Test *b, const Wrapper &w) { use(a.weakProp); // no-warning use(b.weakProp); // no-warning use(w.a.weakProp); // no-warning } static void doubleLevelAccessField(const Wrapper &x, const Wrapper &y) { use(x.a.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(y.a.weakProp); // expected-note{{also accessed here}} } }; // ----------------------- // False positives // ----------------------- // Most of these would require flow-sensitive analysis to silence correctly. void assignNil(Test *a) { if (condition()) a.weakProp = nil; // expected-note{{also accessed here}} use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} } void branch(Test *a) { if (condition()) use(a.weakProp); // expected-warning{{weak property 'weakProp' is accessed multiple times}} else use(a.weakProp); // expected-note{{also accessed here}} } void doubleLevelAccess(Test *a, Test *b) { use(a.strongProp.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(b.strongProp.weakProp); // expected-note{{also accessed here}} use(a.weakProp.weakProp); // no-warning } void doubleLevelAccessIvar(Test *a, Test *b) { use(a->ivar.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(b->ivar.weakProp); // expected-note{{also accessed here}} use(a.strongProp.weakProp); // no-warning } // rdar://13942025 @interface X @end @implementation X - (int) warningAboutWeakVariableInsideTypeof { __typeof__(self) __weak weakSelf = self; ^(){ __typeof__(weakSelf) blockSelf = weakSelf; use(blockSelf); }(); return sizeof(weakSelf); } @end // rdar://19053620 @interface NSNull + (NSNull *)null; @end @interface INTF @end @implementation INTF - (void) Meth : (id) data { data = data ?: NSNull.null; } @end // This used to crash in WeakObjectProfileTy::getBaseInfo when getBase() was // called on an ObjCPropertyRefExpr object whose receiver was an interface. @class NSString; @interface NSBundle +(NSBundle *)foo; @property (class, strong) NSBundle *foo2; @property (strong) NSString *prop; @property(weak) NSString *weakProp; @end @interface NSBundle2 : NSBundle @end void foo() { NSString * t = NSBundle.foo.prop; use(NSBundle.foo.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(NSBundle2.foo.weakProp); // expected-note{{also accessed here}} NSString * t2 = NSBundle.foo2.prop; use(NSBundle.foo2.weakProp); // expected-warning{{weak property 'weakProp' may be accessed multiple times}} use(NSBundle2.foo2.weakProp); // expected-note{{also accessed here}} decltype([NSBundle2.foo2 weakProp]) t3; decltype(NSBundle2.foo2.weakProp) t4; __typeof__(NSBundle2.foo2.weakProp) t5; } // This used to crash in the constructor of WeakObjectProfileTy when a // DeclRefExpr was passed that didn't reference a VarDecl. typedef INTF * INTFPtrTy; enum E { e1 }; void foo1() { INTFPtrTy tmp = (INTFPtrTy)e1; #if __has_feature(objc_arc) // expected-error@-2{{cast of 'E' to 'INTFPtrTy' (aka 'INTF *') is disallowed with ARC}} #endif } @class NSString; static NSString* const kGlobal = @""; @interface NSDictionary - (id)objectForKeyedSubscript:(id)key; @end @interface WeakProp @property (weak) NSDictionary *nd; @end @implementation WeakProp -(void)m { (void)self.nd[@""]; // no warning } @end