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