misc-ps-eager-assume.m revision 72374594c5d9ade02451bc85cf9dfa5b0ea106e7
1// RUN: clang -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s -analyzer-eagerly-assume 2 3// Delta-reduced header stuff (needed for test cases). 4typedef signed char BOOL; 5typedef unsigned int NSUInteger; 6typedef struct _NSZone NSZone; 7@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 8@protocol NSObject - (BOOL)isEqual:(id)object; 9- (oneway void)release; 10@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; 11@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 12@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 13@end @interface NSObject <NSObject> {} 14+ (id)alloc; 15@end typedef struct {} 16NSFastEnumerationState; 17@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 18@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 19@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject; 20- (BOOL)isEqualToString:(NSString *)aString; 21@end @interface NSAutoreleasePool : NSObject {} 22- (void)drain; 23- (id)init; 24@end 25 26// This test case tests that (x != 0) is eagerly evaluated before stored to 27// 'y'. This test case complements recoverCastedSymbol (see below) because 28// the symbolic expression is stored to 'y' (which is a short instead of an 29// int). recoverCastedSymbol() only recovers path-sensitivity when the 30// symbolic expression is literally the branch condition. 31// 32void handle_assign_of_condition(int x) { 33 // The cast to 'short' causes us to lose symbolic constraint. 34 short y = (x != 0); 35 char *p = 0; 36 if (y) { 37 // This should be infeasible. 38 if (!(x != 0)) { 39 *p = 1; // no-warning 40 } 41 } 42} 43 44// From <rdar://problem/6619921> 45// 46// In this test case, 'needsAnArray' is a signed char. The analyzer tracks 47// a symbolic value for this variable, but in the branch condition it is 48// promoted to 'int'. Currently the analyzer doesn't reason well about 49// promotions of symbolic values, so this test case tests the logic in 50// 'recoverCastedSymbol()' (GRExprEngine.cpp) to test that we recover 51// path-sensitivity and use the symbol for 'needsAnArray' in the branch 52// condition. 53// 54void handle_symbolic_cast_in_condition(void) { 55 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 56 57 BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; 58 NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0; 59 if(needsAnArray) 60 [array release]; 61 62 [pool drain]; 63} 64 65// From PR 3836 (http://llvm.org/bugs/show_bug.cgi?id=3836) 66// 67// In this test case, the double '!' works fine with our symbolic constraints, 68// but we don't support comparing SymConstraint != SymConstraint. By eagerly 69// assuming the truth of !!a or !!b, we can compare these values directly. 70// 71void pr3836(int *a, int *b) { 72 if (!!a != !!b) /* one of them is NULL */ 73 return; 74 if (!a && !b) /* both are NULL */ 75 return; 76 77 *a = 1; // no-warning 78 *b = 1; // no-warning 79} 80