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