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