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