blob: 4b588ea36d67a26470e2d87549d19497619e9ea8 [file] [log] [blame]
Anna Zaks5bf5c2e2012-09-26 18:55:16 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -fobjc-default-synthesize-properties -verify %s
Anna Zaks65032552013-01-10 23:34:16 +00002extern 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__))
Anna Zaks5bf5c2e2012-09-26 18:55:16 +00008
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;
Anna Zaks31f69cc2012-09-29 00:20:38 +000019-(id)description;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000020@end
Anna Zaks31f69cc2012-09-29 00:20:38 +000021@class NSString;
22
23extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000024
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")));
Anna Zaks31f69cc2012-09-29 00:20:38 +000035- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator")));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000036@end
37
Anna Zaksb8f66782013-01-11 03:52:40 +000038@protocol Invalidation3;
39@protocol Invalidation2;
40
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000041@interface Invalidation2Class <Invalidation2>
42@end
43
44@interface Invalidation1Class <Invalidation1>
45@end
46
Anna Zaksae81e172013-01-11 03:52:37 +000047@interface ClassWithInvalidationMethodInCategory <NSObject>
48@end
49
50@interface ClassWithInvalidationMethodInCategory ()
51- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
52@end
53
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000054@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> {
Anna Zaks31f69cc2012-09-29 00:20:38 +000055 SomeInvalidationImplementingObject *ObjA; // invalidation in the parent
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000056}
57@end
58
59@implementation SomeInvalidationImplementingObject
60- (void)invalidate{
61 ObjA = 0;
62}
Anna Zaks31f69cc2012-09-29 00:20:38 +000063- (void)invalidate2 {
64 [self invalidate];
65}
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000066@end
67
68@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject {
Anna Zaks31f69cc2012-09-29 00:20:38 +000069 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
Anna Zaksc3c26b72012-10-18 19:17:57 +000082 SomeInvalidationImplementingObject *_Prop8;
Anna Zaksb087bbf2012-09-27 19:45:08 +000083
Anna Zaks26db7db2013-02-08 23:55:43 +000084 // Ivars invalidated by the partial invalidator.
85 SomeInvalidationImplementingObject *Ivar9;
86 SomeInvalidationImplementingObject *_Prop10;
87 SomeInvalidationImplementingObject *Ivar11;
88
Anna Zaks31f69cc2012-09-29 00:20:38 +000089 // No warnings on these as they are not invalidatable.
90 NSObject *NIvar1;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +000091 NSObject *NObj2;
92 NSObject *_NProp1;
93 NSObject *_NpropIvar;
94}
95
96@property (assign) SomeInvalidationImplementingObject* Prop0;
97@property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1;
98@property (assign) SomeInvalidationImplementingObject* Prop2;
99@property (assign) SomeInvalidationImplementingObject* Prop3;
Anna Zaks31f69cc2012-09-29 00:20:38 +0000100@property (assign) SomeInvalidationImplementingObject *Prop5;
101@property (assign) SomeInvalidationImplementingObject *Prop4;
Anna Zaks377945c2012-09-27 21:57:14 +0000102
Anna Zaks31f69cc2012-09-29 00:20:38 +0000103@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop
104@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop
105@property (assign) SomeInvalidationImplementingObject *SynthIvarProp;
Anna Zaks377945c2012-09-27 21:57:14 +0000106
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000107@property (assign) NSObject* NProp0;
108@property (nonatomic, assign) NSObject* NProp1;
109@property (assign) NSObject* NProp2;
110
111-(void)setProp1: (SomeInvalidationImplementingObject*) InO;
112-(void)setNProp1: (NSObject*) InO;
113
114-(void)invalidate;
115
Anna Zaks26db7db2013-02-08 23:55:43 +0000116// Partial invalidators invalidate only some ivars. They are guaranteed to be
117// called before the invalidation methods.
118-(void)partialInvalidator1 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
119-(void)partialInvalidator2 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000120@end
121
Anna Zakse0c50fa2012-10-16 19:36:37 +0000122@interface SomeSubclassInvalidatableObject()
123@property (assign) SomeInvalidationImplementingObject* Prop8;
Anna Zaks26db7db2013-02-08 23:55:43 +0000124@property (assign) SomeInvalidationImplementingObject* Prop10;
Anna Zakse0c50fa2012-10-16 19:36:37 +0000125@end
126
127@implementation SomeSubclassInvalidatableObject{
128 @private
129 SomeInvalidationImplementingObject *Ivar5;
Anna Zaksae81e172013-01-11 03:52:37 +0000130 ClassWithInvalidationMethodInCategory *Ivar13;
Anna Zakse0c50fa2012-10-16 19:36:37 +0000131}
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000132
Anna Zaks31f69cc2012-09-29 00:20:38 +0000133@synthesize Prop7 = _propIvar;
134@synthesize Prop3 = _Prop3;
135@synthesize Prop5 = _Prop5;
136@synthesize Prop4 = _Prop4;
Anna Zaksc3c26b72012-10-18 19:17:57 +0000137@synthesize Prop8 = _Prop8;
Anna Zaks26db7db2013-02-08 23:55:43 +0000138@synthesize Prop10 = _Prop10;
Anna Zaks31f69cc2012-09-29 00:20:38 +0000139
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000140
141- (void) setProp1: (SomeInvalidationImplementingObject*) InObj {
142 _Prop1 = InObj;
143}
144
Anna Zaks31f69cc2012-09-29 00:20:38 +0000145- (void) setProp2: (SomeInvalidationImplementingObject*) InObj {
146 _Prop2 = InObj;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000147}
Anna Zaks31f69cc2012-09-29 00:20:38 +0000148- (SomeInvalidationImplementingObject*) Prop2 {
149 return _Prop2;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000150}
151
152@synthesize NProp2 = _NpropIvar;
153
154- (void) setNProp1: (NSObject*) InObj {
155 _NProp1 = InObj;
156}
157
158- (void) invalidate {
Anna Zaks31f69cc2012-09-29 00:20:38 +0000159 [Ivar2 invalidate];
Anna Zaks377945c2012-09-27 21:57:14 +0000160 self.Prop0 = 0;
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000161 self.Prop1 = 0;
162 [self setProp2:0];
163 [self setProp3:0];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000164 [[self Prop5] invalidate2];
165 [self.Prop4 invalidate];
Anna Zaksc3c26b72012-10-18 19:17:57 +0000166 [self.Prop8 invalidate];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000167 self.Prop6 = 0;
168 [[self Prop7] invalidate];
169
170 [_Ivar3 description];
171 NSLog(@"%@", _Ivar4);
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000172 [super invalidate];
Anna Zaks31f69cc2012-09-29 00:20:38 +0000173}
174// expected-warning@-1 {{Instance variable Ivar1 needs to be invalidated}}
Anna Zaks26db7db2013-02-08 23:55:43 +0000175// expected-warning@-2 {{Instance variable MultipleProtocols needs to be invalidated}}
176// expected-warning@-3 {{Instance variable MultInheritance needs to be invalidated}}
177// expected-warning@-4 {{Property SynthIvarProp needs to be invalidated or set to nil}}
178// expected-warning@-5 {{Instance variable _Ivar3 needs to be invalidated}}
179// expected-warning@-6 {{Instance variable _Ivar4 needs to be invalidated}}
180// expected-warning@-7 {{Instance variable Ivar5 needs to be invalidated or set to nil}}
Anna Zaksae81e172013-01-11 03:52:37 +0000181// expected-warning@-8 {{Instance variable Ivar13 needs to be invalidated or set to nil}}
Anna Zaks26db7db2013-02-08 23:55:43 +0000182
183
184-(void)partialInvalidator1 {
185 [Ivar9 invalidate];
186 [_Prop10 invalidate];
187}
188
189-(void)partialInvalidator2 {
190 [Ivar11 invalidate];
191}
192
Anna Zaks5bf5c2e2012-09-26 18:55:16 +0000193@end
Anna Zaks5879fb32013-01-07 19:12:56 +0000194
195// Example, where the same property is inherited through
196// the parent and directly through a protocol. If a property backing ivar is
197// synthesized in the parent, let the parent invalidate it.
198
199@protocol IDEBuildable <NSObject>
200@property (readonly, strong) id <Invalidation2> ObjB;
201@end
202
203@interface Parent : NSObject <IDEBuildable, Invalidation2> {
204 Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent.
205}
206@end
207
208@interface Child: Parent <Invalidation2, IDEBuildable>
209@end
210
Anna Zaks65032552013-01-10 23:34:16 +0000211@implementation Parent{
212 @private
213 Invalidation2Class *Ivar10;
214 Invalidation2Class *Ivar11;
215 Invalidation2Class *Ivar12;
216}
217
Anna Zaks5879fb32013-01-07 19:12:56 +0000218@synthesize ObjB = _ObjB;
219- (void)invalidate{
220 _ObjB = ((void*)0);
Anna Zaks65032552013-01-10 23:34:16 +0000221
222 assert(Ivar10 == 0);
223
224 if (__builtin_expect(!(Ivar11 == ((void*)0)), 0))
225 assert(0);
226
227 assert(0 == Ivar12);
228
Anna Zaks5879fb32013-01-07 19:12:56 +0000229}
230@end
231
232@implementation Child
233- (void)invalidate{
234 // no-warning
235}
236@end
Anna Zaksb1fc6732013-01-10 20:59:51 +0000237
238@protocol Invalidation <NSObject>
239- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
240@end
241
242@interface Foo : NSObject <Invalidation>
243@end
244
245@class FooBar;
246@protocol FooBar_Protocol <NSObject>
247@end
248
249@interface MissingInvalidationMethod : Foo <FooBar_Protocol>
Anna Zaks79ccd562013-01-16 01:35:57 +0000250@property (assign) MissingInvalidationMethod *foobar15_warn; // expected-warning {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}}
Anna Zaksb1fc6732013-01-10 20:59:51 +0000251@end
252@implementation MissingInvalidationMethod
253@end
254
255@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> {
Anna Zaks79ccd562013-01-16 01:35:57 +0000256 Foo *Ivar1;// expected-warning {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}}
Anna Zaksb1fc6732013-01-10 20:59:51 +0000257}
258@end
259@implementation MissingInvalidationMethod2
260@end
261
262@interface MissingInvalidationMethodDecl : NSObject {
Anna Zaks79ccd562013-01-16 01:35:57 +0000263 Foo *Ivar1;// expected-warning {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}}
Anna Zaksb1fc6732013-01-10 20:59:51 +0000264}
265@end
266@implementation MissingInvalidationMethodDecl
267@end
268
269@interface MissingInvalidationMethodDecl2 : NSObject {
270@private
Anna Zaks79ccd562013-01-16 01:35:57 +0000271 Foo *_foo1; // expected-warning {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}}
Anna Zaksb1fc6732013-01-10 20:59:51 +0000272}
Anna Zaks664566c2013-01-10 22:44:16 +0000273@property (strong) Foo *bar1;
Anna Zaksb1fc6732013-01-10 20:59:51 +0000274@end
275@implementation MissingInvalidationMethodDecl2
276@end
Anna Zaks26db7db2013-02-08 23:55:43 +0000277
278@interface InvalidatedInPartial : SomeInvalidationImplementingObject {
279 SomeInvalidationImplementingObject *Ivar1;
280 SomeInvalidationImplementingObject *Ivar2;
281}
282-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
283@end
284@implementation InvalidatedInPartial
285-(void)partialInvalidator {
286 [Ivar1 invalidate];
287 Ivar2 = 0;
288}
289@end
290
291@interface NotInvalidatedInPartial : SomeInvalidationImplementingObject {
292 SomeInvalidationImplementingObject *Ivar1;
293}
294-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
295-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
296@end
297@implementation NotInvalidatedInPartial
298-(void)partialInvalidator {
299}
300-(void)partialInvalidatorCallsPartial {
301 [self partialInvalidator];
302}
303
304-(void)invalidate {
305} // expected-warning {{Instance variable Ivar1 needs to be invalidated or set to nil}}
306
307@end
308
309// False negative.
310@interface PartialCallsFull : SomeInvalidationImplementingObject {
311 SomeInvalidationImplementingObject *Ivar1;
312}
313-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
314@end
315@implementation PartialCallsFull
316-(void)partialInvalidator {
317 [self invalidate];
318} // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar.
319@end
320