additive-folding.cpp revision 43d9f0d4e9b88dcab473a359a7b5579c2a619b22
1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=basic -Wno-tautological-compare %s
2// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range -Wno-tautological-compare %s
3
4void clang_analyzer_eval(bool);
5
6#define UINT_MAX (~0U)
7#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
8#define INT_MIN (-INT_MAX - 1)
9
10//---------------
11//  Plus/minus
12//---------------
13
14void separateExpressions (int a) {
15  int b = a + 1;
16  --b;
17
18  clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
19}
20
21void oneLongExpression (int a) {
22  // Expression canonicalization should still allow this to work, even though
23  // the first term is on the left.
24  int b = 15 + a + 15 - 10 - 20;
25
26  clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
27}
28
29void mixedTypes (int a) {
30  // Different additive types should not cause crashes when constant-folding.
31  // This is part of PR7406.
32  int b = a + 1LL;
33  clang_analyzer_eval(a != 0 && (b-1) == 0); // not crash, expected-warning{{FALSE}}
34
35  int c = a + 1U;
36  clang_analyzer_eval(a != 0 && (c-1) == 0); // not crash, expected-warning{{FALSE}}
37}
38
39//---------------
40//  Comparisons
41//---------------
42
43// Equality and inequality only
44void eq_ne (unsigned a) {
45  if (a == UINT_MAX) {
46    clang_analyzer_eval(a+1 == 0); // expected-warning{{TRUE}}
47    clang_analyzer_eval(a-1 == UINT_MAX-1); // expected-warning{{TRUE}}
48  } else {
49    clang_analyzer_eval(a+1 != 0); // expected-warning{{TRUE}}
50    clang_analyzer_eval(a-1 != UINT_MAX-1); // expected-warning{{TRUE}}
51  }
52}
53
54// Mixed typed inequalities (part of PR7406)
55// These should not crash.
56void mixed_eq_ne (int a) {
57  if (a == 1) {
58    clang_analyzer_eval(a+1U == 2); // expected-warning{{TRUE}}
59    clang_analyzer_eval(a-1U == 0); // expected-warning{{TRUE}}
60  } else {
61    clang_analyzer_eval(a+1U != 2); // expected-warning{{TRUE}}
62    clang_analyzer_eval(a-1U != 0); // expected-warning{{TRUE}}
63  }
64}
65
66
67// Simple order comparisons with no adjustment
68void baselineGT (unsigned a) {
69  if (a > 0)
70    clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
71  else
72    clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
73}
74
75void baselineGE (unsigned a) {
76  if (a >= UINT_MAX)
77    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
78  else
79    clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
80}
81
82void baselineLT (unsigned a) {
83  if (a < UINT_MAX)
84    clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
85  else
86    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
87}
88
89void baselineLE (unsigned a) {
90  if (a <= 0)
91    clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
92  else
93    clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
94}
95
96
97// Adjustment gives each of these an extra solution!
98void adjustedGT (unsigned a) {
99  clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
100}
101
102void adjustedGE (unsigned a) {
103  clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
104
105  if (a-1 >= UINT_MAX-1)
106    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{UNKNOWN}}
107}
108
109void adjustedLT (unsigned a) {
110  clang_analyzer_eval(a+1 < 1); // expected-warning{{UNKNOWN}}
111}
112
113void adjustedLE (unsigned a) {
114  clang_analyzer_eval(a+1 <= 1); // expected-warning{{UNKNOWN}}
115
116  if (a+1 <= 1)
117    clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
118}
119
120
121// Tautologies
122// The negative forms are exercised as well
123// because clang_analyzer_eval tests both possibilities.
124void tautologies(unsigned a) {
125  clang_analyzer_eval(a <= UINT_MAX); // expected-warning{{TRUE}}
126  clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
127}
128
129
130// Tautologies from outside the range of the symbol
131void tautologiesOutside(unsigned char a) {
132  clang_analyzer_eval(a <= 0x100); // expected-warning{{TRUE}}
133  clang_analyzer_eval(a < 0x100); // expected-warning{{TRUE}}
134
135  clang_analyzer_eval(a != 0x100); // expected-warning{{TRUE}}
136  clang_analyzer_eval(a != -1); // expected-warning{{TRUE}}
137
138  clang_analyzer_eval(a > -1); // expected-warning{{TRUE}}
139  clang_analyzer_eval(a >= -1); // expected-warning{{TRUE}}
140}
141
142
143// Wraparound with mixed types. Note that the analyzer assumes
144// -fwrapv semantics.
145void mixedWraparoundSanityCheck(int a) {
146  int max = INT_MAX;
147  int min = INT_MIN;
148
149  int b = a + 1;
150  clang_analyzer_eval(a == max && b != min); // expected-warning{{FALSE}}
151}
152
153void mixedWraparoundLE_GT(int a) {
154  int max = INT_MAX;
155  int min = INT_MIN;
156
157  clang_analyzer_eval((a + 2) <= (max + 1LL)); // expected-warning{{TRUE}}
158  clang_analyzer_eval((a - 2) > (min - 1LL)); // expected-warning{{TRUE}}
159  clang_analyzer_eval((a + 2LL) <= max); // expected-warning{{UNKNOWN}}
160}
161
162void mixedWraparoundGE_LT(int a) {
163  int max = INT_MAX;
164  int min = INT_MIN;
165
166  clang_analyzer_eval((a + 2) < (max + 1LL)); // expected-warning{{TRUE}}
167  clang_analyzer_eval((a - 2) >= (min - 1LL)); // expected-warning{{TRUE}}
168  clang_analyzer_eval((a - 2LL) >= min); // expected-warning{{UNKNOWN}}
169}
170
171void mixedWraparoundEQ_NE(int a) {
172  int max = INT_MAX;
173
174  clang_analyzer_eval((a + 2) != (max + 1LL)); // expected-warning{{TRUE}}
175  clang_analyzer_eval((a + 2LL) == (max + 1LL)); // expected-warning{{UNKNOWN}}
176}
177
178
179// Mixed-signedness comparisons.
180void mixedSignedness(int a, unsigned b) {
181  int sMin = INT_MIN;
182  unsigned uMin = INT_MIN;
183
184  clang_analyzer_eval(a == sMin && a != uMin); // expected-warning{{FALSE}}
185  clang_analyzer_eval(b == uMin && b != sMin); // expected-warning{{FALSE}}
186}
187
188
189// PR12206/12510 - When SimpleSValBuilder figures out that a symbol is fully
190// constrained, it should cast the value to the result type in a binary
191// operation...unless the binary operation is a comparison, in which case the
192// two arguments should be the same type, but won't match the result type.
193//
194// This is easier to trigger in C++ mode, where the comparison result type is
195// 'bool' and is thus differently sized from int on pretty much every system.
196//
197// This is not directly related to additive folding, but we use SValBuilder's
198// additive folding to tickle the bug. ExprEngine will simplify fully-constrained
199// symbols, so SValBuilder will only see them if they are (a) part of an evaluated
200// SymExpr (e.g. with additive folding) or (b) generated by a checker (e.g.
201// unix.cstring's strlen() modelling).
202void PR12206(int x) {
203  // Build a SymIntExpr, dependent on x.
204  int local = x - 1;
205
206  // Constrain the value of x.
207  int value = 1 + (1 << (8 * sizeof(1 == 1))); // not representable by bool
208  if (x != value) return;
209
210  // Constant-folding will turn (local+1) back into the symbol for x.
211  // The point of this dance is to make SValBuilder be responsible for
212  // turning the symbol into a ConcreteInt, rather than ExprEngine.
213
214  // Test relational operators.
215  clang_analyzer_eval((local + 1) >= 2); // expected-warning{{TRUE}}
216  clang_analyzer_eval(2 <= (local + 1)); // expected-warning{{TRUE}}
217
218  // Test equality operators.
219  clang_analyzer_eval((local + 1) != 1); // expected-warning{{TRUE}}
220  clang_analyzer_eval(1 != (local + 1)); // expected-warning{{TRUE}}
221}
222
223void PR12206_truncation(signed char x) {
224  // Build a SymIntExpr, dependent on x.
225  signed char local = x - 1;
226
227  // Constrain the value of x.
228  if (x != 1) return;
229
230  // Constant-folding will turn (local+1) back into the symbol for x.
231  // The point of this dance is to make SValBuilder be responsible for
232  // turning the symbol into a ConcreteInt, rather than ExprEngine.
233
234  // Construct a value that cannot be represented by 'char',
235  // but that has the same lower bits as x.
236  signed int value = 1 + (1 << 8);
237
238  // Test relational operators.
239  clang_analyzer_eval((local + 1) < value); // expected-warning{{TRUE}}
240  clang_analyzer_eval(value > (local + 1)); // expected-warning{{TRUE}}
241
242  // Test equality operators.
243  clang_analyzer_eval((local + 1) != value); // expected-warning{{TRUE}}
244  clang_analyzer_eval(value != (local + 1)); // expected-warning{{TRUE}}
245}
246
247void multiplicativeSanityTest(int x) {
248  // At one point we were ignoring the *4 completely -- the constraint manager
249  // would see x < 8 and then declare the assertion to be known false.
250  if (x*4 < 8)
251    return;
252
253  clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
254}
255