• Home
  • 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
3void clang_analyzer_eval(int);
4
5typedef unsigned long NSUInteger;
6typedef signed char BOOL;
7typedef 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
31typedef 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
113void testNilArgNSMutableArray1() {
114  NSMutableArray *marray = [[NSMutableArray alloc] init];
115  [marray addObject:0]; // expected-warning {{Argument to 'NSMutableArray' method 'addObject:' cannot be nil}}
116}
117
118void 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
123void 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
128void 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
133void testNilArgNSMutableArray5() {
134  NSMutableArray *marray = [[NSMutableArray alloc] init];
135  marray[1] = 0; // expected-warning {{Array element cannot be nil}}
136}
137
138// NSArray API
139void 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.
145void testNilArgNSMutableDictionary1(NSMutableDictionary *d, NSString* key) {
146  [d setObject:0 forKey:key]; // expected-warning {{Value argument to 'setObject:forKey:' cannot be nil}}
147}
148
149void testNilArgNSMutableDictionary2(NSMutableDictionary *d, NSObject *obj) {
150  [d setObject:obj forKey:0]; // expected-warning {{Key argument to 'setObject:forKey:' cannot be nil}}
151}
152
153void testNilArgNSMutableDictionary3(NSMutableDictionary *d) {
154  [d removeObjectForKey:0]; // expected-warning {{Value argument to 'removeObjectForKey:' cannot be nil}}
155}
156
157void testNilArgNSMutableDictionary5(NSMutableDictionary *d, NSString* key) {
158  d[key] = 0; // no-warning - removing the mapping for the given key
159}
160void testNilArgNSMutableDictionary6(NSMutableDictionary *d, NSString *key) {
161  if (key)
162    ;
163  d[key] = 0; // expected-warning {{'NSMutableDictionary' key cannot be nil}}
164}
165
166NSDictionary *testNilArgNSDictionary1(NSString* key) {
167  return [NSDictionary dictionaryWithObject:0 forKey:key]; // expected-warning {{Value argument to 'dictionaryWithObject:forKey:' cannot be nil}}
168}
169NSDictionary *testNilArgNSDictionary2(NSObject *obj) {
170  return [NSDictionary dictionaryWithObject:obj forKey:0]; // expected-warning {{Key argument to 'dictionaryWithObject:forKey:' cannot be nil}}
171}
172
173id testCreateDictionaryLiteralKey(id value, id nilKey) {
174  if (nilKey)
175    ;
176  return @{@"abc":value, nilKey:@"abc"}; // expected-warning {{Dictionary key cannot be nil}}
177}
178
179id testCreateDictionaryLiteralValue(id nilValue) {
180  if (nilValue)
181    ;
182  return @{@"abc":nilValue}; // expected-warning {{Dictionary value cannot be nil}}
183}
184
185id 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
194id 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.
201void idc(id x) {
202  if (x)
203    ;
204}
205void 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
221void idc2(id x) {
222	if (!x)
223		return;
224}
225Foo *retNil() {
226  return 0;
227}
228
229void testIDC2(Foo *obj) {
230	idc2(obj);
231	*[obj getPtr] = 1; // no-warning
232}
233
234int testIDC3(Foo *obj) {
235	idc2(obj);
236  return 1/[obj getInt];
237}
238
239void testNilReceiverIDC(Foo *obj, NSString *key) {
240	NSMutableDictionary *D = [obj getDictPtr];
241  idc(D);
242  D[key] = @"abc"; // no-warning
243}
244
245void 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
254void 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
263void 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
273void 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
283void 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
292void testArrayCategory(NSMutableArray *arr) {
293  [arr addObject:0 safe:1]; // no-warning
294}
295
296@interface MyView : NSObject
297-(NSArray *)subviews;
298@end
299
300void 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