blob: 6919feaccfc75bf6aae7a27f9472b491b63d5c4d [file] [log] [blame]
Anna Zaks722cd9e2013-02-08 23:55:47 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -DRUN_IVAR_INVALIDATION -fobjc-default-synthesize-properties -verify %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.MissingInvalidationMethod -DRUN_MISSING_INVALIDATION_METHOD -fobjc-default-synthesize-properties -verify %s
Anna Zaks65032552013-01-10 23:34:16 +00003extern void __assert_fail (__const char *__assertion, __const char *__file,
4 unsigned int __line, __const char *__function)
5 __attribute__ ((__noreturn__));
6
7#define assert(expr) \
8 ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
Anna Zaks5bf5c2e2012-09-26 18:55:16 +00009
10@protocol NSObject
11@end
12@interface NSObject <NSObject> {}
13+(id)alloc;
14+(id)new;
15-(id)init;
16-(id)autorelease;
17-(id)copy;
18- (Class)class;
19-(id)retain;
Anna Zaks31f69cc2012-09-29 00:20:38 +000020-(id)description;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000021@end
Anna Zaks31f69cc2012-09-29 00:20:38 +000022@class NSString;
23
24extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000025
26@protocol Invalidation1 <NSObject>
27- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
28@end
29
30@protocol Invalidation2 <NSObject>
31- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
32@end
33
34@protocol Invalidation3 <NSObject>
35- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
Anna Zaks31f69cc2012-09-29 00:20:38 +000036- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator")));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000037@end
38
Anna Zaksb8f66782013-01-11 03:52:40 +000039@protocol Invalidation3;
40@protocol Invalidation2;
41
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000042@interface Invalidation2Class <Invalidation2>
43@end
44
45@interface Invalidation1Class <Invalidation1>
46@end
47
Anna Zaksae81e172013-01-11 03:52:37 +000048@interface ClassWithInvalidationMethodInCategory <NSObject>
49@end
50
51@interface ClassWithInvalidationMethodInCategory ()
52- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
53@end
54
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000055@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> {
Anna Zaks31f69cc2012-09-29 00:20:38 +000056 SomeInvalidationImplementingObject *ObjA; // invalidation in the parent
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000057}
58@end
59
60@implementation SomeInvalidationImplementingObject
61- (void)invalidate{
62 ObjA = 0;
63}
Anna Zaks31f69cc2012-09-29 00:20:38 +000064- (void)invalidate2 {
65 [self invalidate];
66}
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000067@end
68
69@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject {
Anna Zaks31f69cc2012-09-29 00:20:38 +000070 SomeInvalidationImplementingObject *Ivar1; // regular ivar
71 SomeInvalidationImplementingObject *Ivar2; // regular ivar, sending invalidate message
72 SomeInvalidationImplementingObject *_Ivar3; // no property, call -description
73 SomeInvalidationImplementingObject *_Ivar4; // no property, provide as argument to NSLog()
74
75 SomeInvalidationImplementingObject *_Prop1; // partially implemented property, set to 0 with dot syntax
76 SomeInvalidationImplementingObject *_Prop2; // fully implemented prop, set to 0 with dot syntax
77 SomeInvalidationImplementingObject *_propIvar; // property with custom named ivar, set to 0 via setter
78 Invalidation1Class *MultipleProtocols; // regular ivar belonging to a different class
79 Invalidation2Class *MultInheritance; // regular ivar belonging to a different class
80 SomeInvalidationImplementingObject *_Prop3; // property, invalidate via sending a message to a getter method
81 SomeInvalidationImplementingObject *_Prop4; // property with @synthesize, invalidate via property
82 SomeInvalidationImplementingObject *_Prop5; // property with @synthesize, invalidate via getter method
Anna Zaksc3c26b72012-10-18 19:17:57 +000083 SomeInvalidationImplementingObject *_Prop8;
Anna Zaksb087bbf2012-09-27 19:45:08 +000084
Anna Zaks26db7db2013-02-08 23:55:43 +000085 // Ivars invalidated by the partial invalidator.
86 SomeInvalidationImplementingObject *Ivar9;
87 SomeInvalidationImplementingObject *_Prop10;
88 SomeInvalidationImplementingObject *Ivar11;
89
Anna Zaks31f69cc2012-09-29 00:20:38 +000090 // No warnings on these as they are not invalidatable.
91 NSObject *NIvar1;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000092 NSObject *NObj2;
93 NSObject *_NProp1;
94 NSObject *_NpropIvar;
95}
96
97@property (assign) SomeInvalidationImplementingObject* Prop0;
98@property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1;
99@property (assign) SomeInvalidationImplementingObject* Prop2;
100@property (assign) SomeInvalidationImplementingObject* Prop3;
Anna Zaks31f69cc2012-09-29 00:20:38 +0000101@property (assign) SomeInvalidationImplementingObject *Prop5;
102@property (assign) SomeInvalidationImplementingObject *Prop4;
Anna Zaks377945c2012-09-27 21:57:14 +0000103
Anna Zaks31f69cc2012-09-29 00:20:38 +0000104@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop
105@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop
106@property (assign) SomeInvalidationImplementingObject *SynthIvarProp;
Anna Zaks377945c2012-09-27 21:57:14 +0000107
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000108@property (assign) NSObject* NProp0;
109@property (nonatomic, assign) NSObject* NProp1;
110@property (assign) NSObject* NProp2;
111
112-(void)setProp1: (SomeInvalidationImplementingObject*) InO;
113-(void)setNProp1: (NSObject*) InO;
114
115-(void)invalidate;
116
Anna Zaks26db7db2013-02-08 23:55:43 +0000117// Partial invalidators invalidate only some ivars. They are guaranteed to be
118// called before the invalidation methods.
119-(void)partialInvalidator1 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
120-(void)partialInvalidator2 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000121@end
122
Anna Zakse0c50fa2012-10-16 19:36:37 +0000123@interface SomeSubclassInvalidatableObject()
124@property (assign) SomeInvalidationImplementingObject* Prop8;
Anna Zaks26db7db2013-02-08 23:55:43 +0000125@property (assign) SomeInvalidationImplementingObject* Prop10;
Anna Zakse0c50fa2012-10-16 19:36:37 +0000126@end
127
128@implementation SomeSubclassInvalidatableObject{
129 @private
130 SomeInvalidationImplementingObject *Ivar5;
Anna Zaksae81e172013-01-11 03:52:37 +0000131 ClassWithInvalidationMethodInCategory *Ivar13;
Anna Zakse0c50fa2012-10-16 19:36:37 +0000132}
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000133
Anna Zaks31f69cc2012-09-29 00:20:38 +0000134@synthesize Prop7 = _propIvar;
135@synthesize Prop3 = _Prop3;
136@synthesize Prop5 = _Prop5;
137@synthesize Prop4 = _Prop4;
Anna Zaksc3c26b72012-10-18 19:17:57 +0000138@synthesize Prop8 = _Prop8;
Anna Zaks26db7db2013-02-08 23:55:43 +0000139@synthesize Prop10 = _Prop10;
Anna Zaks31f69cc2012-09-29 00:20:38 +0000140
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000141
142- (void) setProp1: (SomeInvalidationImplementingObject*) InObj {
143 _Prop1 = InObj;
144}
145
Anna Zaks31f69cc2012-09-29 00:20:38 +0000146- (void) setProp2: (SomeInvalidationImplementingObject*) InObj {
147 _Prop2 = InObj;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000148}
Anna Zaks31f69cc2012-09-29 00:20:38 +0000149- (SomeInvalidationImplementingObject*) Prop2 {
150 return _Prop2;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000151}
152
153@synthesize NProp2 = _NpropIvar;
154
155- (void) setNProp1: (NSObject*) InObj {
156 _NProp1 = InObj;
157}
158
159- (void) invalidate {
Anna Zaks31f69cc2012-09-29 00:20:38 +0000160 [Ivar2 invalidate];
Anna Zaks377945c2012-09-27 21:57:14 +0000161 self.Prop0 = 0;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000162 self.Prop1 = 0;
163 [self setProp2:0];
164 [self setProp3:0];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000165 [[self Prop5] invalidate2];
166 [self.Prop4 invalidate];
Anna Zaksc3c26b72012-10-18 19:17:57 +0000167 [self.Prop8 invalidate];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000168 self.Prop6 = 0;
169 [[self Prop7] invalidate];
170
171 [_Ivar3 description];
172 NSLog(@"%@", _Ivar4);
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000173 [super invalidate];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000174}
Anna Zaks722cd9e2013-02-08 23:55:47 +0000175#if RUN_IVAR_INVALIDATION
176// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated}}
177// expected-warning@-3 {{Instance variable MultipleProtocols needs to be invalidated}}
178// expected-warning@-4 {{Instance variable MultInheritance needs to be invalidated}}
179// expected-warning@-5 {{Property SynthIvarProp needs to be invalidated or set to nil}}
180// expected-warning@-6 {{Instance variable _Ivar3 needs to be invalidated}}
181// expected-warning@-7 {{Instance variable _Ivar4 needs to be invalidated}}
182// expected-warning@-8 {{Instance variable Ivar5 needs to be invalidated or set to nil}}
183// expected-warning@-9 {{Instance variable Ivar13 needs to be invalidated or set to nil}}
184#endif
Anna Zaks26db7db2013-02-08 23:55:43 +0000185
186-(void)partialInvalidator1 {
187 [Ivar9 invalidate];
188 [_Prop10 invalidate];
189}
190
191-(void)partialInvalidator2 {
192 [Ivar11 invalidate];
193}
194
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000195@end
Anna Zaks5879fb32013-01-07 19:12:56 +0000196
197// Example, where the same property is inherited through
198// the parent and directly through a protocol. If a property backing ivar is
199// synthesized in the parent, let the parent invalidate it.
200
201@protocol IDEBuildable <NSObject>
202@property (readonly, strong) id <Invalidation2> ObjB;
203@end
204
205@interface Parent : NSObject <IDEBuildable, Invalidation2> {
206 Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent.
207}
208@end
209
210@interface Child: Parent <Invalidation2, IDEBuildable>
211@end
212
Anna Zaks65032552013-01-10 23:34:16 +0000213@implementation Parent{
214 @private
215 Invalidation2Class *Ivar10;
216 Invalidation2Class *Ivar11;
217 Invalidation2Class *Ivar12;
218}
219
Anna Zaks5879fb32013-01-07 19:12:56 +0000220@synthesize ObjB = _ObjB;
221- (void)invalidate{
222 _ObjB = ((void*)0);
Anna Zaks65032552013-01-10 23:34:16 +0000223
224 assert(Ivar10 == 0);
225
226 if (__builtin_expect(!(Ivar11 == ((void*)0)), 0))
227 assert(0);
228
229 assert(0 == Ivar12);
230
Anna Zaks5879fb32013-01-07 19:12:56 +0000231}
232@end
233
234@implementation Child
235- (void)invalidate{
236 // no-warning
237}
238@end
Anna Zaksb1fc6732013-01-10 20:59:51 +0000239
240@protocol Invalidation <NSObject>
241- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
242@end
243
244@interface Foo : NSObject <Invalidation>
245@end
246
247@class FooBar;
248@protocol FooBar_Protocol <NSObject>
249@end
250
251@interface MissingInvalidationMethod : Foo <FooBar_Protocol>
Anna Zaks722cd9e2013-02-08 23:55:47 +0000252@property (assign) MissingInvalidationMethod *foobar15_warn;
Anna Zaksd523df62013-02-09 01:09:27 +0000253#if RUN_IVAR_INVALIDATION
Anna Zaks722cd9e2013-02-08 23:55:47 +0000254// expected-warning@-2 {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}}
255#endif
Anna Zaksb1fc6732013-01-10 20:59:51 +0000256@end
257@implementation MissingInvalidationMethod
258@end
259
260@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> {
Anna Zaks722cd9e2013-02-08 23:55:47 +0000261 Foo *Ivar1;
Anna Zaksd523df62013-02-09 01:09:27 +0000262#if RUN_IVAR_INVALIDATION
Anna Zaks722cd9e2013-02-08 23:55:47 +0000263// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}}
264#endif
Anna Zaksb1fc6732013-01-10 20:59:51 +0000265}
266@end
267@implementation MissingInvalidationMethod2
268@end
269
270@interface MissingInvalidationMethodDecl : NSObject {
Anna Zaks722cd9e2013-02-08 23:55:47 +0000271 Foo *Ivar1;
272#if RUN_MISSING_INVALIDATION_METHOD
273// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}}
274#endif
Anna Zaksb1fc6732013-01-10 20:59:51 +0000275}
276@end
277@implementation MissingInvalidationMethodDecl
278@end
279
280@interface MissingInvalidationMethodDecl2 : NSObject {
281@private
Anna Zaks722cd9e2013-02-08 23:55:47 +0000282 Foo *_foo1;
283#if RUN_MISSING_INVALIDATION_METHOD
284// expected-warning@-2 {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}}
285#endif
Anna Zaksb1fc6732013-01-10 20:59:51 +0000286}
Anna Zaks664566c2013-01-10 22:44:16 +0000287@property (strong) Foo *bar1;
Anna Zaksb1fc6732013-01-10 20:59:51 +0000288@end
289@implementation MissingInvalidationMethodDecl2
290@end
Anna Zaks26db7db2013-02-08 23:55:43 +0000291
292@interface InvalidatedInPartial : SomeInvalidationImplementingObject {
293 SomeInvalidationImplementingObject *Ivar1;
294 SomeInvalidationImplementingObject *Ivar2;
295}
296-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
297@end
298@implementation InvalidatedInPartial
299-(void)partialInvalidator {
300 [Ivar1 invalidate];
301 Ivar2 = 0;
302}
303@end
304
305@interface NotInvalidatedInPartial : SomeInvalidationImplementingObject {
306 SomeInvalidationImplementingObject *Ivar1;
307}
308-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
309-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
310@end
311@implementation NotInvalidatedInPartial
312-(void)partialInvalidator {
313}
314-(void)partialInvalidatorCallsPartial {
315 [self partialInvalidator];
316}
317
318-(void)invalidate {
Anna Zaks722cd9e2013-02-08 23:55:47 +0000319}
320#if RUN_IVAR_INVALIDATION
321// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated or set to nil}}
322#endif
Anna Zaks26db7db2013-02-08 23:55:43 +0000323@end
324
Anna Zakscaadc412013-04-24 02:49:16 +0000325@interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject {
326 SomeInvalidationImplementingObject *Ivar1;
327 SomeInvalidationImplementingObject *Ivar2;
328#if RUN_IVAR_INVALIDATION
329 // expected-warning@-2 {{Instance variable Ivar2 needs to be invalidated or set to nil}}
330#endif
331}
332-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
333-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
334@end
335@implementation SomeNotInvalidatedInPartial {
336 SomeInvalidationImplementingObject *Ivar3;
337#if RUN_IVAR_INVALIDATION
338 // expected-warning@-2 {{Instance variable Ivar3 needs to be invalidated or set to nil}}
339#endif
340}
341-(void)partialInvalidator {
342 Ivar1 = 0;
343}
344-(void)partialInvalidatorCallsPartial {
345 [self partialInvalidator];
346}
347@end
348
349@interface OnlyPartialDeclsBase : NSObject
350-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
351@end
352@implementation OnlyPartialDeclsBase
353-(void)partialInvalidator {}
354@end
355
356@interface OnlyPartialDecls : OnlyPartialDeclsBase {
357 SomeInvalidationImplementingObject *Ivar1;
358#if RUN_IVAR_INVALIDATION
359 // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}}
360#endif
361}
362@end
363@implementation OnlyPartialDecls
364@end
365
Anna Zaks26db7db2013-02-08 23:55:43 +0000366// False negative.
367@interface PartialCallsFull : SomeInvalidationImplementingObject {
368 SomeInvalidationImplementingObject *Ivar1;
369}
370-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
371@end
372@implementation PartialCallsFull
373-(void)partialInvalidator {
374 [self invalidate];
375} // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar.
376@end
377