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