blob: 2f14b8ad1aaeecbb901dd805e04758cea9db04dc [file] [log] [blame]
Jordan Rose5d2e4e12013-04-26 21:43:01 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,osx.cocoa.Loops,debug.ExprInspection -verify %s
Jordan Rose1895a0a2012-06-11 16:40:41 +00002
3void clang_analyzer_eval(int);
4
5#define nil ((id)0)
6
Anna Zaks2ffcd182013-06-22 00:23:26 +00007typedef unsigned long NSUInteger;
Jordan Rose1895a0a2012-06-11 16:40:41 +00008@protocol NSFastEnumeration
9- (int)countByEnumeratingWithState:(void *)state objects:(id *)objects count:(unsigned)count;
Jordan Rose219103d2013-11-08 01:15:35 +000010- (void)protocolMethod;
Jordan Rose1895a0a2012-06-11 16:40:41 +000011@end
12
13@interface NSObject
14+ (instancetype)testObject;
15@end
16
17@interface NSEnumerator <NSFastEnumeration>
18@end
19
20@interface NSArray : NSObject <NSFastEnumeration>
Anna Zaks2ffcd182013-06-22 00:23:26 +000021- (NSUInteger)count;
Jordan Rose1895a0a2012-06-11 16:40:41 +000022- (NSEnumerator *)objectEnumerator;
23@end
24
25@interface NSDictionary : NSObject <NSFastEnumeration>
Anna Zaks2ffcd182013-06-22 00:23:26 +000026- (NSUInteger)count;
Jordan Rose219103d2013-11-08 01:15:35 +000027- (id)objectForKey:(id)key;
28@end
29
30@interface NSDictionary (SomeCategory)
31- (void)categoryMethodOnNSDictionary;
Jordan Rose1895a0a2012-06-11 16:40:41 +000032@end
33
34@interface NSMutableDictionary : NSDictionary
Jordan Rose219103d2013-11-08 01:15:35 +000035- (void)setObject:(id)obj forKey:(id)key;
36@end
37
38@interface NSMutableArray : NSArray
39- (void)addObject:(id)obj;
Jordan Rose1895a0a2012-06-11 16:40:41 +000040@end
41
42@interface NSSet : NSObject <NSFastEnumeration>
Anna Zaks2ffcd182013-06-22 00:23:26 +000043- (NSUInteger)count;
Jordan Rose1895a0a2012-06-11 16:40:41 +000044@end
45
46@interface NSPointerArray : NSObject <NSFastEnumeration>
47@end
48
Anna Zaks2ffcd182013-06-22 00:23:26 +000049@interface NSString : NSObject
50@end
51
Jordan Rose1895a0a2012-06-11 16:40:41 +000052void test() {
53 id x;
54 for (x in [NSArray testObject])
55 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
56
57 for (x in [NSMutableDictionary testObject])
58 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
59
60 for (x in [NSSet testObject])
61 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
62
63 for (x in [[NSArray testObject] objectEnumerator])
64 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
65
66 for (x in [NSPointerArray testObject])
67 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}
68}
69
70void testWithVarInFor() {
71 for (id x in [NSArray testObject])
72 clang_analyzer_eval(x != nil); // expected-warning{{TRUE}}
73 for (id x in [NSPointerArray testObject])
74 clang_analyzer_eval(x != nil); // expected-warning{{UNKNOWN}}
75}
76
Jordan Rose5d2e4e12013-04-26 21:43:01 +000077void testNonNil(id a, id b) {
78 clang_analyzer_eval(a != nil); // expected-warning{{UNKNOWN}}
79 for (id x in a)
80 clang_analyzer_eval(a != nil); // expected-warning{{TRUE}}
81
82 if (b != nil)
83 return;
84 for (id x in b)
85 *(volatile int *)0 = 1; // no-warning
86 clang_analyzer_eval(b != nil); // expected-warning{{FALSE}}
87}
88
Anna Zaks2ffcd182013-06-22 00:23:26 +000089void collectionIsEmpty(NSMutableDictionary *D){
90 if ([D count] == 0) { // Count is zero.
91 NSString *s = 0;
92 for (NSString *key in D) {
93 s = key; // Loop is never entered.
94 }
95 clang_analyzer_eval(s == 0); //expected-warning{{TRUE}}
96 }
97}
98
99void processCollection(NSMutableDictionary *D);
100void collectionIsEmptyCollectionIsModified(NSMutableDictionary *D){
101 if ([D count] == 0) { // Count is zero.
102 NSString *s = 0;
103 processCollection(D); // However, the collection has changed.
104 for (NSString *key in D) {
105 s = key; // Loop might be entered.
106 }
107 clang_analyzer_eval(s == 0); //expected-warning{{FALSE}} //expected-warning{{TRUE}}
108 }
109}
110
111int collectionIsEmptyNSSet(NSSet *S){
112 if ([S count] == 2) { // Count is non zero.
113 int tapCounts[2];
114 int i = 0;
115 for (NSString *elem in S) {
116 tapCounts[i]= 1; // Loop is entered.
117 i++;
118 }
119 return (tapCounts[0]); //no warning
120 }
121 return 0;
122}
123
124int collectionIsNotEmptyNSArray(NSArray *A) {
125 int count = [A count];
126 if (count > 0) {
127 int i;
128 int j;
129 for (NSString *a in A) {
130 i = 1;
131 j++;
132 }
133 clang_analyzer_eval(i == 1); // expected-warning {{TRUE}}
134 }
135 return 0;
136}
137
138void onlySuppressExitAfterZeroIterations(NSMutableDictionary *D) {
139 if (D.count > 0) {
140 int *x;
141 int i;
142 for (NSString *key in D) {
143 x = 0;
144 i++;
145 }
146 // Test that this is reachable.
147 int y = *x; // expected-warning {{Dereference of null pointer}}
148 y++;
149 }
150}
151
152void onlySuppressLoopExitAfterZeroIterations_WithContinue(NSMutableDictionary *D) {
153 if (D.count > 0) {
154 int *x;
155 int i;
156 for (NSString *key in D) {
157 x = 0;
158 i++;
159 continue;
160 }
161 // Test that this is reachable.
162 int y = *x; // expected-warning {{Dereference of null pointer}}
163 y++;
164 }
165}
166
167int* getPtr();
168void onlySuppressLoopExitAfterZeroIterations_WithBreak(NSMutableDictionary *D) {
169 if (D.count > 0) {
170 int *x;
171 int i;
172 for (NSString *key in D) {
173 x = 0;
174 break;
175 x = getPtr();
176 i++;
177 }
178 int y = *x; // expected-warning {{Dereference of null pointer}}
179 y++;
180 }
181}
182
Jordan Rose219103d2013-11-08 01:15:35 +0000183int consistencyBetweenLoopsWhenCountIsUnconstrained(NSMutableDictionary *D,
184 int shouldUseCount) {
185 // Test with or without an initial count.
186 int count;
187 if (shouldUseCount)
188 count = [D count];
189
Anna Zaks2ffcd182013-06-22 00:23:26 +0000190 int i;
191 int j = 0;
192 for (NSString *key in D) {
193 i = 5;
194 j++;
195 }
196 for (NSString *key in D) {
197 return i; // no-warning
198 }
199 return 0;
200}
201
Jordan Rose219103d2013-11-08 01:15:35 +0000202int consistencyBetweenLoopsWhenCountIsUnconstrained_dual(NSMutableDictionary *D,
203 int shouldUseCount) {
204 int count;
205 if (shouldUseCount)
206 count = [D count];
207
Anna Zaks2ffcd182013-06-22 00:23:26 +0000208 int i = 8;
209 int j = 1;
210 for (NSString *key in D) {
211 i = 0;
212 j++;
213 }
214 for (NSString *key in D) {
215 i = 5;
216 j++;
217 }
218 return 5/i;
219}
Jordan Rose219103d2013-11-08 01:15:35 +0000220
221int consistencyCountThenLoop(NSArray *array) {
222 if ([array count] == 0)
223 return 0;
224
225 int x;
226 for (id y in array)
227 x = 0;
228 return x; // no-warning
229}
230
231int consistencyLoopThenCount(NSArray *array) {
232 int x;
233 for (id y in array)
234 x = 0;
235
236 if ([array count] == 0)
237 return 0;
238
239 return x; // no-warning
240}
241
242void nonMutatingMethodsDoNotInvalidateCountDictionary(NSMutableDictionary *dict,
243 NSMutableArray *other) {
244 if ([dict count])
245 return;
246
247 for (id key in dict)
248 clang_analyzer_eval(0); // no-warning
249
250 (void)[dict objectForKey:@""];
251
252 for (id key in dict)
253 clang_analyzer_eval(0); // no-warning
254
255 [dict categoryMethodOnNSDictionary];
256
257 for (id key in dict)
258 clang_analyzer_eval(0); // no-warning
259
260 [dict setObject:@"" forKey:@""];
261
262 for (id key in dict)
263 clang_analyzer_eval(0); // expected-warning{{FALSE}}
264
265 // Reset.
266 if ([dict count])
267 return;
268
269 for (id key in dict)
270 clang_analyzer_eval(0); // no-warning
271
272 [other addObject:dict];
273
274 for (id key in dict)
275 clang_analyzer_eval(0); // expected-warning{{FALSE}}
276}
277
278void nonMutatingMethodsDoNotInvalidateCountArray(NSMutableArray *array,
279 NSMutableArray *other) {
280 if ([array count])
281 return;
282
283 for (id key in array)
284 clang_analyzer_eval(0); // no-warning
285
286 (void)[array objectEnumerator];
287
288 for (id key in array)
289 clang_analyzer_eval(0); // no-warning
290
291 [array addObject:@""];
292
293 for (id key in array)
294 clang_analyzer_eval(0); // expected-warning{{FALSE}}
295
296 // Reset.
297 if ([array count])
298 return;
299
300 for (id key in array)
301 clang_analyzer_eval(0); // no-warning
302
303 [other addObject:array];
304
305 for (id key in array)
306 clang_analyzer_eval(0); // expected-warning{{FALSE}}
307}
308
309void protocolMethods(NSMutableArray *array) {
310 if ([array count])
311 return;
312
313 for (id key in array)
314 clang_analyzer_eval(0); // no-warning
315
316 NSArray *immutableArray = array;
317 [immutableArray protocolMethod];
318
319 for (id key in array)
320 clang_analyzer_eval(0); // no-warning
321
322 [array protocolMethod];
323
324 for (id key in array)
325 clang_analyzer_eval(0); // expected-warning{{FALSE}}
326}