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