1*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -DRUN_IVAR_INVALIDATION -verify %s 2*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.MissingInvalidationMethod -DRUN_MISSING_INVALIDATION_METHOD -verify %s 3*67e74705SXin Liextern void __assert_fail (__const char *__assertion, __const char *__file, 4*67e74705SXin Li unsigned int __line, __const char *__function) 5*67e74705SXin Li __attribute__ ((__noreturn__)); 6*67e74705SXin Li 7*67e74705SXin Li#define assert(expr) \ 8*67e74705SXin Li ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) 9*67e74705SXin Li 10*67e74705SXin Li@protocol NSObject 11*67e74705SXin Li@end 12*67e74705SXin Li@interface NSObject <NSObject> {} 13*67e74705SXin Li+(id)alloc; 14*67e74705SXin Li+(id)new; 15*67e74705SXin Li-(id)init; 16*67e74705SXin Li-(id)autorelease; 17*67e74705SXin Li-(id)copy; 18*67e74705SXin Li- (Class)class; 19*67e74705SXin Li-(id)retain; 20*67e74705SXin Li-(id)description; 21*67e74705SXin Li@end 22*67e74705SXin Li@class NSString; 23*67e74705SXin Li 24*67e74705SXin Liextern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); 25*67e74705SXin Li 26*67e74705SXin Li@protocol Invalidation1 <NSObject> 27*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 28*67e74705SXin Li@end 29*67e74705SXin Li 30*67e74705SXin Li@protocol Invalidation2 <NSObject> 31*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 32*67e74705SXin Li@end 33*67e74705SXin Li 34*67e74705SXin Li@protocol Invalidation3 <NSObject> 35*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 36*67e74705SXin Li- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator"))); 37*67e74705SXin Li@end 38*67e74705SXin Li 39*67e74705SXin Li@protocol Invalidation3; 40*67e74705SXin Li@protocol Invalidation2; 41*67e74705SXin Li 42*67e74705SXin Li@interface Invalidation2Class <Invalidation2> 43*67e74705SXin Li@end 44*67e74705SXin Li 45*67e74705SXin Li@interface Invalidation1Class <Invalidation1> 46*67e74705SXin Li@end 47*67e74705SXin Li 48*67e74705SXin Li@interface ClassWithInvalidationMethodInCategory <NSObject> 49*67e74705SXin Li@end 50*67e74705SXin Li 51*67e74705SXin Li@interface ClassWithInvalidationMethodInCategory () 52*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 53*67e74705SXin Li@end 54*67e74705SXin Li 55*67e74705SXin Li@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> { 56*67e74705SXin Li SomeInvalidationImplementingObject *ObjA; // invalidation in the parent 57*67e74705SXin Li} 58*67e74705SXin Li@end 59*67e74705SXin Li 60*67e74705SXin Li@implementation SomeInvalidationImplementingObject 61*67e74705SXin Li- (void)invalidate{ 62*67e74705SXin Li ObjA = 0; 63*67e74705SXin Li} 64*67e74705SXin Li- (void)invalidate2 { 65*67e74705SXin Li [self invalidate]; 66*67e74705SXin Li} 67*67e74705SXin Li@end 68*67e74705SXin Li 69*67e74705SXin Li@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject { 70*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; // regular ivar 71*67e74705SXin Li SomeInvalidationImplementingObject *Ivar2; // regular ivar, sending invalidate message 72*67e74705SXin Li SomeInvalidationImplementingObject *_Ivar3; // no property, call -description 73*67e74705SXin Li SomeInvalidationImplementingObject *_Ivar4; // no property, provide as argument to NSLog() 74*67e74705SXin Li 75*67e74705SXin Li SomeInvalidationImplementingObject *_Prop1; // partially implemented property, set to 0 with dot syntax 76*67e74705SXin Li SomeInvalidationImplementingObject *_Prop2; // fully implemented prop, set to 0 with dot syntax 77*67e74705SXin Li SomeInvalidationImplementingObject *_propIvar; // property with custom named ivar, set to 0 via setter 78*67e74705SXin Li Invalidation1Class *MultipleProtocols; // regular ivar belonging to a different class 79*67e74705SXin Li Invalidation2Class *MultInheritance; // regular ivar belonging to a different class 80*67e74705SXin Li SomeInvalidationImplementingObject *_Prop3; // property, invalidate via sending a message to a getter method 81*67e74705SXin Li SomeInvalidationImplementingObject *_Prop4; // property with @synthesize, invalidate via property 82*67e74705SXin Li SomeInvalidationImplementingObject *_Prop5; // property with @synthesize, invalidate via getter method 83*67e74705SXin Li SomeInvalidationImplementingObject *_Prop8; 84*67e74705SXin Li 85*67e74705SXin Li // Ivars invalidated by the partial invalidator. 86*67e74705SXin Li SomeInvalidationImplementingObject *Ivar9; 87*67e74705SXin Li SomeInvalidationImplementingObject *_Prop10; 88*67e74705SXin Li SomeInvalidationImplementingObject *Ivar11; 89*67e74705SXin Li 90*67e74705SXin Li // No warnings on these as they are not invalidatable. 91*67e74705SXin Li NSObject *NIvar1; 92*67e74705SXin Li NSObject *NObj2; 93*67e74705SXin Li NSObject *_NProp1; 94*67e74705SXin Li NSObject *_NpropIvar; 95*67e74705SXin Li} 96*67e74705SXin Li 97*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop0; 98*67e74705SXin Li@property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1; 99*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop2; 100*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop3; 101*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *Prop5; 102*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *Prop4; 103*67e74705SXin Li 104*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop 105*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop 106*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *SynthIvarProp; 107*67e74705SXin Li 108*67e74705SXin Li@property (assign) NSObject* NProp0; 109*67e74705SXin Li@property (nonatomic, assign) NSObject* NProp1; 110*67e74705SXin Li@property (assign) NSObject* NProp2; 111*67e74705SXin Li 112*67e74705SXin Li-(void)setProp1: (SomeInvalidationImplementingObject*) InO; 113*67e74705SXin Li-(void)setNProp1: (NSObject*) InO; 114*67e74705SXin Li 115*67e74705SXin Li-(void)invalidate; 116*67e74705SXin Li 117*67e74705SXin Li// Partial invalidators invalidate only some ivars. They are guaranteed to be 118*67e74705SXin Li// called before the invalidation methods. 119*67e74705SXin Li-(void)partialInvalidator1 __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 120*67e74705SXin Li-(void)partialInvalidator2 __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 121*67e74705SXin Li@end 122*67e74705SXin Li 123*67e74705SXin Li@interface SomeSubclassInvalidatableObject() 124*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop8; 125*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop10; 126*67e74705SXin Li@end 127*67e74705SXin Li 128*67e74705SXin Li@implementation SomeSubclassInvalidatableObject{ 129*67e74705SXin Li @private 130*67e74705SXin Li SomeInvalidationImplementingObject *Ivar5; 131*67e74705SXin Li ClassWithInvalidationMethodInCategory *Ivar13; 132*67e74705SXin Li} 133*67e74705SXin Li 134*67e74705SXin Li@synthesize Prop7 = _propIvar; 135*67e74705SXin Li@synthesize Prop3 = _Prop3; 136*67e74705SXin Li@synthesize Prop5 = _Prop5; 137*67e74705SXin Li@synthesize Prop4 = _Prop4; 138*67e74705SXin Li@synthesize Prop8 = _Prop8; 139*67e74705SXin Li@synthesize Prop10 = _Prop10; 140*67e74705SXin Li 141*67e74705SXin Li 142*67e74705SXin Li- (void) setProp1: (SomeInvalidationImplementingObject*) InObj { 143*67e74705SXin Li _Prop1 = InObj; 144*67e74705SXin Li} 145*67e74705SXin Li 146*67e74705SXin Li- (void) setProp2: (SomeInvalidationImplementingObject*) InObj { 147*67e74705SXin Li _Prop2 = InObj; 148*67e74705SXin Li} 149*67e74705SXin Li- (SomeInvalidationImplementingObject*) Prop2 { 150*67e74705SXin Li return _Prop2; 151*67e74705SXin Li} 152*67e74705SXin Li 153*67e74705SXin Li@synthesize NProp2 = _NpropIvar; 154*67e74705SXin Li 155*67e74705SXin Li- (void) setNProp1: (NSObject*) InObj { 156*67e74705SXin Li _NProp1 = InObj; 157*67e74705SXin Li} 158*67e74705SXin Li 159*67e74705SXin Li- (void) invalidate { 160*67e74705SXin Li [Ivar2 invalidate]; 161*67e74705SXin Li self.Prop0 = 0; 162*67e74705SXin Li self.Prop1 = 0; 163*67e74705SXin Li [self setProp2:0]; 164*67e74705SXin Li [self setProp3:0]; 165*67e74705SXin Li [[self Prop5] invalidate2]; 166*67e74705SXin Li [self.Prop4 invalidate]; 167*67e74705SXin Li [self.Prop8 invalidate]; 168*67e74705SXin Li self.Prop6 = 0; 169*67e74705SXin Li [[self Prop7] invalidate]; 170*67e74705SXin Li 171*67e74705SXin Li [_Ivar3 description]; 172*67e74705SXin Li NSLog(@"%@", _Ivar4); 173*67e74705SXin Li [super invalidate]; 174*67e74705SXin Li} 175*67e74705SXin Li#if RUN_IVAR_INVALIDATION 176*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated}} 177*67e74705SXin Li// expected-warning@-3 {{Instance variable MultipleProtocols needs to be invalidated}} 178*67e74705SXin Li// expected-warning@-4 {{Instance variable MultInheritance needs to be invalidated}} 179*67e74705SXin Li// expected-warning@-5 {{Property SynthIvarProp needs to be invalidated or set to nil}} 180*67e74705SXin Li// expected-warning@-6 {{Instance variable _Ivar3 needs to be invalidated}} 181*67e74705SXin Li// expected-warning@-7 {{Instance variable _Ivar4 needs to be invalidated}} 182*67e74705SXin Li// expected-warning@-8 {{Instance variable Ivar5 needs to be invalidated or set to nil}} 183*67e74705SXin Li// expected-warning@-9 {{Instance variable Ivar13 needs to be invalidated or set to nil}} 184*67e74705SXin Li#endif 185*67e74705SXin Li 186*67e74705SXin Li-(void)partialInvalidator1 { 187*67e74705SXin Li [Ivar9 invalidate]; 188*67e74705SXin Li [_Prop10 invalidate]; 189*67e74705SXin Li} 190*67e74705SXin Li 191*67e74705SXin Li-(void)partialInvalidator2 { 192*67e74705SXin Li [Ivar11 invalidate]; 193*67e74705SXin Li} 194*67e74705SXin Li 195*67e74705SXin Li@end 196*67e74705SXin Li 197*67e74705SXin Li// Example, where the same property is inherited through 198*67e74705SXin Li// the parent and directly through a protocol. If a property backing ivar is 199*67e74705SXin Li// synthesized in the parent, let the parent invalidate it. 200*67e74705SXin Li 201*67e74705SXin Li@protocol IDEBuildable <NSObject> 202*67e74705SXin Li@property (readonly, strong) id <Invalidation2> ObjB; 203*67e74705SXin Li@end 204*67e74705SXin Li 205*67e74705SXin Li@interface Parent : NSObject <IDEBuildable, Invalidation2> { 206*67e74705SXin Li Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent. 207*67e74705SXin Li} 208*67e74705SXin Li@end 209*67e74705SXin Li 210*67e74705SXin Li@interface Child: Parent <Invalidation2, IDEBuildable> 211*67e74705SXin Li@end 212*67e74705SXin Li 213*67e74705SXin Li@implementation Parent{ 214*67e74705SXin Li @private 215*67e74705SXin Li Invalidation2Class *Ivar10; 216*67e74705SXin Li Invalidation2Class *Ivar11; 217*67e74705SXin Li Invalidation2Class *Ivar12; 218*67e74705SXin Li} 219*67e74705SXin Li 220*67e74705SXin Li@synthesize ObjB = _ObjB; 221*67e74705SXin Li- (void)invalidate{ 222*67e74705SXin Li _ObjB = ((void*)0); 223*67e74705SXin Li 224*67e74705SXin Li assert(Ivar10 == 0); 225*67e74705SXin Li 226*67e74705SXin Li if (__builtin_expect(!(Ivar11 == ((void*)0)), 0)) 227*67e74705SXin Li assert(0); 228*67e74705SXin Li 229*67e74705SXin Li assert(0 == Ivar12); 230*67e74705SXin Li 231*67e74705SXin Li} 232*67e74705SXin Li@end 233*67e74705SXin Li 234*67e74705SXin Li@implementation Child 235*67e74705SXin Li- (void)invalidate{ 236*67e74705SXin Li // no-warning 237*67e74705SXin Li} 238*67e74705SXin Li@end 239*67e74705SXin Li 240*67e74705SXin Li@protocol Invalidation <NSObject> 241*67e74705SXin Li- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 242*67e74705SXin Li@end 243*67e74705SXin Li 244*67e74705SXin Li@interface Foo : NSObject <Invalidation> 245*67e74705SXin Li@end 246*67e74705SXin Li 247*67e74705SXin Li@class FooBar; 248*67e74705SXin Li@protocol FooBar_Protocol <NSObject> 249*67e74705SXin Li@end 250*67e74705SXin Li 251*67e74705SXin Li@interface MissingInvalidationMethod : Foo <FooBar_Protocol> 252*67e74705SXin Li@property (assign) MissingInvalidationMethod *foobar15_warn; 253*67e74705SXin Li#if RUN_IVAR_INVALIDATION 254*67e74705SXin Li// expected-warning@-2 {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}} 255*67e74705SXin Li#endif 256*67e74705SXin Li@end 257*67e74705SXin Li@implementation MissingInvalidationMethod 258*67e74705SXin Li@end 259*67e74705SXin Li 260*67e74705SXin Li@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> { 261*67e74705SXin Li Foo *Ivar1; 262*67e74705SXin Li#if RUN_IVAR_INVALIDATION 263*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}} 264*67e74705SXin Li#endif 265*67e74705SXin Li} 266*67e74705SXin Li@end 267*67e74705SXin Li@implementation MissingInvalidationMethod2 268*67e74705SXin Li@end 269*67e74705SXin Li 270*67e74705SXin Li@interface MissingInvalidationMethodDecl : NSObject { 271*67e74705SXin Li Foo *Ivar1; 272*67e74705SXin Li#if RUN_MISSING_INVALIDATION_METHOD 273*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}} 274*67e74705SXin Li#endif 275*67e74705SXin Li} 276*67e74705SXin Li@end 277*67e74705SXin Li@implementation MissingInvalidationMethodDecl 278*67e74705SXin Li@end 279*67e74705SXin Li 280*67e74705SXin Li@interface MissingInvalidationMethodDecl2 : NSObject { 281*67e74705SXin Li@private 282*67e74705SXin Li Foo *_foo1; 283*67e74705SXin Li#if RUN_MISSING_INVALIDATION_METHOD 284*67e74705SXin Li// expected-warning@-2 {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}} 285*67e74705SXin Li#endif 286*67e74705SXin Li} 287*67e74705SXin Li@property (strong) Foo *bar1; 288*67e74705SXin Li@end 289*67e74705SXin Li@implementation MissingInvalidationMethodDecl2 290*67e74705SXin Li@end 291*67e74705SXin Li 292*67e74705SXin Li@interface InvalidatedInPartial : SomeInvalidationImplementingObject { 293*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; 294*67e74705SXin Li SomeInvalidationImplementingObject *Ivar2; 295*67e74705SXin Li} 296*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 297*67e74705SXin Li@end 298*67e74705SXin Li@implementation InvalidatedInPartial 299*67e74705SXin Li-(void)partialInvalidator { 300*67e74705SXin Li [Ivar1 invalidate]; 301*67e74705SXin Li Ivar2 = 0; 302*67e74705SXin Li} 303*67e74705SXin Li@end 304*67e74705SXin Li 305*67e74705SXin Li@interface NotInvalidatedInPartial : SomeInvalidationImplementingObject { 306*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; 307*67e74705SXin Li} 308*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 309*67e74705SXin Li-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 310*67e74705SXin Li@end 311*67e74705SXin Li@implementation NotInvalidatedInPartial 312*67e74705SXin Li-(void)partialInvalidator { 313*67e74705SXin Li} 314*67e74705SXin Li-(void)partialInvalidatorCallsPartial { 315*67e74705SXin Li [self partialInvalidator]; 316*67e74705SXin Li} 317*67e74705SXin Li 318*67e74705SXin Li-(void)invalidate { 319*67e74705SXin Li} 320*67e74705SXin Li#if RUN_IVAR_INVALIDATION 321*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated or set to nil}} 322*67e74705SXin Li#endif 323*67e74705SXin Li@end 324*67e74705SXin Li 325*67e74705SXin Li@interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject { 326*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; 327*67e74705SXin Li SomeInvalidationImplementingObject *Ivar2; 328*67e74705SXin Li#if RUN_IVAR_INVALIDATION 329*67e74705SXin Li // expected-warning@-2 {{Instance variable Ivar2 needs to be invalidated or set to nil}} 330*67e74705SXin Li#endif 331*67e74705SXin Li} 332*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 333*67e74705SXin Li-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 334*67e74705SXin Li@end 335*67e74705SXin Li@implementation SomeNotInvalidatedInPartial { 336*67e74705SXin Li SomeInvalidationImplementingObject *Ivar3; 337*67e74705SXin Li#if RUN_IVAR_INVALIDATION 338*67e74705SXin Li // expected-warning@-2 {{Instance variable Ivar3 needs to be invalidated or set to nil}} 339*67e74705SXin Li#endif 340*67e74705SXin Li} 341*67e74705SXin Li-(void)partialInvalidator { 342*67e74705SXin Li Ivar1 = 0; 343*67e74705SXin Li} 344*67e74705SXin Li-(void)partialInvalidatorCallsPartial { 345*67e74705SXin Li [self partialInvalidator]; 346*67e74705SXin Li} 347*67e74705SXin Li@end 348*67e74705SXin Li 349*67e74705SXin Li@interface OnlyPartialDeclsBase : NSObject 350*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 351*67e74705SXin Li@end 352*67e74705SXin Li@implementation OnlyPartialDeclsBase 353*67e74705SXin Li-(void)partialInvalidator {} 354*67e74705SXin Li@end 355*67e74705SXin Li 356*67e74705SXin Li@interface OnlyPartialDecls : OnlyPartialDeclsBase { 357*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; 358*67e74705SXin Li#if RUN_IVAR_INVALIDATION 359*67e74705SXin Li // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}} 360*67e74705SXin Li#endif 361*67e74705SXin Li} 362*67e74705SXin Li@end 363*67e74705SXin Li@implementation OnlyPartialDecls 364*67e74705SXin Li@end 365*67e74705SXin Li 366*67e74705SXin Li// False negative. 367*67e74705SXin Li@interface PartialCallsFull : SomeInvalidationImplementingObject { 368*67e74705SXin Li SomeInvalidationImplementingObject *Ivar1; 369*67e74705SXin Li} 370*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial"))); 371*67e74705SXin Li@end 372*67e74705SXin Li@implementation PartialCallsFull 373*67e74705SXin Li-(void)partialInvalidator { 374*67e74705SXin Li [self invalidate]; 375*67e74705SXin Li} // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar. 376*67e74705SXin Li@end 377*67e74705SXin Li 378