NSContainers.m revision f2d8fbed93541b74c3a84bf788f151df2d543b27
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg -verify -Wno-objc-root-class %s 2typedef unsigned long NSUInteger; 3typedef signed char BOOL; 4typedef struct _NSZone NSZone; 5@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 6@protocol NSObject 7@end 8@protocol NSCopying 9- (id)copyWithZone:(NSZone *)zone; 10@end 11@protocol NSMutableCopying 12- (id)mutableCopyWithZone:(NSZone *)zone; 13@end 14@protocol NSCoding 15- (void)encodeWithCoder:(NSCoder *)aCoder; 16@end 17@protocol NSFastEnumeration 18@end 19@protocol NSSecureCoding <NSCoding> 20@required 21+ (BOOL)supportsSecureCoding; 22@end 23@interface NSObject <NSObject> {} 24- (id)init; 25+ (id)alloc; 26@end 27@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 28 29- (NSUInteger)count; 30- (id)objectAtIndex:(NSUInteger)index; 31 32@end 33 34@interface NSArray (NSExtendedArray) 35- (NSArray *)arrayByAddingObject:(id)anObject; 36- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8))); 37@end 38 39@interface NSMutableArray : NSArray 40 41- (void)addObject:(id)anObject; 42- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 43- (void)removeLastObject; 44- (void)removeObjectAtIndex:(NSUInteger)index; 45- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 46 47@end 48 49@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 50 51- (NSUInteger)count; 52- (id)objectForKey:(id)aKey; 53- (NSEnumerator *)keyEnumerator; 54 55@end 56 57@interface NSDictionary (NSDictionaryCreation) 58 59+ (id)dictionary; 60+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key; 61@end 62 63@interface NSMutableDictionary : NSDictionary 64 65- (void)removeObjectForKey:(id)aKey; 66- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey; 67 68@end 69 70@interface NSMutableDictionary (NSExtendedMutableDictionary) 71 72- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; 73- (void)removeAllObjects; 74- (void)removeObjectsForKeys:(NSArray *)keyArray; 75- (void)setDictionary:(NSDictionary *)otherDictionary; 76- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8))); 77 78@end 79 80@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> 81 82@end 83 84@interface NSNull : NSObject <NSCopying, NSSecureCoding> 85+ (NSNull *)null; 86@end 87 88// NSMutableArray API 89void testNilArgNSMutableArray1() { 90 NSMutableArray *marray = [[NSMutableArray alloc] init]; 91 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} 92} 93 94void testNilArgNSMutableArray2() { 95 NSMutableArray *marray = [[NSMutableArray alloc] init]; 96 [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}} 97} 98 99void testNilArgNSMutableArray3() { 100 NSMutableArray *marray = [[NSMutableArray alloc] init]; 101 [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}} 102} 103 104void testNilArgNSMutableArray4() { 105 NSMutableArray *marray = [[NSMutableArray alloc] init]; 106 [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}} 107} 108 109void testNilArgNSMutableArray5() { 110 NSMutableArray *marray = [[NSMutableArray alloc] init]; 111 marray[1] = 0; // expected-warning {{Array element cannot be nil}} 112} 113 114// NSArray API 115void testNilArgNSArray1() { 116 NSArray *array = [[NSArray alloc] init]; 117 NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}} 118} 119 120// NSMutableDictionary and NSDictionary APIs. 121void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { 122 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}} 123} 124 125void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { 126 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}} 127} 128 129void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { 130 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}} 131} 132 133void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { 134 d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}} 135} 136void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) { 137 if (key) 138 ; 139 d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}} 140 // expected-warning@-1 {{Value stored into 'NSMutableDictionary' cannot be nil}} 141} 142 143NSDictionary *testNilArgNSDictionary1(NSString* key) { 144 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}} 145} 146NSDictionary *testNilArgNSDictionary2(NSObject *obj) { 147 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}} 148} 149 150// Test inline defensive checks suppression. 151void idc(id x) { 152 if (x) 153 ; 154} 155void testIDC(NSMutableDictionary *d, NSString *key) { 156 idc(key); 157 d[key] = @"abc"; // no-warning 158} 159 160@interface Foo { 161@public 162 int x; 163} 164- (int *)getPtr; 165- (int)getInt; 166- (NSMutableDictionary *)getDictPtr; 167@property (retain, readonly, nonatomic) Foo* data; 168- (NSString*) stringForKeyFE: (id<NSCopying>)key; 169@end 170 171void idc2(id x) { 172 if (!x) 173 return; 174} 175Foo *retNil() { 176 return 0; 177} 178 179void testIDC2(Foo *obj) { 180 idc2(obj); 181 *[obj getPtr] = 1; // no-warning 182} 183 184int testIDC3(Foo *obj) { 185 idc2(obj); 186 return 1/[obj getInt]; 187} 188 189void testNilReceiverIDC(Foo *obj, NSString *key) { 190 NSMutableDictionary *D = [obj getDictPtr]; 191 idc(D); 192 D[key] = @"abc"; // no-warning 193} 194 195void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) { 196 NSString* const kKeyIdentifier = @"key"; 197 Foo *FooPtr = retNil(); 198 NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier]; 199 // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an 200 // inlined function, so this error report should be suppressed. 201 [D setObject: value forKey: key]; // no-warning 202} 203 204void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object, 205 id InValue) { 206 id Value = Object ? [Table objectForKey:Object] : [NSNull null]; 207 if (!Value) { 208 Value = InValue; 209 [Table setObject:Value forKey:Object]; // no warning 210 } 211} 212 213 214