NSContainers.m revision 741c5411f491a12cd965c9f5ebdff742eddbdc79
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.NonNilReturnValue,osx.cocoa.NilArg,osx.cocoa.Loops -verify -Wno-objc-root-class %s
2typedef unsigned long NSUInteger;
3typedef signed char BOOL;
4typedef struct _NSZone NSZone;
5@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
6@protocol NSObject
7@end
8@protocol NSCopying
9- (id)copyWithZone:(NSZone *)zone;
10@end
11@protocol NSMutableCopying
12- (id)mutableCopyWithZone:(NSZone *)zone;
13@end
14@protocol NSCoding
15- (void)encodeWithCoder:(NSCoder *)aCoder;
16@end
17@protocol NSSecureCoding <NSCoding>
18@required
19+ (BOOL)supportsSecureCoding;
20@end
21@interface NSObject <NSObject> {}
22- (id)init;
23+ (id)alloc;
24@end
25
26typedef struct {
27  unsigned long state;
28  id *itemsPtr;
29  unsigned long *mutationsPtr;
30  unsigned long extra[5];
31} NSFastEnumerationState;
32@protocol NSFastEnumeration
33- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id [])buffer count:(NSUInteger)len;
34@end
35
36@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
37- (NSUInteger)count;
38- (id)objectAtIndex:(NSUInteger)index;
39@end
40
41@interface NSArray (NSExtendedArray)
42- (NSArray *)arrayByAddingObject:(id)anObject;
43- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
44@end
45
46@interface NSArray (NSArrayCreation)
47+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
48@end
49
50@interface NSMutableArray : NSArray
51
52- (void)addObject:(id)anObject;
53- (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
54- (void)removeLastObject;
55- (void)removeObjectAtIndex:(NSUInteger)index;
56- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(id)anObject;
57
58@end
59
60@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
61
62- (NSUInteger)count;
63- (id)objectForKey:(id)aKey;
64- (NSEnumerator *)keyEnumerator;
65
66@end
67
68@interface NSDictionary (NSDictionaryCreation)
69
70+ (id)dictionary;
71+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
72+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
73
74@end
75
76@interface NSMutableDictionary : NSDictionary
77
78- (void)removeObjectForKey:(id)aKey;
79- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
80
81@end
82
83@interface NSMutableDictionary (NSExtendedMutableDictionary)
84
85- (void)addEntriesFromDictionary:(NSDictionary *)otherDictionary;
86- (void)removeAllObjects;
87- (void)removeObjectsForKeys:(NSArray *)keyArray;
88- (void)setDictionary:(NSDictionary *)otherDictionary;
89- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key __attribute__((availability(macosx,introduced=10.8)));
90
91@end
92
93@interface NSOrderedSet : NSObject <NSFastEnumeration>
94@end
95@interface NSOrderedSet (NSOrderedSetCreation)
96- (NSUInteger)count;
97@end
98
99@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
100
101@end
102
103@interface NSNull : NSObject <NSCopying, NSSecureCoding>
104+ (NSNull *)null;
105@end
106
107// NSMutableArray API
108void testNilArgNSMutableArray1() {
109  NSMutableArray *marray = [[NSMutableArray alloc] init];
110  [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}}
111}
112
113void testNilArgNSMutableArray2() {
114  NSMutableArray *marray = [[NSMutableArray alloc] init];
115  [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}}
116}
117
118void testNilArgNSMutableArray3() {
119  NSMutableArray *marray = [[NSMutableArray alloc] init];
120  [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}}
121}
122
123void testNilArgNSMutableArray4() {
124  NSMutableArray *marray = [[NSMutableArray alloc] init];
125  [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}}
126}
127
128void testNilArgNSMutableArray5() {
129  NSMutableArray *marray = [[NSMutableArray alloc] init];
130  marray[1] = 0; // expected-warning {{Array element cannot be nil}}
131}
132
133// NSArray API
134void testNilArgNSArray1() {
135  NSArray *array = [[NSArray alloc] init];
136  NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}}
137}
138
139// NSMutableDictionary and NSDictionary APIs.
140void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) {
141  [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}}
142}
143
144void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) {
145  [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
146}
147
148void testNilArgNSMutableDictionary3(NSMutableDictionary *d) {
149  [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}}
150}
151
152void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) {
153  d[key] = 0; // expected-warning {{Value stored into 'NSMutableDictionary' cannot be nil}}
154}
155void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) {
156  if (key)
157    ;
158  d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}}
159  // expected-warning@-1 {{Value stored into 'NSMutableDictionary' cannot be nil}}
160}
161
162NSDictionary *testNilArgNSDictionary1(NSString* key) {
163  return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}}
164}
165NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
166  return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
167}
168
169id testCreateDictionaryLiteralKey(id value, id nilKey) {
170  if (nilKey)
171    ;
172  return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
173}
174
175id testCreateDictionaryLiteralValue(id nilValue) {
176  if (nilValue)
177    ;
178  return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
179}
180
181id testCreateDictionaryLiteral(id nilValue, id nilKey) {
182  if (nilValue)
183    ;
184  if (nilKey)
185    ;
186  return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
187                                            // expected-warning@-1 {{Dictionary value cannot be nil}}
188}
189
190id testCreateArrayLiteral(id myNil) {
191  if (myNil)
192    ;
193  return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
194}
195
196// Test inline defensive checks suppression.
197void idc(id x) {
198  if (x)
199    ;
200}
201void testIDC(NSMutableDictionary *d, NSString *key) {
202  idc(key);
203  d[key] = @"abc"; // no-warning
204}
205
206@interface Foo {
207@public
208  int x;
209}
210- (int *)getPtr;
211- (int)getInt;
212- (NSMutableDictionary *)getDictPtr;
213@property (retain, readonly, nonatomic) Foo* data;
214- (NSString*) stringForKeyFE: (id<NSCopying>)key;
215@end
216
217void idc2(id x) {
218	if (!x)
219		return;
220}
221Foo *retNil() {
222  return 0;
223}
224
225void testIDC2(Foo *obj) {
226	idc2(obj);
227	*[obj getPtr] = 1; // no-warning
228}
229
230int testIDC3(Foo *obj) {
231	idc2(obj);
232  return 1/[obj getInt];
233}
234
235void testNilReceiverIDC(Foo *obj, NSString *key) {
236	NSMutableDictionary *D = [obj getDictPtr];
237  idc(D);
238  D[key] = @"abc"; // no-warning
239}
240
241void testNilReceiverRetNil2(NSMutableDictionary *D, Foo *FooPtrIn, id value) {
242  NSString* const kKeyIdentifier = @"key";
243	Foo *FooPtr = retNil();
244  NSString *key = [[FooPtr data] stringForKeyFE: kKeyIdentifier];
245  // key is nil because FooPtr is nil. However, FooPtr is set to nil inside an
246  // inlined function, so this error report should be suppressed.
247  [D setObject: value forKey: key]; // no-warning
248}
249
250void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object,
251                                      id InValue) {
252  id Value = Object ? [Table objectForKey:Object] : [NSNull null];
253  if (!Value) {
254    Value = InValue;
255    [Table setObject:Value forKey:Object]; // no warning
256  }
257}
258
259void testCollectionIsNotEmptyWhenCountIsGreaterThanZero(NSMutableDictionary *D){
260  if ([D count] > 0) { // Count is greater than zero.
261    NSString *s = 0;
262    for (NSString *key in D) {
263      s = key;       // Loop is always entered.
264    }
265    [D removeObjectForKey:s]; // no warning
266  }
267}
268
269void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) {
270	int *x = 0;
271  NSUInteger containerCount = [containers count];
272  if (containerCount > 0)    
273		x = validptr;
274	for (id c in containers) {
275		*x = 1; // no warning
276	}
277}
278
279