diff options
Diffstat (limited to 'test/Analysis/NSContainers.m')
-rw-r--r-- | test/Analysis/NSContainers.m | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/test/Analysis/NSContainers.m b/test/Analysis/NSContainers.m new file mode 100644 index 0000000..d6fded5 --- /dev/null +++ b/test/Analysis/NSContainers.m @@ -0,0 +1,200 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NilArg -verify -Wno-objc-root-class %s +typedef unsigned long NSUInteger; +typedef signed char BOOL; +typedef struct _NSZone NSZone; +@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; +@protocol NSObject +@end +@protocol NSCopying +- (id)copyWithZone:(NSZone *)zone; +@end +@protocol NSMutableCopying +- (id)mutableCopyWithZone:(NSZone *)zone; +@end +@protocol NSCoding +- (void)encodeWithCoder:(NSCoder *)aCoder; +@end +@protocol NSFastEnumeration +@end +@protocol NSSecureCoding <NSCoding> +@required ++ (BOOL)supportsSecureCoding; +@end +@interface NSObject <NSObject> {} +- (id)init; ++ (id)alloc; +@end +@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> + +- (NSUInteger)count; +- (id)objectAtIndex:(NSUInteger)index; + +@end + +@interface NSArray (NSExtendedArray) +- (NSArray *)arrayByAddingObject:(id)anObject; +- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8))); +@end + +@interface NSMutableArray : NSArray + +- (void)addObject:(id)anObject; +- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; +- (void)removeLastObject; +- (void)removeObjectAtIndex:(NSUInteger)index; +- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; + +@end + +@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> + +- (NSUInteger)count; +- (id)objectForKey:(id)aKey; +- (NSEnumerator *)keyEnumerator; + +@end + +@interface NSDictionary (NSDictionaryCreation) + ++ (id)dictionary; ++ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key; +@end + +@interface NSMutableDictionary : NSDictionary + +- (void)removeObjectForKey:(id)aKey; +- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey; + +@end + +@interface NSMutableDictionary (NSExtendedMutableDictionary) + +- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; +- (void)removeAllObjects; +- (void)removeObjectsForKeys:(NSArray *)keyArray; +- (void)setDictionary:(NSDictionary *)otherDictionary; +- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8))); + +@end + +@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> + +@end + +// NSMutableArray API +void testNilArgNSMutableArray1() { + NSMutableArray *marray = [[NSMutableArray alloc] init]; + [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} +} + +void testNilArgNSMutableArray2() { + NSMutableArray *marray = [[NSMutableArray alloc] init]; + [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}} +} + +void testNilArgNSMutableArray3() { + NSMutableArray *marray = [[NSMutableArray alloc] init]; + [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}} +} + +void testNilArgNSMutableArray4() { + NSMutableArray *marray = [[NSMutableArray alloc] init]; + [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}} +} + +void testNilArgNSMutableArray5() { + NSMutableArray *marray = [[NSMutableArray alloc] init]; + marray[1] = 0; // expected-warning {{Array element cannot be nil}} +} + +// NSArray API +void testNilArgNSArray1() { + NSArray *array = [[NSArray alloc] init]; + NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}} +} + +// NSMutableDictionary and NSDictionary APIs. +void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { + [d setObject:0 forKey:key]; // expected-warning {{Argument to 'NSMutableDictionary' method 'setObject:forKey:' cannot be nil}} +} + +void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { + [d setObject:obj forKey:0]; // expected-warning {{Argument to 'NSMutableDictionary' method 'setObject:forKey:' cannot be nil}} +} + +void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { + [d removeObjectForKey:0]; // expected-warning {{Argument to 'NSMutableDictionary' method 'removeObjectForKey:' cannot be nil}} +} + +void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { + d[key] = 0; // expected-warning {{Dictionary object cannot be nil}} +} +void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) { + if (key) + ; + d[key] = 0; // expected-warning {{Dictionary key cannot be nil}} + // expected-warning@-1 {{Dictionary object cannot be nil}} +} + +NSDictionary *testNilArgNSDictionary1(NSString* key) { + return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Argument to 'NSDictionary' method 'dictionaryWithObject:forKey:' cannot be nil}} +} +NSDictionary *testNilArgNSDictionary2(NSObject *obj) { + return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Argument to 'NSDictionary' method 'dictionaryWithObject:forKey:' cannot be nil}} +} + +// Test inline defensive checks suppression. +void idc(id x) { + if (x) + ; +} +void testIDC(NSMutableDictionary *d, NSString *key) { + idc(key); + d[key] = @"abc"; // no-warning +} + +@interface Foo { +@public + int x; +} +- (int *)getPtr; +- (int)getInt; +- (NSMutableDictionary *)getDictPtr; +@property (retain, readonly, nonatomic) Foo* data; +- (NSString*) stringForKeyFE: (id<NSCopying>)key; +@end + +void idc2(id x) { + if (!x) + return; +} +Foo *retNil() { + return 0; +} + +void testIDC2(Foo *obj) { + idc2(obj); + *[obj getPtr] = 1; // no-warning +} + +int testIDC3(Foo *obj) { + idc2(obj); + return 1/[obj getInt]; +} + +void testNilReceiverIDC(Foo *obj, NSString *key) { + NSMutableDictionary *D = [obj getDictPtr]; + idc(D); + D[key] = @"abc"; // no-warning +} + +void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) { + NSString* const kKeyIdentifier = @"key"; + Foo *FooPtr = retNil(); + NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier]; + // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an + // inlined function, so this error report should be suppressed. + [D setObject: value forKey: key]; // no-warning +} + + |