objc_invalidation.m revision ae81e172e93b75594c7053f3226a16b9d8daa6fd
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -fobjc-default-synthesize-properties -verify %s 2extern void __assert_fail (__const char *__assertion, __const char *__file, 3 unsigned int __line, __const char *__function) 4 __attribute__ ((__noreturn__)); 5 6#define assert(expr) \ 7 ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__)) 8 9@protocol NSObject 10@end 11@interface NSObject <NSObject> {} 12+(id)alloc; 13+(id)new; 14-(id)init; 15-(id)autorelease; 16-(id)copy; 17- (Class)class; 18-(id)retain; 19-(id)description; 20@end 21@class NSString; 22 23extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); 24 25@protocol Invalidation1 <NSObject> 26- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 27@end 28 29@protocol Invalidation2 <NSObject> 30- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 31@end 32 33@protocol Invalidation3 <NSObject> 34- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 35- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator"))); 36@end 37 38@interface Invalidation2Class <Invalidation2> 39@end 40 41@interface Invalidation1Class <Invalidation1> 42@end 43 44@interface ClassWithInvalidationMethodInCategory <NSObject> 45@end 46 47@interface ClassWithInvalidationMethodInCategory () 48- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 49@end 50 51@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> { 52 SomeInvalidationImplementingObject *ObjA; // invalidation in the parent 53} 54@end 55 56@implementation SomeInvalidationImplementingObject 57- (void)invalidate{ 58 ObjA = 0; 59} 60- (void)invalidate2 { 61 [self invalidate]; 62} 63@end 64 65@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject { 66 SomeInvalidationImplementingObject *Ivar1; // regular ivar 67 SomeInvalidationImplementingObject *Ivar2; // regular ivar, sending invalidate message 68 SomeInvalidationImplementingObject *_Ivar3; // no property, call -description 69 SomeInvalidationImplementingObject *_Ivar4; // no property, provide as argument to NSLog() 70 71 SomeInvalidationImplementingObject *_Prop1; // partially implemented property, set to 0 with dot syntax 72 SomeInvalidationImplementingObject *_Prop2; // fully implemented prop, set to 0 with dot syntax 73 SomeInvalidationImplementingObject *_propIvar; // property with custom named ivar, set to 0 via setter 74 Invalidation1Class *MultipleProtocols; // regular ivar belonging to a different class 75 Invalidation2Class *MultInheritance; // regular ivar belonging to a different class 76 SomeInvalidationImplementingObject *_Prop3; // property, invalidate via sending a message to a getter method 77 SomeInvalidationImplementingObject *_Prop4; // property with @synthesize, invalidate via property 78 SomeInvalidationImplementingObject *_Prop5; // property with @synthesize, invalidate via getter method 79 SomeInvalidationImplementingObject *_Prop8; 80 81 // No warnings on these as they are not invalidatable. 82 NSObject *NIvar1; 83 NSObject *NObj2; 84 NSObject *_NProp1; 85 NSObject *_NpropIvar; 86} 87 88@property (assign) SomeInvalidationImplementingObject* Prop0; 89@property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1; 90@property (assign) SomeInvalidationImplementingObject* Prop2; 91@property (assign) SomeInvalidationImplementingObject* Prop3; 92@property (assign) SomeInvalidationImplementingObject *Prop5; 93@property (assign) SomeInvalidationImplementingObject *Prop4; 94 95@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop 96@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop 97@property (assign) SomeInvalidationImplementingObject *SynthIvarProp; 98 99@property (assign) NSObject* NProp0; 100@property (nonatomic, assign) NSObject* NProp1; 101@property (assign) NSObject* NProp2; 102 103-(void)setProp1: (SomeInvalidationImplementingObject*) InO; 104-(void)setNProp1: (NSObject*) InO; 105 106-(void)invalidate; 107 108@end 109 110@interface SomeSubclassInvalidatableObject() 111@property (assign) SomeInvalidationImplementingObject* Prop8; 112@end 113 114@implementation SomeSubclassInvalidatableObject{ 115 @private 116 SomeInvalidationImplementingObject *Ivar5; 117 ClassWithInvalidationMethodInCategory *Ivar13; 118} 119 120@synthesize Prop7 = _propIvar; 121@synthesize Prop3 = _Prop3; 122@synthesize Prop5 = _Prop5; 123@synthesize Prop4 = _Prop4; 124@synthesize Prop8 = _Prop8; 125 126 127- (void) setProp1: (SomeInvalidationImplementingObject*) InObj { 128 _Prop1 = InObj; 129} 130 131- (void) setProp2: (SomeInvalidationImplementingObject*) InObj { 132 _Prop2 = InObj; 133} 134- (SomeInvalidationImplementingObject*) Prop2 { 135 return _Prop2; 136} 137 138@synthesize NProp2 = _NpropIvar; 139 140- (void) setNProp1: (NSObject*) InObj { 141 _NProp1 = InObj; 142} 143 144- (void) invalidate { 145 [Ivar2 invalidate]; 146 self.Prop0 = 0; 147 self.Prop1 = 0; 148 [self setProp2:0]; 149 [self setProp3:0]; 150 [[self Prop5] invalidate2]; 151 [self.Prop4 invalidate]; 152 [self.Prop8 invalidate]; 153 self.Prop6 = 0; 154 [[self Prop7] invalidate]; 155 156 [_Ivar3 description]; 157 NSLog(@"%@", _Ivar4); 158 [super invalidate]; 159} 160// expected-warning@-1 {{Instance variable Ivar1 needs to be invalidated}} 161 // expected-warning@-2 {{Instance variable MultipleProtocols needs to be invalidated}} 162 // expected-warning@-3 {{Instance variable MultInheritance needs to be invalidated}} 163 // expected-warning@-4 {{Property SynthIvarProp needs to be invalidated or set to nil}} 164 // expected-warning@-5 {{Instance variable _Ivar3 needs to be invalidated}} 165 // expected-warning@-6 {{Instance variable _Ivar4 needs to be invalidated}} 166 // expected-warning@-7 {{Instance variable Ivar5 needs to be invalidated or set to nil}} 167// expected-warning@-8 {{Instance variable Ivar13 needs to be invalidated or set to nil}} 168@end 169 170// Example, where the same property is inherited through 171// the parent and directly through a protocol. If a property backing ivar is 172// synthesized in the parent, let the parent invalidate it. 173 174@protocol IDEBuildable <NSObject> 175@property (readonly, strong) id <Invalidation2> ObjB; 176@end 177 178@interface Parent : NSObject <IDEBuildable, Invalidation2> { 179 Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent. 180} 181@end 182 183@interface Child: Parent <Invalidation2, IDEBuildable> 184@end 185 186@implementation Parent{ 187 @private 188 Invalidation2Class *Ivar10; 189 Invalidation2Class *Ivar11; 190 Invalidation2Class *Ivar12; 191} 192 193@synthesize ObjB = _ObjB; 194- (void)invalidate{ 195 _ObjB = ((void*)0); 196 197 assert(Ivar10 == 0); 198 199 if (__builtin_expect(!(Ivar11 == ((void*)0)), 0)) 200 assert(0); 201 202 assert(0 == Ivar12); 203 204} 205@end 206 207@implementation Child 208- (void)invalidate{ 209 // no-warning 210} 211@end 212 213@protocol Invalidation <NSObject> 214- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator"))); 215@end 216 217@interface Foo : NSObject <Invalidation> 218@end 219 220@class FooBar; 221@protocol FooBar_Protocol <NSObject> 222@end 223 224@interface MissingInvalidationMethod : Foo <FooBar_Protocol> 225@property (assign) MissingInvalidationMethod *foobar15_warn; // expected-warning {{No invalidation method defined in the @implementation for MissingInvalidationMethod; Property foobar15_warn needs to be invalidated}} 226@end 227@implementation MissingInvalidationMethod 228@end 229 230@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> { 231 Foo *Ivar1;// expected-warning {{No invalidation method defined in the @implementation for MissingInvalidationMethod2; Instance variable Ivar1 needs to be invalidated}} 232} 233@end 234@implementation MissingInvalidationMethod2 235@end 236 237@interface MissingInvalidationMethodDecl : NSObject { 238 Foo *Ivar1;// expected-warning {{No invalidation method declared in the @interface for MissingInvalidationMethodDecl; Instance variable Ivar1 needs to be invalidated}} 239} 240@end 241@implementation MissingInvalidationMethodDecl 242@end 243 244@interface MissingInvalidationMethodDecl2 : NSObject { 245@private 246 Foo *_foo1; // expected-warning {{No invalidation method declared in the @interface for MissingInvalidationMethodDecl2; Instance variable _foo1 needs to be invalidated}} 247} 248@property (strong) Foo *bar1; 249@end 250@implementation MissingInvalidationMethodDecl2 251@end 252