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 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 28 - (id)mutableCopy; 29 @end 30 31 typedef 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 113 void testNilArgNSMutableArray1() { 114 NSMutableArray *marray = [[NSMutableArray alloc] init]; 115 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}} 116 } 117 118 void 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 123 void 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 128 void 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 133 void testNilArgNSMutableArray5() { 134 NSMutableArray *marray = [[NSMutableArray alloc] init]; 135 marray[1] = 0; // expected-warning {{Array element cannot be nil}} 136 } 137 138 // NSArray API 139 void 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. 145 void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) { 146 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}} 147 } 148 149 void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) { 150 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}} 151 } 152 153 void testNilArgNSMutableDictionary3(NSMutableDictionary *d) { 154 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}} 155 } 156 157 void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) { 158 d[key] = 0; // no-warning - removing the mapping for the given key 159 } 160 void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) { 161 if (key) 162 ; 163 d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}} 164 } 165 166 NSDictionary *testNilArgNSDictionary1(NSString* key) { 167 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}} 168 } 169 NSDictionary *testNilArgNSDictionary2(NSObject *obj) { 170 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}} 171 } 172 173 id testCreateDictionaryLiteralKey(id value, id nilKey) { 174 if (nilKey) 175 ; 176 return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}} 177 } 178 179 id testCreateDictionaryLiteralValue(id nilValue) { 180 if (nilValue) 181 ; 182 return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}} 183 } 184 185 id 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 194 id 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. 201 void idc(id x) { 202 if (x) 203 ; 204 } 205 void 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 221 void idc2(id x) { 222 if (!x) 223 return; 224 } 225 Foo *retNil() { 226 return 0; 227 } 228 229 void testIDC2(Foo *obj) { 230 idc2(obj); 231 *[obj getPtr] = 1; // no-warning 232 } 233 234 int testIDC3(Foo *obj) { 235 idc2(obj); 236 return 1/[obj getInt]; 237 } 238 239 void testNilReceiverIDC(Foo *obj, NSString *key) { 240 NSMutableDictionary *D = [obj getDictPtr]; 241 idc(D); 242 D[key] = @"abc"; // no-warning 243 } 244 245 void 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 254 void 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 263 void 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 273 void 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 283 void 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 292 void testArrayCategory(NSMutableArray *arr) { 293 [arr addObject:0 safe:1]; // no-warning 294 } 295 296 @interface MyView : NSObject 297 -(NSArray *)subviews; 298 @end 299 300 void 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