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 3 void clang_analyzer_eval(int); 4 5 typedef unsigned long NSUInteger; 6 typedef signed char BOOL; 7 typedef 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 29 typedef 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 111 void testNilArgNSMutableArray1() { 112 NSMutableArray *marray = [[NSMutableArray alloc] init]; 113 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} 114 } 115 116 void 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 121 void 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 126 void 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 131 void testNilArgNSMutableArray5() { 132 NSMutableArray *marray = [[NSMutableArray alloc] init]; 133 marray[1] = 0; // expected-warning {{Array element cannot be nil}} 134 } 135 136 // NSArray API 137 void 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. 143 void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { 144 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}} 145 } 146 147 void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { 148 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}} 149 } 150 151 void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { 152 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}} 153 } 154 155 void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { 156 d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}} 157 } 158 void 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 165 NSDictionary *testNilArgNSDictionary1(NSString* key) { 166 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}} 167 } 168 NSDictionary *testNilArgNSDictionary2(NSObject *obj) { 169 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}} 170 } 171 172 id testCreateDictionaryLiteralKey(id value, id nilKey) { 173 if (nilKey) 174 ; 175 return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 176 } 177 178 id testCreateDictionaryLiteralValue(id nilValue) { 179 if (nilValue) 180 ; 181 return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}} 182 } 183 184 id 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 193 id 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. 200 void idc(id x) { 201 if (x) 202 ; 203 } 204 void 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 220 void idc2(id x) { 221 if (!x) 222 return; 223 } 224 Foo *retNil() { 225 return 0; 226 } 227 228 void testIDC2(Foo *obj) { 229 idc2(obj); 230 *[obj getPtr] = 1; // no-warning 231 } 232 233 int testIDC3(Foo *obj) { 234 idc2(obj); 235 return 1/[obj getInt]; 236 } 237 238 void testNilReceiverIDC(Foo *obj, NSString *key) { 239 NSMutableDictionary *D = [obj getDictPtr]; 240 idc(D); 241 D[key] = @"abc"; // no-warning 242 } 243 244 void 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 253 void 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 262 void 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 272 void 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 282 void 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 291 void testArrayCategory(NSMutableArray *arr) { 292 [arr addObject:0 safe:1]; // no-warning 293 } 294 295