1// RUN: %clang_analyze_cc1 -analyzer-checker=core,alpha.core -verify -fblocks %s 2// expected-no-diagnostics 3 4// Delta-reduced header stuff (needed for test cases). 5typedef signed char BOOL; 6typedef unsigned int NSUInteger; 7typedef struct _NSZone NSZone; 8@class NSInvocation, NSMethodSignature, NSCoder, NSString, NSEnumerator; 9@protocol NSObject - (BOOL)isEqual:(id)object; 10- (oneway void)release; 11@end @protocol NSCopying - (id)copyWithZone:(NSZone *)zone; 12@end @protocol NSMutableCopying - (id)mutableCopyWithZone:(NSZone *)zone; 13@end @protocol NSCoding - (void)encodeWithCoder:(NSCoder *)aCoder; 14@end @interface NSObject <NSObject> {} 15+ (id)alloc; 16- (id)init; 17@end typedef struct {} 18NSFastEnumerationState; 19@protocol NSFastEnumeration - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(NSUInteger)len; 20@end @interface NSArray : NSObject <NSCopying, NSMutableCopying, NSCoding, NSFastEnumeration> - (NSUInteger)count; 21@end @interface NSMutableArray : NSArray - (void)addObject:(id)anObject; 22- (BOOL)isEqualToString:(NSString *)aString; 23@end @interface NSAutoreleasePool : NSObject {} 24- (void)drain; 25- (id)init; 26@end 27 28// This test case tests that (x != 0) is eagerly evaluated before stored to 29// 'y'. This test case complements recoverCastedSymbol (see below) because 30// the symbolic expression is stored to 'y' (which is a short instead of an 31// int). recoverCastedSymbol() only recovers path-sensitivity when the 32// symbolic expression is literally the branch condition. 33// 34void handle_assign_of_condition(int x) { 35 // The cast to 'short' causes us to lose symbolic constraint. 36 short y = (x != 0); 37 char *p = 0; 38 if (y) { 39 // This should be infeasible. 40 if (!(x != 0)) { 41 *p = 1; // no-warning 42 } 43 } 44} 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()' (ExprEngine.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 81 82//===---------------------------------------------------------------------===// 83// This false positive occurred because the symbolic constraint on a short was 84// not maintained via sign extension. The analyzer doesn't properly handle 85// the sign extension, but now tracks the constraint. This particular 86// case relies on -analyzer-options eagerly-assume=true because of the expression 87// 'Flag1 != Count > 0'. 88//===---------------------------------------------------------------------===// 89 90void rdar7342806_aux(short x); 91 92void rdar7342806(void) { 93 extern short Count; 94 extern short Flag1; 95 96 short *Pointer = 0; 97 short Flag2 = !!Pointer; // Flag2 is false (0). 98 short Ok = 1; 99 short Which; 100 101 if( Flag1 != Count > 0 ) 102 // Static analyzer skips this so either 103 // Flag1 is true and Count > 0 104 // or 105 // Flag1 is false and Count <= 0 106 Ok = 0; 107 108 if( Flag1 != Flag2 ) 109 // Analyzer skips this so Flag1 and Flag2 have the 110 // same value, both are false because Flag2 is false. And 111 // from that we know Count must be <= 0. 112 Ok = 0; 113 114 for( Which = 0; 115 Which < Count && Ok; 116 Which++ ) 117 // This statement can only execute if Count > 0 which can only 118 // happen when Flag1 and Flag2 are both true and Flag2 will only 119 // be true when Pointer is not NULL. 120 rdar7342806_aux(*Pointer); // no-warning 121} 122 123//===---------------------------------------------------------------------===// 124// PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627 125// This test case depends on using -analyzer-config eagerly-assume=true. 126// The 'eagerly-assume=true' causes the path 127// to bifurcate when evaluating the function call argument, and a state 128// caching bug in ExprEngine::CheckerVisit (and friends) caused the store 129// to 'p' to not be evaluated along one path, but then an autotransition caused 130// the path to keep on propagating with 'p' still set to an undefined value. 131// We would then get a bogus report of returning uninitialized memory. 132// Note: CheckerVisit mistakenly cleared an existing node, and the cleared 133// node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where 134// 'p' was not assigned. 135//===---------------------------------------------------------------------===// 136 137float *pr5627_f(int y); 138 139float *pr5627_g(int x) { 140 float *p; 141 p = pr5627_f(!x); 142 return p; // no-warning 143} 144 145