brintos

brintos / llvm-project-archived public Read only

0
0
Text · 12.4 KiB · e61b089 Raw
391 lines · plain
1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.cocoa.InstanceVariableInvalidation -DRUN_IVAR_INVALIDATION -verify %s2// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.osx.cocoa.MissingInvalidationMethod -DRUN_MISSING_INVALIDATION_METHOD -verify %s3extern 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__))9 10@protocol NSObject11@end12@interface NSObject <NSObject> {}13+(id)alloc;14+(id)new;15-(id)init;16-(id)autorelease;17-(id)copy;18- (Class)class;19-(id)retain;20-(id)description;21@end22@class NSString;23 24extern void NSLog(NSString *format, ...) __attribute__((format(__NSString__, 1, 2)));25 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")));36- (void) invalidate2 __attribute__((annotate("objc_instance_variable_invalidator")));37@end38 39@protocol Invalidation3;40@protocol Invalidation2;41 42@interface Invalidation2Class <Invalidation2>43@end44 45@interface Invalidation1Class <Invalidation1>46@end47 48@interface ClassWithInvalidationMethodInCategory <NSObject>49@end50 51@interface ClassWithInvalidationMethodInCategory ()52- (void) invalidate __attribute__((annotate("objc_instance_variable_invalidator")));53@end54 55@interface SomeInvalidationImplementingObject: NSObject <Invalidation3, Invalidation2> {56  SomeInvalidationImplementingObject *ObjA; // invalidation in the parent57}58@end59 60@implementation SomeInvalidationImplementingObject61- (void)invalidate{62  ObjA = 0;63}64- (void)invalidate2 {65  [self invalidate];66}67@end68 69@interface SomeSubclassInvalidatableObject : SomeInvalidationImplementingObject {70  SomeInvalidationImplementingObject *Ivar1; // regular ivar71  SomeInvalidationImplementingObject *Ivar2; // regular ivar, sending invalidate message72  SomeInvalidationImplementingObject *_Ivar3; // no property, call -description73  SomeInvalidationImplementingObject *_Ivar4; // no property, provide as argument to NSLog()74 75  SomeInvalidationImplementingObject *_Prop1; // partially implemented property, set to 0 with dot syntax76  SomeInvalidationImplementingObject *_Prop2; // fully implemented prop, set to 0 with dot syntax77  SomeInvalidationImplementingObject *_propIvar; // property with custom named ivar, set to 0 via setter78  Invalidation1Class *MultipleProtocols; // regular ivar belonging to a different class79  Invalidation2Class *MultInheritance; // regular ivar belonging to a different class80  SomeInvalidationImplementingObject *_Prop3; // property, invalidate via sending a message to a getter method81  SomeInvalidationImplementingObject *_Prop4; // property with @synthesize, invalidate via property82  SomeInvalidationImplementingObject *_Prop5; // property with @synthesize, invalidate via getter method83  SomeInvalidationImplementingObject *_Prop8;84  85  // Ivars invalidated by the partial invalidator. 86  SomeInvalidationImplementingObject *Ivar9;87  SomeInvalidationImplementingObject *_Prop10;88  SomeInvalidationImplementingObject *Ivar11;89 90  // No warnings on these as they are not invalidatable.91  NSObject *NIvar1;92  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;101@property (assign) SomeInvalidationImplementingObject *Prop5;102@property (assign) SomeInvalidationImplementingObject *Prop4;103 104@property (assign) SomeInvalidationImplementingObject* Prop6; // automatically synthesized prop105@property (assign) SomeInvalidationImplementingObject* Prop7; // automatically synthesized prop106@property (assign) SomeInvalidationImplementingObject *SynthIvarProp;107 108@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 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")));121@end122 123@interface SomeSubclassInvalidatableObject()124@property (assign) SomeInvalidationImplementingObject* Prop8;125@property (assign) SomeInvalidationImplementingObject* Prop10;126@end127 128@implementation SomeSubclassInvalidatableObject{129  @private130  SomeInvalidationImplementingObject *Ivar5;131  ClassWithInvalidationMethodInCategory *Ivar13;132}133 134@synthesize Prop7 = _propIvar;135@synthesize Prop3 = _Prop3;136@synthesize Prop5 = _Prop5;137@synthesize Prop4 = _Prop4;138@synthesize Prop8 = _Prop8;139@synthesize Prop10 = _Prop10;140 141 142- (void) setProp1: (SomeInvalidationImplementingObject*) InObj {143  _Prop1 = InObj;144}145 146- (void) setProp2: (SomeInvalidationImplementingObject*) InObj {147  _Prop2 = InObj;148}149- (SomeInvalidationImplementingObject*) Prop2 {150  return _Prop2;151}152 153@synthesize NProp2 = _NpropIvar;154 155- (void) setNProp1: (NSObject*) InObj {156  _NProp1 = InObj;157}158 159- (void) invalidate {160   [Ivar2 invalidate];161   self.Prop0 = 0;162   self.Prop1 = 0;163   [self setProp2:0];164   [self setProp3:0];165   [[self Prop5] invalidate2];166   [self.Prop4 invalidate];167   [self.Prop8 invalidate];168   self.Prop6 = 0;169   [[self Prop7] invalidate];170 171   [_Ivar3 description]; 172   NSLog(@"%@", _Ivar4);173   [super invalidate];174}175#if RUN_IVAR_INVALIDATION176// 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#endif185 186-(void)partialInvalidator1 {187  [Ivar9 invalidate];188  [_Prop10 invalidate];189}190 191-(void)partialInvalidator2 {192  [Ivar11 invalidate];193}194 195@end196 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@end204 205@interface Parent : NSObject <IDEBuildable, Invalidation2> {206  Invalidation2Class *_ObjB; // Invalidation of ObjB happens in the parent.207}208@end209 210@interface Child: Parent <Invalidation2, IDEBuildable> 211@end212 213@implementation Parent{214  @private215  Invalidation2Class *Ivar10;216  Invalidation2Class *Ivar11;217  Invalidation2Class *Ivar12;218}219 220@synthesize ObjB = _ObjB;221- (void)invalidate{222  _ObjB = ((void*)0);223  224  assert(Ivar10 == 0);225 226  if (__builtin_expect(!(Ivar11 == ((void*)0)), 0))227    assert(0);228 229  assert(0 == Ivar12);230 231}232@end233 234@implementation Child235- (void)invalidate{ 236  // no-warning237} 238@end239 240@protocol Invalidation <NSObject>241- (void)invalidate __attribute__((annotate("objc_instance_variable_invalidator")));242@end243 244@interface Foo : NSObject <Invalidation>245@end246 247@class FooBar;248@protocol FooBar_Protocol <NSObject>249@end250 251@interface MissingInvalidationMethod : Foo <FooBar_Protocol>252@property (assign) MissingInvalidationMethod *foobar15_warn;253#if RUN_IVAR_INVALIDATION254// expected-warning@-2 {{Property foobar15_warn needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod}}255#endif256@end257@implementation MissingInvalidationMethod258@end259 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_INVALIDATION264// expected-warning@-3 {{Property foobar16_warn needs to be invalidated; no invalidation method is defined in the @implementation for SuppressedMissingInvalidationMethod}}265#endif266 267@end268@implementation SuppressedMissingInvalidationMethod269@end270 271@interface MissingInvalidationMethod2 : Foo <FooBar_Protocol> {272  Foo *Ivar1;273#if RUN_IVAR_INVALIDATION274// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for MissingInvalidationMethod2}}275#endif276}277@end278@implementation MissingInvalidationMethod2279@end280 281@interface MissingInvalidationMethodDecl : NSObject {282  Foo *Ivar1;283#if RUN_MISSING_INVALIDATION_METHOD284// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl}}285#endif286}287@end288@implementation MissingInvalidationMethodDecl289@end290 291@interface MissingInvalidationMethodDecl2 : NSObject {292@private293    Foo *_foo1;294#if RUN_MISSING_INVALIDATION_METHOD295// expected-warning@-2 {{Instance variable _foo1 needs to be invalidated; no invalidation method is declared for MissingInvalidationMethodDecl2}}296#endif297}298@property (strong) Foo *bar1; 299@end300@implementation MissingInvalidationMethodDecl2301@end302 303@interface InvalidatedInPartial : SomeInvalidationImplementingObject {304  SomeInvalidationImplementingObject *Ivar1;305  SomeInvalidationImplementingObject *Ivar2;306  [[clang::suppress]]307  SomeInvalidationImplementingObject *Ivar3; // no-warning308}309-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));310@end311@implementation InvalidatedInPartial312-(void)partialInvalidator {313  [Ivar1 invalidate];314  Ivar2 = 0;315}316@end317 318@interface NotInvalidatedInPartial : SomeInvalidationImplementingObject {319  SomeInvalidationImplementingObject *Ivar1; 320}321-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));322-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));323@end324@implementation NotInvalidatedInPartial325-(void)partialInvalidator {326}327-(void)partialInvalidatorCallsPartial {328  [self partialInvalidator];329}330 331-(void)invalidate {332} 333#if RUN_IVAR_INVALIDATION334// expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated or set to nil}}335#endif336@end337 338@interface SomeNotInvalidatedInPartial : SomeInvalidationImplementingObject {339  SomeInvalidationImplementingObject *Ivar1;340  SomeInvalidationImplementingObject *Ivar2;341#if RUN_IVAR_INVALIDATION342  // expected-warning@-2 {{Instance variable Ivar2 needs to be invalidated or set to nil}}343#endif344}345-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));346-(void)partialInvalidatorCallsPartial __attribute__((annotate("objc_instance_variable_invalidator_partial")));347@end348@implementation SomeNotInvalidatedInPartial {349  SomeInvalidationImplementingObject *Ivar3;350#if RUN_IVAR_INVALIDATION351  // expected-warning@-2 {{Instance variable Ivar3 needs to be invalidated or set to nil}}352#endif353}354-(void)partialInvalidator {355  Ivar1 = 0;356}357-(void)partialInvalidatorCallsPartial {358  [self partialInvalidator];359}360@end361 362@interface OnlyPartialDeclsBase : NSObject363-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));364@end365@implementation OnlyPartialDeclsBase366-(void)partialInvalidator {}367@end368 369@interface OnlyPartialDecls : OnlyPartialDeclsBase {370  SomeInvalidationImplementingObject *Ivar1;371#if RUN_IVAR_INVALIDATION372  // expected-warning@-2 {{Instance variable Ivar1 needs to be invalidated; no invalidation method is defined in the @implementation for OnlyPartialDecls}}373#endif374}375@end376@implementation OnlyPartialDecls377@end378 379// False negative.380@interface PartialCallsFull : SomeInvalidationImplementingObject {381  SomeInvalidationImplementingObject *Ivar1;382}383-(void)partialInvalidator __attribute__((annotate("objc_instance_variable_invalidator_partial")));384@end385@implementation PartialCallsFull386-(void)partialInvalidator {387 [self invalidate];388} // TODO: It would be nice to check that the full invalidation method actually invalidates the ivar. 389@end390 391