1 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -DRUN_IVAR_INVALIDATION -verify %s
2 // RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.cocoa.MissingInvalidationMethod -DRUN_MISSING_INVALIDATION_METHOD -verify %s
3 extern void __assert_fail (__const char *__assertion, __const char *__file,
4 unsigned int __line, __const char *__function)
5 __attribute__ ((__noreturn__));
8 ((expr) ? (void)(0) : __assert_fail (#expr, __FILE__, __LINE__, __func__))
12 @interface NSObject <NSObject> {}
24 extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
26 @protocol Invalidation1 <NSObject>
27 - (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
30 @protocol Invalidation2 <NSObject>
31 - (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
34 @protocol Invalidation3 <NSObject>
35 - (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
36 - (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator")));
39 @protocol Invalidation3;
40 @protocol Invalidation2;
42 @interface Invalidation2Class <Invalidation2>
45 @interface Invalidation1Class <Invalidation1>
48 @interface ClassWithInvalidationMethodInCategory <NSObject>
51 @interface ClassWithInvalidationMethodInCategory ()
52 - (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
55 @interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> {
56 SomeInvalidationImplementingObject *ObjA; // invalidation in the parent
60 @implementation SomeInvalidationImplementingObject
69 @interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject {
70 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()
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
83 SomeInvalidationImplementingObject *_Prop8;
85 // Ivars invalidated by the partial invalidator.
86 SomeInvalidationImplementingObject *Ivar9;
87 SomeInvalidationImplementingObject *_Prop10;
88 SomeInvalidationImplementingObject *Ivar11;
90 // No warnings on these as they are not invalidatable.
97 @property (assign) SomeInvalidationImplementingObject* Prop0;
98 @property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1;
99 @property (assign) SomeInvalidationImplementingObject* Prop2;
100 @property (assign) SomeInvalidationImplementingObject* Prop3;
101 @property (assign) SomeInvalidationImplementingObject *Prop5;
102 @property (assign) SomeInvalidationImplementingObject *Prop4;
104 @property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop
105 @property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop
106 @property (assign) SomeInvalidationImplementingObject *SynthIvarProp;
108 @property (assign) NSObject* NProp0;
109 @property (nonatomic, assign) NSObject* NProp1;
110 @property (assign) NSObject* NProp2;
112 -(void)setProp1: (SomeInvalidationImplementingObject*) InO;
113 -(void)setNProp1: (NSObject*) InO;
117 // 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")));
123 @interface SomeSubclassInvalidatableObject()
124 @property (assign) SomeInvalidationImplementingObject* Prop8;
125 @property (assign) SomeInvalidationImplementingObject* Prop10;
128 @implementation SomeSubclassInvalidatableObject{
130 SomeInvalidationImplementingObject *Ivar5;
131 ClassWithInvalidationMethodInCategory *Ivar13;
134 @synthesize Prop7 = _propIvar;
135 @synthesize Prop3 = _Prop3;
136 @synthesize Prop5 = _Prop5;
137 @synthesize Prop4 = _Prop4;
138 @synthesize Prop8 = _Prop8;
139 @synthesize Prop10 = _Prop10;
142 - (void) setProp1: (SomeInvalidationImplementingObject*) InObj {
146 - (void) setProp2: (SomeInvalidationImplementingObject*) InObj {
149 - (SomeInvalidationImplementingObject*) Prop2 {
153 @synthesize NProp2 = _NpropIvar;
155 - (void) setNProp1: (NSObject*) InObj {
159 - (void) invalidate {
165 [[self Prop5] invalidate2];
166 [self.Prop4 invalidate];
167 [self.Prop8 invalidate];
169 [[self Prop7] invalidate];
171 [_Ivar3 description];
172 NSLog(@"%@", _Ivar4);
175 #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}}
186 -(void)partialInvalidator1 {
188 [_Prop10 invalidate];
191 -(void)partialInvalidator2 {
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.
201 @protocol IDEBuildable <NSObject>
202 @property (readonly, strong) id <Invalidation2> ObjB;
205 @interface Parent : NSObject <IDEBuildable, Invalidation2> {
206 Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent.
210 @interface Child: Parent <Invalidation2, IDEBuildable>
213 @implementation Parent{
215 Invalidation2Class *Ivar10;
216 Invalidation2Class *Ivar11;
217 Invalidation2Class *Ivar12;
220 @synthesize ObjB = _ObjB;
226 if (__builtin_expect(!(Ivar11 == ((void*)0)), 0))
234 @implementation Child
240 @protocol Invalidation <NSObject>
241 - (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
244 @interface Foo : NSObject <Invalidation>
248 @protocol FooBar_Protocol <NSObject>
251 @interface MissingInvalidationMethod : Foo <FooBar_Protocol>
252 @property (assign) MissingInvalidationMethod *foobar15_warn;
253 #if RUN_IVAR_INVALIDATION
254 // expected-warning@-2 {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}}
257 @implementation MissingInvalidationMethod
260 @interface SuppressedMissingInvalidationMethod : Foo <FooBar_Protocol>
261 @property (assign) [[clang::suppress]] SuppressedMissingInvalidationMethod *foobar16_warn;
262 // FIXME: Suppression should have worked but decl-with-issue is the ivar, not the property.
263 #if RUN_IVAR_INVALIDATION
264 // expected-warning@-3 {{Property foobar16_warn needs to be invalidated; no invalidation method is defined in the @implementation for SuppressedMissingInvalidationMethod}}
268 @implementation SuppressedMissingInvalidationMethod
271 @interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> {
273 #if RUN_IVAR_INVALIDATION
274 // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}}
278 @implementation MissingInvalidationMethod2
281 @interface MissingInvalidationMethodDecl : NSObject {
283 #if RUN_MISSING_INVALIDATION_METHOD
284 // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}}
288 @implementation MissingInvalidationMethodDecl
291 @interface MissingInvalidationMethodDecl2 : NSObject {
294 #if RUN_MISSING_INVALIDATION_METHOD
295 // expected-warning@-2 {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}}
298 @property (strong) Foo *bar1;
300 @implementation MissingInvalidationMethodDecl2
303 @interface InvalidatedInPartial : SomeInvalidationImplementingObject {
304 SomeInvalidationImplementingObject *Ivar1;
305 SomeInvalidationImplementingObject *Ivar2;
307 SomeInvalidationImplementingObject *Ivar3; // no-warning
309 -(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
311 @implementation InvalidatedInPartial
312 -(void)partialInvalidator {
318 @interface NotInvalidatedInPartial : SomeInvalidationImplementingObject {
319 SomeInvalidationImplementingObject *Ivar1;
321 -(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
322 -(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
324 @implementation NotInvalidatedInPartial
325 -(void)partialInvalidator {
327 -(void)partialInvalidatorCallsPartial {
328 [self partialInvalidator];
333 #if RUN_IVAR_INVALIDATION
334 // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated or set to nil}}
338 @interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject {
339 SomeInvalidationImplementingObject *Ivar1;
340 SomeInvalidationImplementingObject *Ivar2;
341 #if RUN_IVAR_INVALIDATION
342 // expected-warning@-2 {{Instance variable Ivar2 needs to be invalidated or set to nil}}
345 -(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
346 -(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
348 @implementation SomeNotInvalidatedInPartial {
349 SomeInvalidationImplementingObject *Ivar3;
350 #if RUN_IVAR_INVALIDATION
351 // expected-warning@-2 {{Instance variable Ivar3 needs to be invalidated or set to nil}}
354 -(void)partialInvalidator {
357 -(void)partialInvalidatorCallsPartial {
358 [self partialInvalidator];
362 @interface OnlyPartialDeclsBase : NSObject
363 -(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
365 @implementation OnlyPartialDeclsBase
366 -(void)partialInvalidator {}
369 @interface OnlyPartialDecls : OnlyPartialDeclsBase {
370 SomeInvalidationImplementingObject *Ivar1;
371 #if RUN_IVAR_INVALIDATION
372 // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}}
376 @implementation OnlyPartialDecls
380 @interface PartialCallsFull : SomeInvalidationImplementingObject {
381 SomeInvalidationImplementingObject *Ivar1;
383 -(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
385 @implementation PartialCallsFull
386 -(void)partialInvalidator {
388 } // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar.