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