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