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
3 void clang_analyzer_eval(int);
7 typedef unsigned long NSUInteger;
8 typedef signed char BOOL;
9 typedef struct _NSZone NSZone;
10 @class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
14 - (id)copyWithZone:(NSZone *)zone;
16 @protocol NSMutableCopying
17 - (id)mutableCopyWithZone:(NSZone *)zone;
20 - (void)encodeWithCoder:(NSCoder *)aCoder;
22 @protocol NSSecureCoding <NSCoding>
24 + (BOOL)supportsSecureCoding;
26 @interface NSObject <NSObject> {}
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;
43 @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
45 - (id)objectAtIndex:(NSUInteger)index;
48 @interface NSArray (NSExtendedArray)
49 - (NSArray *)arrayByAddingObject:(id)anObject;
50 - (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
53 @interface NSArray (NSArrayCreation)
54 + (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
57 @interface NSMutableArray : NSArray
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;
67 @interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
70 - (id)objectForKey:(id)aKey;
71 - (NSEnumerator *)keyEnumerator;
75 @interface NSDictionary (NSDictionaryCreation)
78 + (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
79 + (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
83 @interface NSMutableDictionary : NSDictionary
85 - (void)removeObjectForKey:(id)aKey;
86 - (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
90 @interface NSMutableDictionary (NSExtendedMutableDictionary)
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)));
100 @interface NSOrderedSet : NSObject <NSFastEnumeration>
102 @interface NSOrderedSet (NSOrderedSetCreation)
106 @interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
110 @interface NSNull : NSObject <NSCopying, NSSecureCoding>
114 // NSMutableArray API
115 void testNilArgNSMutableArray1(void) {
116 NSMutableArray *marray = [[NSMutableArray alloc] init];
117 [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}}
120 void testNilArgNSMutableArray2(void) {
121 NSMutableArray *marray = [[NSMutableArray alloc] init];
122 [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}}
125 void testNilArgNSMutableArray3(void) {
126 NSMutableArray *marray = [[NSMutableArray alloc] init];
127 [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}}
130 void testNilArgNSMutableArray4(void) {
131 NSMutableArray *marray = [[NSMutableArray alloc] init];
132 [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}}
135 void testNilArgNSMutableArray5(void) {
136 NSMutableArray *marray = [[NSMutableArray alloc] init];
137 marray[1] = 0; // expected-warning {{Array element cannot be nil}}
141 void testNilArgNSArray1(void) {
142 NSArray *array = [[NSArray alloc] init];
143 NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}}
146 // NSMutableDictionary and NSDictionary APIs.
147 void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) {
148 [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}}
151 void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) {
152 [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
155 void testNilArgNSMutableDictionary3(NSMutableDictionary *d) {
156 [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}}
159 void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) {
160 d[key] = 0; // no-warning - removing the mapping for the given key
162 void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) {
165 d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}}
168 NSDictionary *testNilArgNSDictionary1(NSString* key) {
169 return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}}
171 NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
172 return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
175 id testCreateDictionaryLiteralKey(id value, id nilKey) {
178 return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
181 id testCreateDictionaryLiteralValue(id nilValue) {
184 return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
187 id testCreateDictionaryLiteral(id nilValue, id nilKey) {
192 return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
193 // expected-warning@-1 {{Dictionary value cannot be nil}}
196 id testCreateArrayLiteral(id myNil) {
199 return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
202 // Test inline defensive checks suppression.
207 void testIDC(NSMutableDictionary *d, NSString *key) {
209 d[key] = @"abc"; // no-warning
218 - (NSMutableDictionary *)getDictPtr;
219 @property (retain, readonly, nonatomic) Foo* data;
220 - (NSString*) stringForKeyFE: (id<NSCopying>)key;
231 void testIDC2(Foo *obj) {
233 *[obj getPtr] = 1; // no-warning
236 int testIDC3(Foo *obj) {
238 return 1/[obj getInt];
241 void testNilReceiverIDC(Foo *obj, NSString *key) {
242 NSMutableDictionary *D = [obj getDictPtr];
244 D[key] = @"abc"; // no-warning
247 void 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
256 void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object,
258 id Value = Object ? [Table objectForKey:Object] : [NSNull null];
261 [Table setObject:Value forKey:Object]; // no warning
265 void testCollectionIsNotEmptyWhenCountIsGreaterThanZero(NSMutableDictionary *D){
266 if ([D count] > 0) { // Count is greater than zero.
268 for (NSString *key in D) {
269 s = key; // Loop is always entered.
271 [D removeObjectForKey:s]; // no warning
275 void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) {
277 NSUInteger containerCount = [containers count];
278 if (containerCount > 0)
280 for (id c in containers) {
281 *x = 1; // no warning
285 void testLiteralsNonNil(void) {
286 clang_analyzer_eval(!!@[]); // expected-warning{{TRUE}}
287 clang_analyzer_eval(!!@{}); // expected-warning{{TRUE}}
290 @interface NSMutableArray (MySafeAdd)
291 - (void)addObject:(id)obj safe:(BOOL)safe;
294 void testArrayCategory(NSMutableArray *arr) {
295 [arr addObject:0 safe:1]; // no-warning
298 @interface MyView : NSObject
299 -(NSArray *)subviews;
302 void testNoReportWhenReceiverNil(NSMutableArray *array, int b) {
303 // Don't warn about adding nil to a container when the receiver is also
306 [array addObject:0]; // no-warning
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
313 [subviews addObject:view]; // no-warning
316 NSString *getStringFromString(NSString *string) {
319 return @"New String";
321 void 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