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