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