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