blob: 9fbe3d0e4ee9a525b58f402346fa7e774bcf2ccd [file] [log] [blame]
Ted Kremenek722398f2012-08-24 20:39:55 +00001// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core -analyzer-store=region -analyzer-constraints=range -verify -fblocks %s -analyzer-eagerly-assume
Andy Gibbsc6e68da2012-10-19 12:44:48 +00002// expected-no-diagnostics
Ted Kremenekdc3f50f2009-02-25 22:32:02 +00003
Ted Kremenek22358bd2009-03-13 16:32:54 +00004// 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;
Douglas Gregorc9224d62011-06-13 16:42:53 +000016- (id)init;
Ted Kremenek22358bd2009-03-13 16:32:54 +000017@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//
Ted Kremenekdc3f50f2009-02-25 22:32:02 +000034void 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
Ted Kremenek22358bd2009-03-13 16:32:54 +000046// 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//
56void 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}
Ted Kremenek891642e2009-03-18 23:49:26 +000066
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//
73void 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}
Ted Kremenek33335b12009-10-29 00:49:46 +000082
83
84//===---------------------------------------------------------------------===//
85// <rdar://problem/7342806>
Chris Lattner57540c52011-04-15 05:22:18 +000086// This false positive occurred because the symbolic constraint on a short was
Ted Kremenek33335b12009-10-29 00:49:46 +000087// 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
93void rdar7342806_aux(short x);
94
95void 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}
Ted Kremenek32c32892009-12-09 02:45:41 +0000125
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.
Zhongxing Xu39644a62009-12-09 04:22:30 +0000135// Note: CheckerVisit mistakenly cleared an existing node, and the cleared
136// node was resurrected by GRStmtNodeBuilder::~GRStmtNodeBuilder(), where
137// 'p' was not assigned.
Ted Kremenek32c32892009-12-09 02:45:41 +0000138//===---------------------------------------------------------------------===//
139
140float *pr5627_f(int y);
141
142float *pr5627_g(int x) {
143 float *p;
144 p = pr5627_f(!x);
145 return p; // no-warning
146}
147