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
2
3void clang_analyzer_eval(int);
4
5#define nil ((id)0)
6
7typedef unsigned long NSUInteger;
8typedef signed char BOOL;
9typedef struct _NSZone NSZone;
10@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator;
11@protocol NSObject
12@end
13@protocol NSCopying
14- (id)copyWithZone:(NSZone *)zone;
15@end
16@protocol NSMutableCopying
17- (id)mutableCopyWithZone:(NSZone *)zone;
18@end
19@protocol NSCoding
20- (void)encodeWithCoder:(NSCoder *)aCoder;
21@end
22@protocol NSSecureCoding <NSCoding>
23@required
24+ (BOOL)supportsSecureCoding;
25@end
26@interface NSObject <NSObject> {}
27- (id)init;
28+ (id)alloc;
29
30- (id)mutableCopy;
31@end
32
33typedef struct {
34  unsigned long state;
35  id *itemsPtr;
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;
41@end
42
43@interface NSArray : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
44- (NSUInteger)count;
45- (id)objectAtIndex:(NSUInteger)index;
46@end
47
48@interface NSArray (NSExtendedArray)
49- (NSArray *)arrayByAddingObject:(id)anObject;
50- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx __attribute__((availability(macosx,introduced=10.8)));
51@end
52
53@interface NSArray (NSArrayCreation)
54+ (instancetype)arrayWithObjects:(const id [])objects count:(NSUInteger)cnt;
55@end
56
57@interface NSMutableArray : NSArray
58
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;
64
65@end
66
67@interface NSDictionary : NSObject <NSCopying, NSMutableCopying, NSSecureCoding, NSFastEnumeration>
68
69- (NSUInteger)count;
70- (id)objectForKey:(id)aKey;
71- (NSEnumerator *)keyEnumerator;
72
73@end
74
75@interface NSDictionary (NSDictionaryCreation)
76
77+ (id)dictionary;
78+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
79+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
80
81@end
82
83@interface NSMutableDictionary : NSDictionary
84
85- (void)removeObjectForKey:(id)aKey;
86- (void)setObject:(id)anObject forKey:(id <NSCopying>)aKey;
87
88@end
89
90@interface NSMutableDictionary (NSExtendedMutableDictionary)
91
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)));
97
98@end
99
100@interface NSOrderedSet : NSObject <NSFastEnumeration>
101@end
102@interface NSOrderedSet (NSOrderedSetCreation)
103- (NSUInteger)count;
104@end
105
106@interface NSString : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
107
108@end
109
110@interface NSNull : NSObject <NSCopying, NSSecureCoding>
111+ (NSNull *)null;
112@end
113
114// NSMutableArray API
115void testNilArgNSMutableArray1() {
116  NSMutableArray *marray = [[NSMutableArray alloc] init];
117  [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}}
118}
119
120void testNilArgNSMutableArray2() {
121  NSMutableArray *marray = [[NSMutableArray alloc] init];
122  [marray insertObject:0 atIndex:1]; // expected-warning {{Argument to 'NSMutableArray' method 'insertObject:atIndex:' cannot be nil}}
123}
124
125void testNilArgNSMutableArray3() {
126  NSMutableArray *marray = [[NSMutableArray alloc] init];
127  [marray replaceObjectAtIndex:1 withObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'replaceObjectAtIndex:withObject:' cannot be nil}}
128}
129
130void testNilArgNSMutableArray4() {
131  NSMutableArray *marray = [[NSMutableArray alloc] init];
132  [marray setObject:0 atIndexedSubscript:1]; // expected-warning {{Argument to 'NSMutableArray' method 'setObject:atIndexedSubscript:' cannot be nil}}
133}
134
135void testNilArgNSMutableArray5() {
136  NSMutableArray *marray = [[NSMutableArray alloc] init];
137  marray[1] = 0; // expected-warning {{Array element cannot be nil}}
138}
139
140// NSArray API
141void testNilArgNSArray1() {
142  NSArray *array = [[NSArray alloc] init];
143  NSArray *copyArray = [array arrayByAddingObject:0]; // expected-warning {{Argument to 'NSArray' method 'arrayByAddingObject:' cannot be nil}}
144}
145
146// NSMutableDictionary and NSDictionary APIs.
147void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) {
148  [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}}
149}
150
151void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) {
152  [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
153}
154
155void testNilArgNSMutableDictionary3(NSMutableDictionary *d) {
156  [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}}
157}
158
159void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) {
160  d[key] = 0; // no-warning - removing the mapping for the given key
161}
162void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) {
163  if (key)
164    ;
165  d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}}
166}
167
168NSDictionary *testNilArgNSDictionary1(NSString* key) {
169  return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}}
170}
171NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
172  return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
173}
174
175id testCreateDictionaryLiteralKey(id value, id nilKey) {
176  if (nilKey)
177    ;
178  return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
179}
180
181id testCreateDictionaryLiteralValue(id nilValue) {
182  if (nilValue)
183    ;
184  return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
185}
186
187id testCreateDictionaryLiteral(id nilValue, id nilKey) {
188  if (nilValue)
189    ;
190  if (nilKey)
191    ;
192  return @{@"abc":nilValue, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
193                                            // expected-warning@-1 {{Dictionary value cannot be nil}}
194}
195
196id testCreateArrayLiteral(id myNil) {
197  if (myNil)
198    ;
199  return @[ @"a", myNil, @"c" ]; // expected-warning {{Array element cannot be nil}}
200}
201
202// Test inline defensive checks suppression.
203void idc(id x) {
204  if (x)
205    ;
206}
207void testIDC(NSMutableDictionary *d, NSString *key) {
208  idc(key);
209  d[key] = @"abc"; // no-warning
210}
211
212@interface Foo {
213@public
214  int x;
215}
216- (int *)getPtr;
217- (int)getInt;
218- (NSMutableDictionary *)getDictPtr;
219@property (retain, readonly, nonatomic) Foo* data;
220- (NSString*) stringForKeyFE: (id<NSCopying>)key;
221@end
222
223void idc2(id x) {
224	if (!x)
225		return;
226}
227Foo *retNil() {
228  return 0;
229}
230
231void testIDC2(Foo *obj) {
232	idc2(obj);
233	*[obj getPtr] = 1; // no-warning
234}
235
236int testIDC3(Foo *obj) {
237	idc2(obj);
238  return 1/[obj getInt];
239}
240
241void testNilReceiverIDC(Foo *obj, NSString *key) {
242	NSMutableDictionary *D = [obj getDictPtr];
243  idc(D);
244  D[key] = @"abc"; // no-warning
245}
246
247void 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
254}
255
256void testAssumeNSNullNullReturnsNonNil(NSMutableDictionary *Table, id Object,
257                                      id InValue) {
258  id Value = Object ? [Table objectForKey:Object] : [NSNull null];
259  if (!Value) {
260    Value = InValue;
261    [Table setObject:Value forKey:Object]; // no warning
262  }
263}
264
265void testCollectionIsNotEmptyWhenCountIsGreaterThanZero(NSMutableDictionary *D){
266  if ([D count] > 0) { // Count is greater than zero.
267    NSString *s = 0;
268    for (NSString *key in D) {
269      s = key;       // Loop is always entered.
270    }
271    [D removeObjectForKey:s]; // no warning
272  }
273}
274
275void testCountAwareNSOrderedSet(NSOrderedSet *containers, int *validptr) {
276	int *x = 0;
277  NSUInteger containerCount = [containers count];
278  if (containerCount > 0)
279		x = validptr;
280	for (id c in containers) {
281		*x = 1; // no warning
282	}
283}
284
285void testLiteralsNonNil() {
286  clang_analyzer_eval(!!@[]); // expected-warning{{TRUE}}
287  clang_analyzer_eval(!!@{}); // expected-warning{{TRUE}}
288}
289
290@interface NSMutableArray (MySafeAdd)
291- (void)addObject:(id)obj safe:(BOOL)safe;
292@end
293
294void testArrayCategory(NSMutableArray *arr) {
295  [arr addObject:0 safe:1]; // no-warning
296}
297
298@interface MyView : NSObject
299-(NSArray *)subviews;
300@end
301
302void testNoReportWhenReceiverNil(NSMutableArray *array, int b) {
303  // Don't warn about adding nil to a container when the receiver is also
304  // definitely nil.
305  if (array == 0) {
306    [array addObject:0]; // no-warning
307  }
308
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
312  // here either.
313  [subviews addObject:view]; // no-warning
314}
315
316NSString *getStringFromString(NSString *string) {
317  if (!string)
318    return nil;
319  return @"New String";
320}
321void 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
325}
326