NSContainers.m revision 741c5411f491a12cd965c9f5ebdff742eddbdc79
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops -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 NSSecureCoding <NSCoding> 18@required 19+ (BOOL)supportsSecureCoding; 20@end 21@interface NSObject <NSObject> {} 22- (id)init; 23+ (id)alloc; 24@end 25 26typedef struct { 27 unsigned long state; 28 id *itemsPtr; 29 unsigned long *mutationsPtr; 30 unsigned long extra[5]; 31} NSFastEnumerationState; 32@protocol NSFastEnumeration 33- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len; 34@end 35 36@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 37- (NSUInteger)count; 38- (id)objectAtIndex:(NSUInteger)index; 39@end 40 41@interface NSArray (NSExtendedArray) 42- (NSArray *)arrayByAddingObject:(id)anObject; 43- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8))); 44@end 45 46@interface NSArray (NSArrayCreation) 47+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt; 48@end 49 50@interface NSMutableArray : NSArray 51 52- (void)addObject:(id)anObject; 53- (void)insertObject:(id)anObject atIndex:(NSUInteger)index; 54- (void)removeLastObject; 55- (void)removeObjectAtIndex:(NSUInteger)index; 56- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject; 57 58@end 59 60@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration> 61 62- (NSUInteger)count; 63- (id)objectForKey:(id)aKey; 64- (NSEnumerator *)keyEnumerator; 65 66@end 67 68@interface NSDictionary (NSDictionaryCreation) 69 70+ (id)dictionary; 71+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key; 72+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt; 73 74@end 75 76@interface NSMutableDictionary : NSDictionary 77 78- (void)removeObjectForKey:(id)aKey; 79- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey; 80 81@end 82 83@interface NSMutableDictionary (NSExtendedMutableDictionary) 84 85- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary; 86- (void)removeAllObjects; 87- (void)removeObjectsForKeys:(NSArray *)keyArray; 88- (void)setDictionary:(NSDictionary *)otherDictionary; 89- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8))); 90 91@end 92 93@interface NSOrderedSet : NSObject <NSFastEnumeration> 94@end 95@interface NSOrderedSet (NSOrderedSetCreation) 96- (NSUInteger)count; 97@end 98 99@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding> 100 101@end 102 103@interface NSNull : NSObject <NSCopying, NSSecureCoding> 104+ (NSNull *)null; 105@end 106 107// NSMutableArray API 108void testNilArgNSMutableArray1() { 109 NSMutableArray *marray = [[NSMutableArray alloc] init]; 110 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} 111} 112 113void testNilArgNSMutableArray2() { 114 NSMutableArray *marray = [[NSMutableArray alloc] init]; 115 [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}} 116} 117 118void testNilArgNSMutableArray3() { 119 NSMutableArray *marray = [[NSMutableArray alloc] init]; 120 [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}} 121} 122 123void testNilArgNSMutableArray4() { 124 NSMutableArray *marray = [[NSMutableArray alloc] init]; 125 [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}} 126} 127 128void testNilArgNSMutableArray5() { 129 NSMutableArray *marray = [[NSMutableArray alloc] init]; 130 marray[1] = 0; // expected-warning {{Array element cannot be nil}} 131} 132 133// NSArray API 134void testNilArgNSArray1() { 135 NSArray *array = [[NSArray alloc] init]; 136 NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}} 137} 138 139// NSMutableDictionary and NSDictionary APIs. 140void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { 141 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}} 142} 143 144void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { 145 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}} 146} 147 148void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { 149 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}} 150} 151 152void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { 153 d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}} 154} 155void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) { 156 if (key) 157 ; 158 d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}} 159 // expected-warning@-1 {{Value stored into 'NSMutableDictionary' cannot be nil}} 160} 161 162NSDictionary *testNilArgNSDictionary1(NSString* key) { 163 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}} 164} 165NSDictionary *testNilArgNSDictionary2(NSObject *obj) { 166 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}} 167} 168 169id testCreateDictionaryLiteralKey(id value, id nilKey) { 170 if (nilKey) 171 ; 172 return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 173} 174 175id testCreateDictionaryLiteralValue(id nilValue) { 176 if (nilValue) 177 ; 178 return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}} 179} 180 181id testCreateDictionaryLiteral(id nilValue, id nilKey) { 182 if (nilValue) 183 ; 184 if (nilKey) 185 ; 186 return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 187 // expected-warning@-1 {{Dictionary value cannot be nil}} 188} 189 190id testCreateArrayLiteral(id myNil) { 191 if (myNil) 192 ; 193 return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}} 194} 195 196// Test inline defensive checks suppression. 197void idc(id x) { 198 if (x) 199 ; 200} 201void testIDC(NSMutableDictionary *d, NSString *key) { 202 idc(key); 203 d[key] = @"abc"; // no-warning 204} 205 206@interface Foo { 207@public 208 int x; 209} 210- (int *)getPtr; 211- (int)getInt; 212- (NSMutableDictionary *)getDictPtr; 213@property (retain, readonly, nonatomic) Foo* data; 214- (NSString*) stringForKeyFE: (id<NSCopying>)key; 215@end 216 217void idc2(id x) { 218 if (!x) 219 return; 220} 221Foo *retNil() { 222 return 0; 223} 224 225void testIDC2(Foo *obj) { 226 idc2(obj); 227 *[obj getPtr] = 1; // no-warning 228} 229 230int testIDC3(Foo *obj) { 231 idc2(obj); 232 return 1/[obj getInt]; 233} 234 235void testNilReceiverIDC(Foo *obj, NSString *key) { 236 NSMutableDictionary *D = [obj getDictPtr]; 237 idc(D); 238 D[key] = @"abc"; // no-warning 239} 240 241void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) { 242 NSString* const kKeyIdentifier = @"key"; 243 Foo *FooPtr = retNil(); 244 NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier]; 245 // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an 246 // inlined function, so this error report should be suppressed. 247 [D setObject: value forKey: key]; // no-warning 248} 249 250void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object, 251 id InValue) { 252 id Value = Object ? [Table objectForKey:Object] : [NSNull null]; 253 if (!Value) { 254 Value = InValue; 255 [Table setObject:Value forKey:Object]; // no warning 256 } 257} 258 259void testCollectionIsNotEmptyWhenCountIsGreaterThanZero(NSMutableDictionary *D){ 260 if ([D count] > 0) { // Count is greater than zero. 261 NSString *s = 0; 262 for (NSString *key in D) { 263 s = key; // Loop is always entered. 264 } 265 [D removeObjectForKey:s]; // no warning 266 } 267} 268 269void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) { 270 int *x = 0; 271 NSUInteger containerCount = [containers count]; 272 if (containerCount > 0) 273 x = validptr; 274 for (id c in containers) { 275 *x = 1; // no warning 276 } 277} 278 279