1*f4a2713aSLionel Sambuc// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume 2*f4a2713aSLionel Sambuc// expected-no-diagnostics 3*f4a2713aSLionel Sambuc 4*f4a2713aSLionel Sambuc// Delta-reduced header stuff (needed for test cases). 5*f4a2713aSLionel Sambuctypedef signed char BOOL; 6*f4a2713aSLionel Sambuctypedef unsigned int NSUInteger; 7*f4a2713aSLionel Sambuctypedef struct _NSZone NSZone; 8*f4a2713aSLionel Sambuc@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 9*f4a2713aSLionel Sambuc@protocol NSObject - (BOOL)isEqual:(id)object; 10*f4a2713aSLionel Sambuc- (oneway void)release; 11*f4a2713aSLionel Sambuc@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; 12*f4a2713aSLionel Sambuc@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 13*f4a2713aSLionel Sambuc@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 14*f4a2713aSLionel Sambuc@end @interface NSObject <NSObject> {} 15*f4a2713aSLionel Sambuc+ (id)alloc; 16*f4a2713aSLionel Sambuc- (id)init; 17*f4a2713aSLionel Sambuc@end typedef struct {} 18*f4a2713aSLionel SambucNSFastEnumerationState; 19*f4a2713aSLionel Sambuc@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 20*f4a2713aSLionel Sambuc@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 21*f4a2713aSLionel Sambuc@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject; 22*f4a2713aSLionel Sambuc- (BOOL)isEqualToString:(NSString *)aString; 23*f4a2713aSLionel Sambuc@end @interface NSAutoreleasePool : NSObject {} 24*f4a2713aSLionel Sambuc- (void)drain; 25*f4a2713aSLionel Sambuc- (id)init; 26*f4a2713aSLionel Sambuc@end 27*f4a2713aSLionel Sambuc 28*f4a2713aSLionel Sambuc// This test case tests that (x != 0) is eagerly evaluated before stored to 29*f4a2713aSLionel Sambuc// 'y'. This test case complements recoverCastedSymbol (see below) because 30*f4a2713aSLionel Sambuc// the symbolic expression is stored to 'y' (which is a short instead of an 31*f4a2713aSLionel Sambuc// int). recoverCastedSymbol() only recovers path-sensitivity when the 32*f4a2713aSLionel Sambuc// symbolic expression is literally the branch condition. 33*f4a2713aSLionel Sambuc// 34*f4a2713aSLionel Sambucvoid handle_assign_of_condition(int x) { 35*f4a2713aSLionel Sambuc // The cast to 'short' causes us to lose symbolic constraint. 36*f4a2713aSLionel Sambuc short y = (x != 0); 37*f4a2713aSLionel Sambuc char *p = 0; 38*f4a2713aSLionel Sambuc if (y) { 39*f4a2713aSLionel Sambuc // This should be infeasible. 40*f4a2713aSLionel Sambuc if (!(x != 0)) { 41*f4a2713aSLionel Sambuc *p = 1; // no-warning 42*f4a2713aSLionel Sambuc } 43*f4a2713aSLionel Sambuc } 44*f4a2713aSLionel Sambuc} 45*f4a2713aSLionel Sambuc 46*f4a2713aSLionel Sambuc// From <rdar://problem/6619921> 47*f4a2713aSLionel Sambuc// 48*f4a2713aSLionel Sambuc// In this test case, 'needsAnArray' is a signed char. The analyzer tracks 49*f4a2713aSLionel Sambuc// a symbolic value for this variable, but in the branch condition it is 50*f4a2713aSLionel Sambuc// promoted to 'int'. Currently the analyzer doesn't reason well about 51*f4a2713aSLionel Sambuc// promotions of symbolic values, so this test case tests the logic in 52*f4a2713aSLionel Sambuc// 'recoverCastedSymbol()' (GRExprEngine.cpp) to test that we recover 53*f4a2713aSLionel Sambuc// path-sensitivity and use the symbol for 'needsAnArray' in the branch 54*f4a2713aSLionel Sambuc// condition. 55*f4a2713aSLionel Sambuc// 56*f4a2713aSLionel Sambucvoid handle_symbolic_cast_in_condition(void) { 57*f4a2713aSLionel Sambuc NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 58*f4a2713aSLionel Sambuc 59*f4a2713aSLionel Sambuc BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; 60*f4a2713aSLionel Sambuc NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0; 61*f4a2713aSLionel Sambuc if(needsAnArray) 62*f4a2713aSLionel Sambuc [array release]; 63*f4a2713aSLionel Sambuc 64*f4a2713aSLionel Sambuc [pool drain]; 65*f4a2713aSLionel Sambuc} 66*f4a2713aSLionel Sambuc 67*f4a2713aSLionel Sambuc// From PR 3836 (http://llvm.org/bugs/show_bug.cgi?id=3836) 68*f4a2713aSLionel Sambuc// 69*f4a2713aSLionel Sambuc// In this test case, the double '!' works fine with our symbolic constraints, 70*f4a2713aSLionel Sambuc// but we don't support comparing SymConstraint != SymConstraint. By eagerly 71*f4a2713aSLionel Sambuc// assuming the truth of !!a or !!b, we can compare these values directly. 72*f4a2713aSLionel Sambuc// 73*f4a2713aSLionel Sambucvoid pr3836(int *a, int *b) { 74*f4a2713aSLionel Sambuc if (!!a != !!b) /* one of them is NULL */ 75*f4a2713aSLionel Sambuc return; 76*f4a2713aSLionel Sambuc if (!a && !b) /* both are NULL */ 77*f4a2713aSLionel Sambuc return; 78*f4a2713aSLionel Sambuc 79*f4a2713aSLionel Sambuc *a = 1; // no-warning 80*f4a2713aSLionel Sambuc *b = 1; // no-warning 81*f4a2713aSLionel Sambuc} 82*f4a2713aSLionel Sambuc 83*f4a2713aSLionel Sambuc 84*f4a2713aSLionel Sambuc//===---------------------------------------------------------------------===// 85*f4a2713aSLionel Sambuc// <rdar://problem/7342806> 86*f4a2713aSLionel Sambuc// This false positive occurred because the symbolic constraint on a short was 87*f4a2713aSLionel Sambuc// not maintained via sign extension. The analyzer doesn't properly handle 88*f4a2713aSLionel Sambuc// the sign extension, but now tracks the constraint. This particular 89*f4a2713aSLionel Sambuc// case relies on -analyzer-eagerly-assume because of the expression 90*f4a2713aSLionel Sambuc// 'Flag1 != Count > 0'. 91*f4a2713aSLionel Sambuc//===---------------------------------------------------------------------===// 92*f4a2713aSLionel Sambuc 93*f4a2713aSLionel Sambucvoid rdar7342806_aux(short x); 94*f4a2713aSLionel Sambuc 95*f4a2713aSLionel Sambucvoid rdar7342806() { 96*f4a2713aSLionel Sambuc extern short Count; 97*f4a2713aSLionel Sambuc extern short Flag1; 98*f4a2713aSLionel Sambuc 99*f4a2713aSLionel Sambuc short *Pointer = 0; 100*f4a2713aSLionel Sambuc short Flag2 = !!Pointer; // Flag2 is false (0). 101*f4a2713aSLionel Sambuc short Ok = 1; 102*f4a2713aSLionel Sambuc short Which; 103*f4a2713aSLionel Sambuc 104*f4a2713aSLionel Sambuc if( Flag1 != Count > 0 ) 105*f4a2713aSLionel Sambuc // Static analyzer skips this so either 106*f4a2713aSLionel Sambuc // Flag1 is true and Count > 0 107*f4a2713aSLionel Sambuc // or 108*f4a2713aSLionel Sambuc // Flag1 is false and Count <= 0 109*f4a2713aSLionel Sambuc Ok = 0; 110*f4a2713aSLionel Sambuc 111*f4a2713aSLionel Sambuc if( Flag1 != Flag2 ) 112*f4a2713aSLionel Sambuc // Analyzer skips this so Flag1 and Flag2 have the 113*f4a2713aSLionel Sambuc // same value, both are false because Flag2 is false. And 114*f4a2713aSLionel Sambuc // from that we know Count must be <= 0. 115*f4a2713aSLionel Sambuc Ok = 0; 116*f4a2713aSLionel Sambuc 117*f4a2713aSLionel Sambuc for( Which = 0; 118*f4a2713aSLionel Sambuc Which < Count && Ok; 119*f4a2713aSLionel Sambuc Which++ ) 120*f4a2713aSLionel Sambuc // This statement can only execute if Count > 0 which can only 121*f4a2713aSLionel Sambuc // happen when Flag1 and Flag2 are both true and Flag2 will only 122*f4a2713aSLionel Sambuc // be true when Pointer is not NULL. 123*f4a2713aSLionel Sambuc rdar7342806_aux(*Pointer); // no-warning 124*f4a2713aSLionel Sambuc} 125*f4a2713aSLionel Sambuc 126*f4a2713aSLionel Sambuc//===---------------------------------------------------------------------===// 127*f4a2713aSLionel Sambuc// PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627 128*f4a2713aSLionel Sambuc// This test case depends on using -analyzer-eagerly-assume and 129*f4a2713aSLionel Sambuc// -analyzer-store=region. The '-analyzer-eagerly-assume' causes the path 130*f4a2713aSLionel Sambuc// to bifurcate when evaluating the function call argument, and a state 131*f4a2713aSLionel Sambuc// caching bug in GRExprEngine::CheckerVisit (and friends) caused the store 132*f4a2713aSLionel Sambuc// to 'p' to not be evaluated along one path, but then an autotransition caused 133*f4a2713aSLionel Sambuc// the path to keep on propagating with 'p' still set to an undefined value. 134*f4a2713aSLionel Sambuc// We would then get a bogus report of returning uninitialized memory. 135*f4a2713aSLionel Sambuc// Note: CheckerVisit mistakenly cleared an existing node, and the cleared 136*f4a2713aSLionel Sambuc// node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where 137*f4a2713aSLionel Sambuc// 'p' was not assigned. 138*f4a2713aSLionel Sambuc//===---------------------------------------------------------------------===// 139*f4a2713aSLionel Sambuc 140*f4a2713aSLionel Sambucfloat *pr5627_f(int y); 141*f4a2713aSLionel Sambuc 142*f4a2713aSLionel Sambucfloat *pr5627_g(int x) { 143*f4a2713aSLionel Sambuc float *p; 144*f4a2713aSLionel Sambuc p = pr5627_f(!x); 145*f4a2713aSLionel Sambuc return p; // no-warning 146*f4a2713aSLionel Sambuc} 147*f4a2713aSLionel Sambuc 148