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