|  | // 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}} | 
|  | } | 
|  |  | 
|  | // 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 = @""; |