xref: /llvm-project/clang/test/Analysis/equality_tracking.c (revision 0851d7b00c651d527a37becc206566580bf3c615)
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_value(int);
12 void clang_analyzer_eval(int);
13 void clang_analyzer_warnIfReached(void);
14 
15 int getInt(void);
16 
zeroImpliesEquality(int a,int b)17 void zeroImpliesEquality(int a, int b) {
18   clang_analyzer_eval((a - b) == 0); // expected-warning{{UNKNOWN}}
19   if ((a - b) == 0) {
20     clang_analyzer_eval(b != a);    // expected-warning{{FALSE}}
21     clang_analyzer_eval(b == a);    // expected-warning{{TRUE}}
22     clang_analyzer_eval(!(a != b)); // expected-warning{{TRUE}}
23     clang_analyzer_eval(!(b == a)); // expected-warning{{FALSE}}
24     return;
25   }
26   clang_analyzer_eval((a - b) == 0); // expected-warning{{FALSE}}
27   clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
28   clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
29 }
30 
31 typedef int I32_A;
32 typedef int I32_B;
zeroImpliesEqualityWithTypedef(I32_A a,I32_B b)33 void zeroImpliesEqualityWithTypedef(I32_A a, I32_B b) {
34   clang_analyzer_eval((a - b) == 0); // expected-warning{{UNKNOWN}}
35   if ((a - b) == 0) {
36     clang_analyzer_eval(b != a);    // expected-warning{{FALSE}}
37     clang_analyzer_eval(b == a);    // expected-warning{{TRUE}}
38     clang_analyzer_eval(!(a != b)); // expected-warning{{TRUE}}
39     clang_analyzer_eval(!(b == a)); // expected-warning{{FALSE}}
40     return;
41   }
42   clang_analyzer_eval((a - b) == 0); // expected-warning{{FALSE}}
43   clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
44   clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
45 }
46 
zeroImpliesReversedEqual(int a,int b)47 void zeroImpliesReversedEqual(int a, int b) {
48   clang_analyzer_eval((b - a) == 0); // expected-warning{{UNKNOWN}}
49   if ((b - a) == 0) {
50     clang_analyzer_eval(b != a); // expected-warning{{FALSE}}
51     clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
52     return;
53   }
54   clang_analyzer_eval((b - a) == 0); // expected-warning{{FALSE}}
55   clang_analyzer_eval(b == a);       // expected-warning{{FALSE}}
56   clang_analyzer_eval(b != a);       // expected-warning{{TRUE}}
57 }
58 
canonicalEqual(int a,int b)59 void canonicalEqual(int a, int b) {
60   clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
61   if (a == b) {
62     clang_analyzer_eval(b == a); // expected-warning{{TRUE}}
63     return;
64   }
65   clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
66   clang_analyzer_eval(b == a); // expected-warning{{FALSE}}
67 }
68 
test(int a,int b,int c,int d)69 void test(int a, int b, int c, int d) {
70   if (a == b && c == d) {
71     if (a == 0 && b == d) {
72       clang_analyzer_eval(c == 0); // expected-warning{{TRUE}}
73     }
74     c = 10;
75     if (b == d) {
76       clang_analyzer_eval(c == 10); // expected-warning{{TRUE}}
77       clang_analyzer_eval(d == 10); // expected-warning{{UNKNOWN}}
78                                     // expected-warning@-1{{FALSE}}
79       clang_analyzer_eval(b == a);  // expected-warning{{TRUE}}
80       clang_analyzer_eval(a == d);  // expected-warning{{TRUE}}
81 
82       b = getInt();
83       clang_analyzer_eval(a == d); // expected-warning{{TRUE}}
84       clang_analyzer_eval(a == b); // expected-warning{{UNKNOWN}}
85     }
86   }
87 
88   if (a != b && b == c) {
89     if (c == 42) {
90       clang_analyzer_eval(b == 42); // expected-warning{{TRUE}}
91       clang_analyzer_eval(a != 42); // expected-warning{{TRUE}}
92     }
93   }
94 }
95 
testIntersection(int a,int b,int c)96 void testIntersection(int a, int b, int c) {
97   if (a < 42 && b > 15 && c >= 25 && c <= 30) {
98     if (a != b)
99       return;
100 
101     clang_analyzer_eval(a > 15);  // expected-warning{{TRUE}}
102     clang_analyzer_eval(b < 42);  // expected-warning{{TRUE}}
103     clang_analyzer_eval(a <= 30); // expected-warning{{UNKNOWN}}
104 
105     if (c == b) {
106       // For all equal symbols, we should track the minimal common range.
107       //
108       // Also, it should be noted that c is dead at this point, but the
109       // constraint initially associated with c is still around.
110       clang_analyzer_eval(a >= 25 && a <= 30); // expected-warning{{TRUE}}
111       clang_analyzer_eval(b >= 25 && b <= 30); // expected-warning{{TRUE}}
112     }
113   }
114 }
115 
testPromotion(int a,char b)116 void testPromotion(int a, char b) {
117   if (b > 10) {
118     if (a == b) {
119       // FIXME: support transferring char ranges onto equal int symbols
120       //        when char is promoted to int
121       clang_analyzer_eval(a > 10);        // expected-warning{{UNKNOWN}}
122       clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
123     }
124   }
125 }
126 
testPromotionOnlyTypes(int a,char b)127 void testPromotionOnlyTypes(int a, char b) {
128   if (a == b) {
129     // FIXME: support transferring char ranges onto equal int symbols
130     //        when char is promoted to int
131     clang_analyzer_eval(a <= CHAR_MAX); // expected-warning{{UNKNOWN}}
132   }
133 }
134 
testDowncast(int a,unsigned char b)135 void testDowncast(int a, unsigned char b) {
136   if (a <= -10) {
137     if ((unsigned char)a == b) {
138       // Even though ranges for a and b do not intersect,
139       // ranges for (unsigned char)a and b do.
140       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
141     }
142     if (a == b) {
143       // FIXME: This case on the other hand is different, it shouldn't be
144       //        reachable.  However, the corrent symbolic information available
145       //        to the solver doesn't allow it to distinguish this expression
146       //        from the previous one.
147       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
148     }
149   }
150 }
151 
testPointers(int * a,int * b,int * c,int * d)152 void testPointers(int *a, int *b, int *c, int *d) {
153   if (a == b && c == d) {
154     if (a == NULL && b == d) {
155       clang_analyzer_eval(c == NULL); // expected-warning{{TRUE}}
156     }
157   }
158 
159   if (a != b && b == c) {
160     if (c == NULL) {
161       clang_analyzer_eval(a != NULL); // expected-warning{{TRUE}}
162     }
163   }
164 }
165 
testDisequalitiesAfter(int a,int b,int c)166 void testDisequalitiesAfter(int a, int b, int c) {
167   if (a >= 10 && b <= 42) {
168     if (a == b && c == 15 && c != a) {
169       clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
170       clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
171       clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
172       clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
173       clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
174     }
175   }
176 }
177 
testDisequalitiesBefore(int a,int b,int c)178 void testDisequalitiesBefore(int a, int b, int c) {
179   if (a >= 10 && b <= 42 && c == 15) {
180     if (a == b && c != a) {
181       clang_analyzer_eval(b != c);  // expected-warning{{TRUE}}
182       clang_analyzer_eval(a != 15); // expected-warning{{TRUE}}
183       clang_analyzer_eval(b != 15); // expected-warning{{TRUE}}
184       clang_analyzer_eval(b >= 10); // expected-warning{{TRUE}}
185       clang_analyzer_eval(a <= 42); // expected-warning{{TRUE}}
186     }
187   }
188 }
189 
avoidInfeasibleConstraintsForClasses(int a,int b)190 void avoidInfeasibleConstraintsForClasses(int a, int b) {
191   if (a >= 0 && a <= 10 && b >= 20 && b <= 50) {
192     if ((b - a) == 0) {
193       clang_analyzer_warnIfReached(); // no warning
194     }
195     if (a == b) {
196       clang_analyzer_warnIfReached(); // no warning
197     }
198     if (a != b) {
199       clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
200     } else {
201       clang_analyzer_warnIfReached(); // no warning
202     }
203   }
204 }
205 
avoidInfeasibleConstraintforGT(int a,int b)206 void avoidInfeasibleConstraintforGT(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 
avoidInfeasibleConstraintforLT(int a,int b)223 void avoidInfeasibleConstraintforLT(int a, int b) {
224   int c = b - a;
225   if (c >= 0)
226     return;
227   // c < 0
228   // b - a < 0
229   // b < a
230   if (a != b) {
231     clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
232     return;
233   }
234   clang_analyzer_warnIfReached(); // no warning
235   // a == b
236   if (c < 0)
237     ;
238 }
239 
implyDisequalityFromGT(int a,int b)240 void implyDisequalityFromGT(int a, int b) {
241   if (a > b) {
242     clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
243     clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
244   }
245 }
246 
implyDisequalityFromLT(int a,int b)247 void implyDisequalityFromLT(int a, int b) {
248   if (a < b) {
249     clang_analyzer_eval(a == b); // expected-warning{{FALSE}}
250     clang_analyzer_eval(a != b); // expected-warning{{TRUE}}
251   }
252 }
253 
deletePointBefore(int x,int tmp)254 void deletePointBefore(int x, int tmp) {
255   if(tmp == 0)
256     if(x != tmp)
257      clang_analyzer_value(x); // expected-warning {{32s:{ [-2147483648, -1], [1, 2147483647] }}}
258 }
259 
deletePointAfter(int x,int tmp)260 void deletePointAfter(int x, int tmp) {
261   if(x != tmp)
262     if(tmp == 2147483647)
263       clang_analyzer_value(x); // expected-warning {{32s:{ [-2147483648, 2147483646] }}}
264 }
265 
deleteTwoPoints(int x,int tmp1,int tmp2)266 void deleteTwoPoints(int x, int tmp1, int tmp2) {
267   if(x != tmp1) {
268     if (tmp1 == 42 && tmp2 == 87) {
269       clang_analyzer_value(x); // expected-warning {{32s:{ [-2147483648, 41], [43, 2147483647] }}}
270       if(x != tmp2)
271         clang_analyzer_value(x); // expected-warning {{32s:{ [-2147483648, 41], [43, 86], [88, 2147483647] }}}
272     }
273   }
274 }
275 
deleteAllPoints(unsigned char x,unsigned char * arr)276 void deleteAllPoints(unsigned char x, unsigned char *arr) {
277 
278 #define cond(n) \
279 arr[n##0] == n##0 && \
280 arr[n##1] == n##1 && \
281 arr[n##2] == n##2 && \
282 arr[n##3] == n##3 && \
283 arr[n##4] == n##4 && \
284 arr[n##5] == n##5 && \
285 arr[n##6] == n##6 && \
286 arr[n##7] == n##7 && \
287 arr[n##8] == n##8 && \
288 arr[n##9] == n##9 && \
289 
290 #define condX(n) \
291 arr[n##0] != x && \
292 arr[n##1] != x && \
293 arr[n##2] != x && \
294 arr[n##3] != x && \
295 arr[n##4] != x && \
296 arr[n##5] != x && \
297 arr[n##6] != x && \
298 arr[n##7] != x && \
299 arr[n##8] != x && \
300 arr[n##9] != x && \
301 
302   clang_analyzer_value(x); // expected-warning {{{ [0, 255] }}}
303   if (
304     cond()  // 0  .. 9
305     cond(1) // 10 .. 19
306     cond(2) // 20 .. 29
307     cond(3) // 30 .. 39
308     cond(4) // 40 .. 49
309     cond(5) // 50 .. 59
310     cond(6) // 60 .. 69
311     cond(7) // 70 .. 79
312     cond(8) // 80 .. 89
313     cond(9) // 90 .. 99
314     cond(10) // 100 .. 209
315     cond(11) // 110 .. 219
316     cond(12) // 120 .. 229
317     cond(13) // 130 .. 239
318     cond(14) // 140 .. 249
319     cond(15) // 150 .. 259
320     cond(16) // 160 .. 269
321     cond(17) // 170 .. 279
322     cond(18) // 180 .. 289
323     cond(19) // 190 .. 199
324     cond(20) // 200 .. 209
325     cond(21) // 210 .. 219
326     cond(22) // 220 .. 229
327     cond(23) // 230 .. 239
328     cond(24) // 240 .. 249
329     arr[250] == 250 &&
330     arr[251] == 251 &&
331     arr[252] == 252 &&
332     arr[253] == 253 &&
333     arr[254] == 254 &&
334     arr[255] == 255
335     ) {
336     if (
337       condX()  // 0  .. 9
338       condX(1) // 10 .. 19
339       condX(2) // 20 .. 29
340       condX(3) // 30 .. 39
341       condX(4) // 40 .. 49
342       condX(5) // 50 .. 59
343       condX(6) // 60 .. 69
344       condX(7) // 70 .. 79
345       condX(8) // 80 .. 89
346       condX(9) // 90 .. 99
347       condX(10) // 100 .. 209
348       condX(11) // 110 .. 219
349       condX(12) // 120 .. 229
350       condX(13) // 130 .. 239
351       condX(14) // 140 .. 249
352       condX(15) // 150 .. 259
353       condX(16) // 160 .. 269
354       condX(17) // 170 .. 279
355       condX(18) // 180 .. 289
356       condX(19) // 190 .. 199
357       condX(20) // 200 .. 209
358       condX(21) // 210 .. 219
359       condX(22) // 220 .. 229
360       condX(23) // 230 .. 239
361       arr[240] != x &&
362       arr[241] != x &&
363       arr[242] != x &&
364       arr[243] != x &&
365       arr[244] != x &&
366       arr[245] != x &&
367       arr[246] != x &&
368       arr[247] != x &&
369       arr[248] != x &&
370       arr[249] != x
371       ) {
372       clang_analyzer_value(x); // expected-warning {{{ [250, 255] }}}
373       if (
374       arr[250] != x &&
375       arr[251] != x &&
376       //skip arr[252]
377       arr[253] != x &&
378       arr[254] != x &&
379       arr[255] != x
380       ) {
381         clang_analyzer_value(x); // expected-warning {{32s:252}}
382         if (arr[252] != x) {
383           clang_analyzer_warnIfReached(); // unreachable
384         }
385       }
386     }
387   }
388 }
389