1 // RUN: %clang_analyze_cc1 -verify %s \
2 // RUN:   -analyzer-checker=core,debug.ExprInspection \
3 // RUN:   -analyzer-config eagerly-assume=false
4 
5 #define NULL (void *)0
6 
7 #define UCHAR_MAX (unsigned char)(~0U)
8 #define CHAR_MAX (char)(UCHAR_MAX & (UCHAR_MAX >> 1))
9 #define CHAR_MIN (char)(UCHAR_MAX & ~(UCHAR_MAX >> 1))
10 
11 void clang_analyzer_eval(int);
12 void clang_analyzer_warnIfReached();
13 
14 int getInt();
15 
zeroImpliesEquality(int a,int b)16 void zeroImpliesEquality(int a, int b) {
17   clang_analyzer_eval((a - b) == 0); // expected-warning{{UNKNOWN}}
18   if ((a - b) == 0) {
19     clang_analyzer_eval(b != a);    // expected-warning{{FALSE}}
20     clang_analyzer_eval(b == a);    // expected-warning{{TRUE}}
21     clang_analyzer_eval(!(a != b)); // expected-warning{{TRUE}}
22     clang_analyzer_eval(!(b == a)); // expected-warning{{FALSE}}
23     return;
24   }
25   clang_analyzer_eval((a - b) == 0); // expected-warning{{FALSE}}
26   clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
27   clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
28 }
29 
zeroImpliesReversedEqual(int a,int b)30 void zeroImpliesReversedEqual(int a, int b) {
31   clang_analyzer_eval((b - a) == 0); // expected-warning{{UNKNOWN}}
32   if ((b - a) == 0) {
33     clang_analyzer_eval(b != a); // expected-warning{{FALSE}}
34     clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
35     return;
36   }
37   clang_analyzer_eval((b - a) == 0); // expected-warning{{FALSE}}
38   clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
39   clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
40 }
41 
canonicalEqual(int a,int b)42 void canonicalEqual(int a, int b) {
43   clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
44   if (a == b) {
45     clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
46     return;
47   }
48   clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
49   clang_analyzer_eval(b == a); // expected-warning{{FALSE}}
50 }
51 
test(int a,int b,int c,int d)52 void test(int a, int b, int c, int d) {
53   if (a == b && c == d) {
54     if (a == 0 && b == d) {
55       clang_analyzer_eval(c == 0); // expected-warning{{TRUE}}
56     }
57     c = 10;
58     if (b == d) {
59       clang_analyzer_eval(c == 10); // expected-warning{{TRUE}}
60       clang_analyzer_eval(d == 10); // expected-warning{{UNKNOWN}}
61                                     // expected-warning@-1{{FALSE}}
62       clang_analyzer_eval(b == a);  // expected-warning{{TRUE}}
63       clang_analyzer_eval(a == d);  // expected-warning{{TRUE}}
64 
65       b = getInt();
66       clang_analyzer_eval(a == d); // expected-warning{{TRUE}}
67       clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
68     }
69   }
70 
71   if (a != b && b == c) {
72     if (c == 42) {
73       clang_analyzer_eval(b == 42); // expected-warning{{TRUE}}
74       clang_analyzer_eval(a != 42); // expected-warning{{TRUE}}
75     }
76   }
77 }
78 
testIntersection(int a,int b,int c)79 void testIntersection(int a, int b, int c) {
80   if (a < 42 && b > 15 && c >= 25 && c <= 30) {
81     if (a != b)
82       return;
83 
84     clang_analyzer_eval(a > 15);  // expected-warning{{TRUE}}
85     clang_analyzer_eval(b < 42);  // expected-warning{{TRUE}}
86     clang_analyzer_eval(a <= 30); // expected-warning{{UNKNOWN}}
87 
88     if (c == b) {
89       // For all equal symbols, we should track the minimal common range.
90       //
91       // Also, it should be noted that c is dead at this point, but the
92       // constraint initially associated with c is still around.
93       clang_analyzer_eval(a >= 25 && a <= 30); // expected-warning{{TRUE}}
94       clang_analyzer_eval(b >= 25 && b <= 30); // expected-warning{{TRUE}}
95     }
96   }
97 }
98 
testPromotion(int a,char b)99 void testPromotion(int a, char b) {
100   if (b > 10) {
101     if (a == b) {
102       // FIXME: support transferring char ranges onto equal int symbols
103       //        when char is promoted to int
104       clang_analyzer_eval(a > 10);        // expected-warning{{UNKNOWN}}
105       clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
106     }
107   }
108 }
109 
testPromotionOnlyTypes(int a,char b)110 void testPromotionOnlyTypes(int a, char b) {
111   if (a == b) {
112     // FIXME: support transferring char ranges onto equal int symbols
113     //        when char is promoted to int
114     clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
115   }
116 }
117 
testDowncast(int a,unsigned char b)118 void testDowncast(int a, unsigned char b) {
119   if (a <= -10) {
120     if ((unsigned char)a == b) {
121       // Even though ranges for a and b do not intersect,
122       // ranges for (unsigned char)a and b do.
123       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
124     }
125     if (a == b) {
126       // FIXME: This case on the other hand is different, it shouldn't be
127       //        reachable.  However, the corrent symbolic information available
128       //        to the solver doesn't allow it to distinguish this expression
129       //        from the previous one.
130       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
131     }
132   }
133 }
134 
testPointers(int * a,int * b,int * c,int * d)135 void testPointers(int *a, int *b, int *c, int *d) {
136   if (a == b && c == d) {
137     if (a == NULL && b == d) {
138       clang_analyzer_eval(c == NULL); // expected-warning{{TRUE}}
139     }
140   }
141 
142   if (a != b && b == c) {
143     if (c == NULL) {
144       clang_analyzer_eval(a != NULL); // expected-warning{{TRUE}}
145     }
146   }
147 }
148 
testDisequalitiesAfter(int a,int b,int c)149 void testDisequalitiesAfter(int a, int b, int c) {
150   if (a >= 10 && b <= 42) {
151     if (a == b && c == 15 && c != a) {
152       clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
153       clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
154       clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
155       clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
156       clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
157     }
158   }
159 }
160 
testDisequalitiesBefore(int a,int b,int c)161 void testDisequalitiesBefore(int a, int b, int c) {
162   if (a >= 10 && b <= 42 && c == 15) {
163     if (a == b && c != a) {
164       clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
165       clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
166       clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
167       clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
168       clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
169     }
170   }
171 }
172 
avoidInfeasibleConstraintsForClasses(int a,int b)173 void avoidInfeasibleConstraintsForClasses(int a, int b) {
174   if (a >= 0 && a <= 10 && b >= 20 && b <= 50) {
175     if ((b - a) == 0) {
176       clang_analyzer_warnIfReached(); // no warning
177     }
178     if (a == b) {
179       clang_analyzer_warnIfReached(); // no warning
180     }
181     if (a != b) {
182       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
183     } else {
184       clang_analyzer_warnIfReached(); // no warning
185     }
186   }
187 }
188 
avoidInfeasibleConstraintforGT(int a,int b)189 void avoidInfeasibleConstraintforGT(int a, int b) {
190   int c = b - a;
191   if (c <= 0)
192     return;
193   // c > 0
194   // b - a > 0
195   // b > a
196   if (a != b) {
197     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
198     return;
199   }
200   clang_analyzer_warnIfReached(); // no warning
201   // a == b
202   if (c < 0)
203     ;
204 }
205 
avoidInfeasibleConstraintforLT(int a,int b)206 void avoidInfeasibleConstraintforLT(int a, int b) {
207   int c = b - a;
208   if (c >= 0)
209     return;
210   // c < 0
211   // b - a < 0
212   // b < a
213   if (a != b) {
214     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
215     return;
216   }
217   clang_analyzer_warnIfReached(); // no warning
218   // a == b
219   if (c < 0)
220     ;
221 }
222 
implyDisequalityFromGT(int a,int b)223 void implyDisequalityFromGT(int a, int b) {
224   if (a > b) {
225     clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
226     clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
227   }
228 }
229 
implyDisequalityFromLT(int a,int b)230 void implyDisequalityFromLT(int a, int b) {
231   if (a < b) {
232     clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
233     clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
234   }
235 }
236