1 // RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume 2 // expected-no-diagnostics 3 4 // Delta-reduced header stuff (needed for test cases). 5 typedef signed char BOOL; 6 typedef unsigned int NSUInteger; 7 typedef 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 {} 18 NSFastEnumerationState; 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 // 34 void 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 // From <rdar://problem/6619921> 47 // 48 // In this test case, 'needsAnArray' is a signed char. The analyzer tracks 49 // a symbolic value for this variable, but in the branch condition it is 50 // promoted to 'int'. Currently the analyzer doesn't reason well about 51 // promotions of symbolic values, so this test case tests the logic in 52 // 'recoverCastedSymbol()' (GRExprEngine.cpp) to test that we recover 53 // path-sensitivity and use the symbol for 'needsAnArray' in the branch 54 // condition. 55 // 56 void handle_symbolic_cast_in_condition(void) { 57 NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; 58 59 BOOL needsAnArray = [@"aString" isEqualToString:@"anotherString"]; 60 NSMutableArray* array = needsAnArray ? [[NSMutableArray alloc] init] : 0; 61 if(needsAnArray) 62 [array release]; 63 64 [pool drain]; 65 } 66 67 // From PR 3836 (http://llvm.org/bugs/show_bug.cgi?id=3836) 68 // 69 // In this test case, the double '!' works fine with our symbolic constraints, 70 // but we don't support comparing SymConstraint != SymConstraint. By eagerly 71 // assuming the truth of !!a or !!b, we can compare these values directly. 72 // 73 void pr3836(int *a, int *b) { 74 if (!!a != !!b) /* one of them is NULL */ 75 return; 76 if (!a && !b) /* both are NULL */ 77 return; 78 79 *a = 1; // no-warning 80 *b = 1; // no-warning 81 } 82 83 84 //===---------------------------------------------------------------------===// 85 // <rdar://problem/7342806> 86 // This false positive occurred because the symbolic constraint on a short was 87 // not maintained via sign extension. The analyzer doesn't properly handle 88 // the sign extension, but now tracks the constraint. This particular 89 // case relies on -analyzer-eagerly-assume because of the expression 90 // 'Flag1 != Count > 0'. 91 //===---------------------------------------------------------------------===// 92 93 void rdar7342806_aux(short x); 94 95 void rdar7342806() { 96 extern short Count; 97 extern short Flag1; 98 99 short *Pointer = 0; 100 short Flag2 = !!Pointer; // Flag2 is false (0). 101 short Ok = 1; 102 short Which; 103 104 if( Flag1 != Count > 0 ) 105 // Static analyzer skips this so either 106 // Flag1 is true and Count > 0 107 // or 108 // Flag1 is false and Count <= 0 109 Ok = 0; 110 111 if( Flag1 != Flag2 ) 112 // Analyzer skips this so Flag1 and Flag2 have the 113 // same value, both are false because Flag2 is false. And 114 // from that we know Count must be <= 0. 115 Ok = 0; 116 117 for( Which = 0; 118 Which < Count && Ok; 119 Which++ ) 120 // This statement can only execute if Count > 0 which can only 121 // happen when Flag1 and Flag2 are both true and Flag2 will only 122 // be true when Pointer is not NULL. 123 rdar7342806_aux(*Pointer); // no-warning 124 } 125 126 //===---------------------------------------------------------------------===// 127 // PR 5627 - http://llvm.org/bugs/show_bug.cgi?id=5627 128 // This test case depends on using -analyzer-eagerly-assume and 129 // -analyzer-store=region. The '-analyzer-eagerly-assume' causes the path 130 // to bifurcate when evaluating the function call argument, and a state 131 // caching bug in GRExprEngine::CheckerVisit (and friends) caused the store 132 // to 'p' to not be evaluated along one path, but then an autotransition caused 133 // the path to keep on propagating with 'p' still set to an undefined value. 134 // We would then get a bogus report of returning uninitialized memory. 135 // Note: CheckerVisit mistakenly cleared an existing node, and the cleared 136 // node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where 137 // 'p' was not assigned. 138 //===---------------------------------------------------------------------===// 139 140 float *pr5627_f(int y); 141 142 float *pr5627_g(int x) { 143 float *p; 144 p = pr5627_f(!x); 145 return p; // no-warning 146 } 147 148