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