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