NSContainers.m revision b834a78f9b79cb71b093ebbbb381b92f9d4bbf3b
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 NSArray (NSArrayCreation) 40+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; 41@end 42 43@interface NSMutableArray : NSArray 44 45- (void)addObject:(id)anObject; 46- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 47- (void)removeLastObject; 48- (void)removeObjectAtIndex:(NSUInteger)index; 49- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 50 51@end 52 53@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 54 55- (NSUInteger)count; 56- (id)objectForKey:(id)aKey; 57- (NSEnumerator *)keyEnumerator; 58 59@end 60 61@interface NSDictionary (NSDictionaryCreation) 62 63+ (id)dictionary; 64+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key; 65+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt; 66 67@end 68 69@interface NSMutableDictionary : NSDictionary 70 71- (void)removeObjectForKey:(id)aKey; 72- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey; 73 74@end 75 76@interface NSMutableDictionary (NSExtendedMutableDictionary) 77 78- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; 79- (void)removeAllObjects; 80- (void)removeObjectsForKeys:(NSArray *)keyArray; 81- (void)setDictionary:(NSDictionary *)otherDictionary; 82- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8))); 83 84@end 85 86@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> 87 88@end 89 90@interface NSNull : NSObject <NSCopying, NSSecureCoding> 91+ (NSNull *)null; 92@end 93 94// NSMutableArray API 95void testNilArgNSMutableArray1() { 96 NSMutableArray *marray = [[NSMutableArray alloc] init]; 97 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} 98} 99 100void testNilArgNSMutableArray2() { 101 NSMutableArray *marray = [[NSMutableArray alloc] init]; 102 [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}} 103} 104 105void testNilArgNSMutableArray3() { 106 NSMutableArray *marray = [[NSMutableArray alloc] init]; 107 [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}} 108} 109 110void testNilArgNSMutableArray4() { 111 NSMutableArray *marray = [[NSMutableArray alloc] init]; 112 [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}} 113} 114 115void testNilArgNSMutableArray5() { 116 NSMutableArray *marray = [[NSMutableArray alloc] init]; 117 marray[1] = 0; // expected-warning {{Array element cannot be nil}} 118} 119 120// NSArray API 121void testNilArgNSArray1() { 122 NSArray *array = [[NSArray alloc] init]; 123 NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}} 124} 125 126// NSMutableDictionary and NSDictionary APIs. 127void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { 128 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}} 129} 130 131void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { 132 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}} 133} 134 135void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { 136 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}} 137} 138 139void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { 140 d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}} 141} 142void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) { 143 if (key) 144 ; 145 d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}} 146 // expected-warning@-1 {{Value stored into 'NSMutableDictionary' cannot be nil}} 147} 148 149NSDictionary *testNilArgNSDictionary1(NSString* key) { 150 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}} 151} 152NSDictionary *testNilArgNSDictionary2(NSObject *obj) { 153 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}} 154} 155 156id testCreateDictionaryLiteralKey(id value, id nilKey) { 157 if (nilKey) 158 ; 159 return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 160} 161 162id testCreateDictionaryLiteralValue(id nilValue) { 163 if (nilValue) 164 ; 165 return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}} 166} 167 168id testCreateDictionaryLiteral(id nilValue, id nilKey) { 169 if (nilValue) 170 ; 171 if (nilKey) 172 ; 173 return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 174 // expected-warning@-1 {{Dictionary value cannot be nil}} 175} 176 177id testCreateArrayLiteral(id myNil) { 178 if (myNil) 179 ; 180 return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}} 181} 182 183// Test inline defensive checks suppression. 184void idc(id x) { 185 if (x) 186 ; 187} 188void testIDC(NSMutableDictionary *d, NSString *key) { 189 idc(key); 190 d[key] = @"abc"; // no-warning 191} 192 193@interface Foo { 194@public 195 int x; 196} 197- (int *)getPtr; 198- (int)getInt; 199- (NSMutableDictionary *)getDictPtr; 200@property (retain, readonly, nonatomic) Foo* data; 201- (NSString*) stringForKeyFE: (id<NSCopying>)key; 202@end 203 204void idc2(id x) { 205 if (!x) 206 return; 207} 208Foo *retNil() { 209 return 0; 210} 211 212void testIDC2(Foo *obj) { 213 idc2(obj); 214 *[obj getPtr] = 1; // no-warning 215} 216 217int testIDC3(Foo *obj) { 218 idc2(obj); 219 return 1/[obj getInt]; 220} 221 222void testNilReceiverIDC(Foo *obj, NSString *key) { 223 NSMutableDictionary *D = [obj getDictPtr]; 224 idc(D); 225 D[key] = @"abc"; // no-warning 226} 227 228void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) { 229 NSString* const kKeyIdentifier = @"key"; 230 Foo *FooPtr = retNil(); 231 NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier]; 232 // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an 233 // inlined function, so this error report should be suppressed. 234 [D setObject: value forKey: key]; // no-warning 235} 236 237void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object, 238 id InValue) { 239 id Value = Object ? [Table objectForKey:Object] : [NSNull null]; 240 if (!Value) { 241 Value = InValue; 242 [Table setObject:Value forKey:Object]; // no warning 243 } 244} 245 246 247