Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 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; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 13 | -(id)description; |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 14 | @end |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 15 | @class NSString; |
| 16 | |
| 17 | extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2))); |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 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"))); |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 29 | - (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator"))); |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 30 | @end |
| 31 | |
| 32 | @interface Invalidation2Class <Invalidation2> |
| 33 | @end |
| 34 | |
| 35 | @interface Invalidation1Class <Invalidation1> |
| 36 | @end |
| 37 | |
| 38 | @interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> { |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 39 | SomeInvalidationImplementingObject *ObjA; // invalidation in the parent |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 40 | } |
| 41 | @end |
| 42 | |
| 43 | @implementation SomeInvalidationImplementingObject |
| 44 | - (void)invalidate{ |
| 45 | ObjA = 0; |
| 46 | } |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 47 | - (void)invalidate2 { |
| 48 | [self invalidate]; |
| 49 | } |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 50 | @end |
| 51 | |
| 52 | @interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject { |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 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 |
Anna Zaks | c3c26b7 | 2012-10-18 19:17:57 +0000 | [diff] [blame] | 66 | SomeInvalidationImplementingObject *_Prop8; |
Anna Zaks | b087bbf | 2012-09-27 19:45:08 +0000 | [diff] [blame] | 67 | |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 68 | // No warnings on these as they are not invalidatable. |
| 69 | NSObject *NIvar1; |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 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; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 79 | @property (assign) SomeInvalidationImplementingObject *Prop5; |
| 80 | @property (assign) SomeInvalidationImplementingObject *Prop4; |
Anna Zaks | 377945c | 2012-09-27 21:57:14 +0000 | [diff] [blame] | 81 | |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 82 | @property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop |
| 83 | @property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop |
| 84 | @property (assign) SomeInvalidationImplementingObject *SynthIvarProp; |
Anna Zaks | 377945c | 2012-09-27 21:57:14 +0000 | [diff] [blame] | 85 | |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 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 | |
Anna Zaks | e0c50fa | 2012-10-16 19:36:37 +0000 | [diff] [blame] | 97 | @interface SomeSubclassInvalidatableObject() |
| 98 | @property (assign) SomeInvalidationImplementingObject* Prop8; |
| 99 | @end |
| 100 | |
| 101 | @implementation SomeSubclassInvalidatableObject{ |
| 102 | @private |
| 103 | SomeInvalidationImplementingObject *Ivar5; |
| 104 | } |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 105 | |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 106 | @synthesize Prop7 = _propIvar; |
| 107 | @synthesize Prop3 = _Prop3; |
| 108 | @synthesize Prop5 = _Prop5; |
| 109 | @synthesize Prop4 = _Prop4; |
Anna Zaks | c3c26b7 | 2012-10-18 19:17:57 +0000 | [diff] [blame] | 110 | @synthesize Prop8 = _Prop8; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 111 | |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 112 | |
| 113 | - (void) setProp1: (SomeInvalidationImplementingObject*) InObj { |
| 114 | _Prop1 = InObj; |
| 115 | } |
| 116 | |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 117 | - (void) setProp2: (SomeInvalidationImplementingObject*) InObj { |
| 118 | _Prop2 = InObj; |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 119 | } |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 120 | - (SomeInvalidationImplementingObject*) Prop2 { |
| 121 | return _Prop2; |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | @synthesize NProp2 = _NpropIvar; |
| 125 | |
| 126 | - (void) setNProp1: (NSObject*) InObj { |
| 127 | _NProp1 = InObj; |
| 128 | } |
| 129 | |
| 130 | - (void) invalidate { |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 131 | [Ivar2 invalidate]; |
Anna Zaks | 377945c | 2012-09-27 21:57:14 +0000 | [diff] [blame] | 132 | self.Prop0 = 0; |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 133 | self.Prop1 = 0; |
| 134 | [self setProp2:0]; |
| 135 | [self setProp3:0]; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 136 | [[self Prop5] invalidate2]; |
| 137 | [self.Prop4 invalidate]; |
Anna Zaks | c3c26b7 | 2012-10-18 19:17:57 +0000 | [diff] [blame] | 138 | [self.Prop8 invalidate]; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 139 | self.Prop6 = 0; |
| 140 | [[self Prop7] invalidate]; |
| 141 | |
| 142 | [_Ivar3 description]; |
| 143 | NSLog(@"%@", _Ivar4); |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 144 | [super invalidate]; |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 145 | } |
| 146 | // expected-warning@-1 {{Instance variable Ivar1 needs to be invalidated}} |
Anna Zaks | b087bbf | 2012-09-27 19:45:08 +0000 | [diff] [blame] | 147 | // expected-warning@-2 {{Instance variable MultipleProtocols needs to be invalidated}} |
| 148 | // expected-warning@-3 {{Instance variable MultInheritance needs to be invalidated}} |
Anna Zaks | c3c26b7 | 2012-10-18 19:17:57 +0000 | [diff] [blame] | 149 | // expected-warning@-4 {{Property SynthIvarProp needs to be invalidated or set to nil}} |
Anna Zaks | 31f69cc | 2012-09-29 00:20:38 +0000 | [diff] [blame] | 150 | // expected-warning@-5 {{Instance variable _Ivar3 needs to be invalidated}} |
| 151 | // expected-warning@-6 {{Instance variable _Ivar4 needs to be invalidated}} |
Anna Zaks | e0c50fa | 2012-10-16 19:36:37 +0000 | [diff] [blame] | 152 | // expected-warning@-7 {{Instance variable Ivar5 needs to be invalidated or set to nil}} |
Anna Zaks | 5bf5c2e | 2012-09-26 18:55:16 +0000 | [diff] [blame] | 153 | @end |
Anna Zaks | 5879fb3 | 2013-01-07 19:12:56 +0000 | [diff] [blame^] | 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 |