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