369 lines · plain
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 %s5 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 NSObject15@end16@protocol NSCopying17- (id)copyWithZone:(NSZone *)zone;18@end19@protocol NSMutableCopying20- (id)mutableCopyWithZone:(NSZone *)zone;21@end22@protocol NSCoding23- (void)encodeWithCoder:(NSCoder *)aCoder;24@end25@protocol NSSecureCoding <NSCoding>26@required27+ (BOOL)supportsSecureCoding;28@end29@interface NSObject <NSObject> {}30- (id)init;31+ (id)alloc;32 33- (id)mutableCopy;34@end35 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 NSFastEnumeration43- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained _Nullable [_Nonnull])buffer count:(NSUInteger)len;44@end45 46@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>47- (NSUInteger)count;48- (id)objectAtIndex:(NSUInteger)index;49@end50 51@interface NSArray (NSExtendedArray)52- (NSArray *)arrayByAddingObject:(id)anObject;53- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));54@end55 56@interface NSArray (NSArrayCreation)57+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;58@end59 60@interface NSMutableArray : NSArray61 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@end69 70@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>71 72- (NSUInteger)count;73- (id)objectForKey:(id)aKey;74- (NSEnumerator *)keyEnumerator;75 76@end77 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@end85 86@interface NSMutableDictionary : NSDictionary87 88- (void)removeObjectForKey:(id)aKey;89- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;90 91@end92 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@end102 103@interface NSOrderedSet : NSObject <NSFastEnumeration>104@end105@interface NSOrderedSet (NSOrderedSetCreation)106- (NSUInteger)count;107@end108 109@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>110 111@end112 113@interface NSNull : NSObject <NSCopying, NSSecureCoding>114+ (NSNull *)null;115@end116 117// NSMutableArray API118void 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 API144void 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 key164}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-warning213}214 215@interface Foo {216@public217 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@end225 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-warning237}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-warning248}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 an255 // inlined function, so this error report should be suppressed.256 [D setObject: value forKey: key]; // no-warning257}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 warning265 }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 warning275 }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 warning285 }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@end296 297void testArrayCategory(NSMutableArray *arr) {298 [arr addObject:0 safe:1]; // no-warning299}300 301@interface MyView : NSObject302-(NSArray *)subviews;303@end304 305void testNoReportWhenReceiverNil(NSMutableArray *array, int b) {306 // Don't warn about adding nil to a container when the receiver is also307 // definitely nil.308 if (array == 0) {309 [array addObject:0]; // no-warning310 }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 warning315 // here either.316 [subviews addObject:view]; // no-warning317}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 indication326 // that 'obj' can be nil in this context.327 dict[obj] = getStringFromString(obj); // no-warning328}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-warning344 (void)@{@"abc" : p2}; // no-warning345 (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-warning362 (void)@[p2]; // no-warning363 (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