xref: /aosp_15_r20/external/clang/test/Analysis/objc_invalidation.m (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -DRUN_IVAR_INVALIDATION -verify %s
2*67e74705SXin Li// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.MissingInvalidationMethod -DRUN_MISSING_INVALIDATION_METHOD -verify %s
3*67e74705SXin Liextern void __assert_fail (__const char *__assertion, __const char *__file,
4*67e74705SXin Li    unsigned int __line, __const char *__function)
5*67e74705SXin Li     __attribute__ ((__noreturn__));
6*67e74705SXin Li
7*67e74705SXin Li#define assert(expr) \
8*67e74705SXin Li  ((expr)  ? (void)(0)  : __assert_fail (#expr, __FILE__, __LINE__, __func__))
9*67e74705SXin Li
10*67e74705SXin Li@protocol NSObject
11*67e74705SXin Li@end
12*67e74705SXin Li@interface NSObject <NSObject> {}
13*67e74705SXin Li+(id)alloc;
14*67e74705SXin Li+(id)new;
15*67e74705SXin Li-(id)init;
16*67e74705SXin Li-(id)autorelease;
17*67e74705SXin Li-(id)copy;
18*67e74705SXin Li- (Class)class;
19*67e74705SXin Li-(id)retain;
20*67e74705SXin Li-(id)description;
21*67e74705SXin Li@end
22*67e74705SXin Li@class NSString;
23*67e74705SXin Li
24*67e74705SXin Liextern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));
25*67e74705SXin Li
26*67e74705SXin Li@protocol Invalidation1 <NSObject>
27*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
28*67e74705SXin Li@end
29*67e74705SXin Li
30*67e74705SXin Li@protocol Invalidation2 <NSObject>
31*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
32*67e74705SXin Li@end
33*67e74705SXin Li
34*67e74705SXin Li@protocol Invalidation3 <NSObject>
35*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
36*67e74705SXin Li- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator")));
37*67e74705SXin Li@end
38*67e74705SXin Li
39*67e74705SXin Li@protocol Invalidation3;
40*67e74705SXin Li@protocol Invalidation2;
41*67e74705SXin Li
42*67e74705SXin Li@interface Invalidation2Class <Invalidation2>
43*67e74705SXin Li@end
44*67e74705SXin Li
45*67e74705SXin Li@interface Invalidation1Class <Invalidation1>
46*67e74705SXin Li@end
47*67e74705SXin Li
48*67e74705SXin Li@interface ClassWithInvalidationMethodInCategory <NSObject>
49*67e74705SXin Li@end
50*67e74705SXin Li
51*67e74705SXin Li@interface ClassWithInvalidationMethodInCategory ()
52*67e74705SXin Li- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
53*67e74705SXin Li@end
54*67e74705SXin Li
55*67e74705SXin Li@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> {
56*67e74705SXin Li  SomeInvalidationImplementingObject *ObjA; // invalidation in the parent
57*67e74705SXin Li}
58*67e74705SXin Li@end
59*67e74705SXin Li
60*67e74705SXin Li@implementation SomeInvalidationImplementingObject
61*67e74705SXin Li- (void)invalidate{
62*67e74705SXin Li  ObjA = 0;
63*67e74705SXin Li}
64*67e74705SXin Li- (void)invalidate2 {
65*67e74705SXin Li  [self invalidate];
66*67e74705SXin Li}
67*67e74705SXin Li@end
68*67e74705SXin Li
69*67e74705SXin Li@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject {
70*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1; // regular ivar
71*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar2; // regular ivar, sending invalidate message
72*67e74705SXin Li  SomeInvalidationImplementingObject *_Ivar3; // no property, call -description
73*67e74705SXin Li  SomeInvalidationImplementingObject *_Ivar4; // no property, provide as argument to NSLog()
74*67e74705SXin Li
75*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop1; // partially implemented property, set to 0 with dot syntax
76*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop2; // fully implemented prop, set to 0 with dot syntax
77*67e74705SXin Li  SomeInvalidationImplementingObject *_propIvar; // property with custom named ivar, set to 0 via setter
78*67e74705SXin Li  Invalidation1Class *MultipleProtocols; // regular ivar belonging to a different class
79*67e74705SXin Li  Invalidation2Class *MultInheritance; // regular ivar belonging to a different class
80*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop3; // property, invalidate via sending a message to a getter method
81*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop4; // property with @synthesize, invalidate via property
82*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop5; // property with @synthesize, invalidate via getter method
83*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop8;
84*67e74705SXin Li
85*67e74705SXin Li  // Ivars invalidated by the partial invalidator.
86*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar9;
87*67e74705SXin Li  SomeInvalidationImplementingObject *_Prop10;
88*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar11;
89*67e74705SXin Li
90*67e74705SXin Li  // No warnings on these as they are not invalidatable.
91*67e74705SXin Li  NSObject *NIvar1;
92*67e74705SXin Li  NSObject *NObj2;
93*67e74705SXin Li  NSObject *_NProp1;
94*67e74705SXin Li  NSObject *_NpropIvar;
95*67e74705SXin Li}
96*67e74705SXin Li
97*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop0;
98*67e74705SXin Li@property (nonatomic, assign) SomeInvalidationImplementingObject* Prop1;
99*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop2;
100*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop3;
101*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *Prop5;
102*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *Prop4;
103*67e74705SXin Li
104*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop
105*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop
106*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject *SynthIvarProp;
107*67e74705SXin Li
108*67e74705SXin Li@property (assign) NSObject* NProp0;
109*67e74705SXin Li@property (nonatomic, assign) NSObject* NProp1;
110*67e74705SXin Li@property (assign) NSObject* NProp2;
111*67e74705SXin Li
112*67e74705SXin Li-(void)setProp1: (SomeInvalidationImplementingObject*) InO;
113*67e74705SXin Li-(void)setNProp1: (NSObject*) InO;
114*67e74705SXin Li
115*67e74705SXin Li-(void)invalidate;
116*67e74705SXin Li
117*67e74705SXin Li// Partial invalidators invalidate only some ivars. They are guaranteed to be
118*67e74705SXin Li// called before the invalidation methods.
119*67e74705SXin Li-(void)partialInvalidator1 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
120*67e74705SXin Li-(void)partialInvalidator2 __attribute__((annotate("objc_instance_variable_invalidator_partial")));
121*67e74705SXin Li@end
122*67e74705SXin Li
123*67e74705SXin Li@interface SomeSubclassInvalidatableObject()
124*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop8;
125*67e74705SXin Li@property (assign) SomeInvalidationImplementingObject* Prop10;
126*67e74705SXin Li@end
127*67e74705SXin Li
128*67e74705SXin Li@implementation SomeSubclassInvalidatableObject{
129*67e74705SXin Li  @private
130*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar5;
131*67e74705SXin Li  ClassWithInvalidationMethodInCategory *Ivar13;
132*67e74705SXin Li}
133*67e74705SXin Li
134*67e74705SXin Li@synthesize Prop7 = _propIvar;
135*67e74705SXin Li@synthesize Prop3 = _Prop3;
136*67e74705SXin Li@synthesize Prop5 = _Prop5;
137*67e74705SXin Li@synthesize Prop4 = _Prop4;
138*67e74705SXin Li@synthesize Prop8 = _Prop8;
139*67e74705SXin Li@synthesize Prop10 = _Prop10;
140*67e74705SXin Li
141*67e74705SXin Li
142*67e74705SXin Li- (void) setProp1: (SomeInvalidationImplementingObject*) InObj {
143*67e74705SXin Li  _Prop1 = InObj;
144*67e74705SXin Li}
145*67e74705SXin Li
146*67e74705SXin Li- (void) setProp2: (SomeInvalidationImplementingObject*) InObj {
147*67e74705SXin Li  _Prop2 = InObj;
148*67e74705SXin Li}
149*67e74705SXin Li- (SomeInvalidationImplementingObject*) Prop2 {
150*67e74705SXin Li  return _Prop2;
151*67e74705SXin Li}
152*67e74705SXin Li
153*67e74705SXin Li@synthesize NProp2 = _NpropIvar;
154*67e74705SXin Li
155*67e74705SXin Li- (void) setNProp1: (NSObject*) InObj {
156*67e74705SXin Li  _NProp1 = InObj;
157*67e74705SXin Li}
158*67e74705SXin Li
159*67e74705SXin Li- (void) invalidate {
160*67e74705SXin Li   [Ivar2 invalidate];
161*67e74705SXin Li   self.Prop0 = 0;
162*67e74705SXin Li   self.Prop1 = 0;
163*67e74705SXin Li   [self setProp2:0];
164*67e74705SXin Li   [self setProp3:0];
165*67e74705SXin Li   [[self Prop5] invalidate2];
166*67e74705SXin Li   [self.Prop4 invalidate];
167*67e74705SXin Li   [self.Prop8 invalidate];
168*67e74705SXin Li   self.Prop6 = 0;
169*67e74705SXin Li   [[self Prop7] invalidate];
170*67e74705SXin Li
171*67e74705SXin Li   [_Ivar3 description];
172*67e74705SXin Li   NSLog(@"%@", _Ivar4);
173*67e74705SXin Li   [super invalidate];
174*67e74705SXin Li}
175*67e74705SXin Li#if RUN_IVAR_INVALIDATION
176*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated}}
177*67e74705SXin Li// expected-warning@-3 {{Instance variable MultipleProtocols needs to be invalidated}}
178*67e74705SXin Li// expected-warning@-4 {{Instance variable MultInheritance needs to be invalidated}}
179*67e74705SXin Li// expected-warning@-5 {{Property SynthIvarProp needs to be invalidated or set to nil}}
180*67e74705SXin Li// expected-warning@-6 {{Instance variable _Ivar3 needs to be invalidated}}
181*67e74705SXin Li// expected-warning@-7 {{Instance variable _Ivar4 needs to be invalidated}}
182*67e74705SXin Li// expected-warning@-8 {{Instance variable Ivar5 needs to be invalidated or set to nil}}
183*67e74705SXin Li// expected-warning@-9 {{Instance variable Ivar13 needs to be invalidated or set to nil}}
184*67e74705SXin Li#endif
185*67e74705SXin Li
186*67e74705SXin Li-(void)partialInvalidator1 {
187*67e74705SXin Li  [Ivar9 invalidate];
188*67e74705SXin Li  [_Prop10 invalidate];
189*67e74705SXin Li}
190*67e74705SXin Li
191*67e74705SXin Li-(void)partialInvalidator2 {
192*67e74705SXin Li  [Ivar11 invalidate];
193*67e74705SXin Li}
194*67e74705SXin Li
195*67e74705SXin Li@end
196*67e74705SXin Li
197*67e74705SXin Li// Example, where the same property is inherited through
198*67e74705SXin Li// the parent and directly through a protocol. If a property backing ivar is
199*67e74705SXin Li// synthesized in the parent, let the parent invalidate it.
200*67e74705SXin Li
201*67e74705SXin Li@protocol IDEBuildable <NSObject>
202*67e74705SXin Li@property (readonly, strong) id <Invalidation2> ObjB;
203*67e74705SXin Li@end
204*67e74705SXin Li
205*67e74705SXin Li@interface Parent : NSObject <IDEBuildable, Invalidation2> {
206*67e74705SXin Li  Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent.
207*67e74705SXin Li}
208*67e74705SXin Li@end
209*67e74705SXin Li
210*67e74705SXin Li@interface Child: Parent <Invalidation2, IDEBuildable>
211*67e74705SXin Li@end
212*67e74705SXin Li
213*67e74705SXin Li@implementation Parent{
214*67e74705SXin Li  @private
215*67e74705SXin Li  Invalidation2Class *Ivar10;
216*67e74705SXin Li  Invalidation2Class *Ivar11;
217*67e74705SXin Li  Invalidation2Class *Ivar12;
218*67e74705SXin Li}
219*67e74705SXin Li
220*67e74705SXin Li@synthesize ObjB = _ObjB;
221*67e74705SXin Li- (void)invalidate{
222*67e74705SXin Li  _ObjB = ((void*)0);
223*67e74705SXin Li
224*67e74705SXin Li  assert(Ivar10 == 0);
225*67e74705SXin Li
226*67e74705SXin Li  if (__builtin_expect(!(Ivar11 == ((void*)0)), 0))
227*67e74705SXin Li    assert(0);
228*67e74705SXin Li
229*67e74705SXin Li  assert(0 == Ivar12);
230*67e74705SXin Li
231*67e74705SXin Li}
232*67e74705SXin Li@end
233*67e74705SXin Li
234*67e74705SXin Li@implementation Child
235*67e74705SXin Li- (void)invalidate{
236*67e74705SXin Li  // no-warning
237*67e74705SXin Li}
238*67e74705SXin Li@end
239*67e74705SXin Li
240*67e74705SXin Li@protocol Invalidation <NSObject>
241*67e74705SXin Li- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator")));
242*67e74705SXin Li@end
243*67e74705SXin Li
244*67e74705SXin Li@interface Foo : NSObject <Invalidation>
245*67e74705SXin Li@end
246*67e74705SXin Li
247*67e74705SXin Li@class FooBar;
248*67e74705SXin Li@protocol FooBar_Protocol <NSObject>
249*67e74705SXin Li@end
250*67e74705SXin Li
251*67e74705SXin Li@interface MissingInvalidationMethod : Foo <FooBar_Protocol>
252*67e74705SXin Li@property (assign) MissingInvalidationMethod *foobar15_warn;
253*67e74705SXin Li#if RUN_IVAR_INVALIDATION
254*67e74705SXin Li// expected-warning@-2 {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}}
255*67e74705SXin Li#endif
256*67e74705SXin Li@end
257*67e74705SXin Li@implementation MissingInvalidationMethod
258*67e74705SXin Li@end
259*67e74705SXin Li
260*67e74705SXin Li@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> {
261*67e74705SXin Li  Foo *Ivar1;
262*67e74705SXin Li#if RUN_IVAR_INVALIDATION
263*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}}
264*67e74705SXin Li#endif
265*67e74705SXin Li}
266*67e74705SXin Li@end
267*67e74705SXin Li@implementation MissingInvalidationMethod2
268*67e74705SXin Li@end
269*67e74705SXin Li
270*67e74705SXin Li@interface MissingInvalidationMethodDecl : NSObject {
271*67e74705SXin Li  Foo *Ivar1;
272*67e74705SXin Li#if RUN_MISSING_INVALIDATION_METHOD
273*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}}
274*67e74705SXin Li#endif
275*67e74705SXin Li}
276*67e74705SXin Li@end
277*67e74705SXin Li@implementation MissingInvalidationMethodDecl
278*67e74705SXin Li@end
279*67e74705SXin Li
280*67e74705SXin Li@interface MissingInvalidationMethodDecl2 : NSObject {
281*67e74705SXin Li@private
282*67e74705SXin Li    Foo *_foo1;
283*67e74705SXin Li#if RUN_MISSING_INVALIDATION_METHOD
284*67e74705SXin Li// expected-warning@-2 {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}}
285*67e74705SXin Li#endif
286*67e74705SXin Li}
287*67e74705SXin Li@property (strong) Foo *bar1;
288*67e74705SXin Li@end
289*67e74705SXin Li@implementation MissingInvalidationMethodDecl2
290*67e74705SXin Li@end
291*67e74705SXin Li
292*67e74705SXin Li@interface InvalidatedInPartial : SomeInvalidationImplementingObject {
293*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1;
294*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar2;
295*67e74705SXin Li}
296*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
297*67e74705SXin Li@end
298*67e74705SXin Li@implementation InvalidatedInPartial
299*67e74705SXin Li-(void)partialInvalidator {
300*67e74705SXin Li  [Ivar1 invalidate];
301*67e74705SXin Li  Ivar2 = 0;
302*67e74705SXin Li}
303*67e74705SXin Li@end
304*67e74705SXin Li
305*67e74705SXin Li@interface NotInvalidatedInPartial : SomeInvalidationImplementingObject {
306*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1;
307*67e74705SXin Li}
308*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
309*67e74705SXin Li-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
310*67e74705SXin Li@end
311*67e74705SXin Li@implementation NotInvalidatedInPartial
312*67e74705SXin Li-(void)partialInvalidator {
313*67e74705SXin Li}
314*67e74705SXin Li-(void)partialInvalidatorCallsPartial {
315*67e74705SXin Li  [self partialInvalidator];
316*67e74705SXin Li}
317*67e74705SXin Li
318*67e74705SXin Li-(void)invalidate {
319*67e74705SXin Li}
320*67e74705SXin Li#if RUN_IVAR_INVALIDATION
321*67e74705SXin Li// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated or set to nil}}
322*67e74705SXin Li#endif
323*67e74705SXin Li@end
324*67e74705SXin Li
325*67e74705SXin Li@interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject {
326*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1;
327*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar2;
328*67e74705SXin Li#if RUN_IVAR_INVALIDATION
329*67e74705SXin Li  // expected-warning@-2 {{Instance variable Ivar2 needs to be invalidated or set to nil}}
330*67e74705SXin Li#endif
331*67e74705SXin Li}
332*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
333*67e74705SXin Li-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));
334*67e74705SXin Li@end
335*67e74705SXin Li@implementation SomeNotInvalidatedInPartial {
336*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar3;
337*67e74705SXin Li#if RUN_IVAR_INVALIDATION
338*67e74705SXin Li  // expected-warning@-2 {{Instance variable Ivar3 needs to be invalidated or set to nil}}
339*67e74705SXin Li#endif
340*67e74705SXin Li}
341*67e74705SXin Li-(void)partialInvalidator {
342*67e74705SXin Li  Ivar1 = 0;
343*67e74705SXin Li}
344*67e74705SXin Li-(void)partialInvalidatorCallsPartial {
345*67e74705SXin Li  [self partialInvalidator];
346*67e74705SXin Li}
347*67e74705SXin Li@end
348*67e74705SXin Li
349*67e74705SXin Li@interface OnlyPartialDeclsBase : NSObject
350*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
351*67e74705SXin Li@end
352*67e74705SXin Li@implementation OnlyPartialDeclsBase
353*67e74705SXin Li-(void)partialInvalidator {}
354*67e74705SXin Li@end
355*67e74705SXin Li
356*67e74705SXin Li@interface OnlyPartialDecls : OnlyPartialDeclsBase {
357*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1;
358*67e74705SXin Li#if RUN_IVAR_INVALIDATION
359*67e74705SXin Li  // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}}
360*67e74705SXin Li#endif
361*67e74705SXin Li}
362*67e74705SXin Li@end
363*67e74705SXin Li@implementation OnlyPartialDecls
364*67e74705SXin Li@end
365*67e74705SXin Li
366*67e74705SXin Li// False negative.
367*67e74705SXin Li@interface PartialCallsFull : SomeInvalidationImplementingObject {
368*67e74705SXin Li  SomeInvalidationImplementingObject *Ivar1;
369*67e74705SXin Li}
370*67e74705SXin Li-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));
371*67e74705SXin Li@end
372*67e74705SXin Li@implementation PartialCallsFull
373*67e74705SXin Li-(void)partialInvalidator {
374*67e74705SXin Li [self invalidate];
375*67e74705SXin Li} // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar.
376*67e74705SXin Li@end
377*67e74705SXin Li
378