1// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify -analyzer-constraints=range -Wno-tautological-compare %s
2
3void clang_analyzer_eval(bool);
4
5#define UINT_MAX (~0U)
6#define INT_MAX (UINT_MAX & (UINT_MAX >> 1))
7#define INT_MIN (-INT_MAX - 1)
8
9//---------------
10//  Plus/minus
11//---------------
12
13void separateExpressions (int a) {
14  int b = a + 1;
15  --b;
16
17  clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
18}
19
20void oneLongExpression (int a) {
21  // Expression canonicalization should still allow this to work, even though
22  // the first term is on the left.
23  int b = 15 + a + 15 - 10 - 20;
24
25  clang_analyzer_eval(a != 0 && b == 0); // expected-warning{{FALSE}}
26}
27
28void mixedTypes (int a) {
29  // Different additive types should not cause crashes when constant-folding.
30  // This is part of PR7406.
31  int b = a + 1LL;
32  clang_analyzer_eval(a != 0 && (b-1) == 0); // not crash, expected-warning{{FALSE}}
33
34  int c = a + 1U;
35  clang_analyzer_eval(a != 0 && (c-1) == 0); // not crash, expected-warning{{FALSE}}
36}
37
38//---------------
39//  Comparisons
40//---------------
41
42// Equality and inequality only
43void eq_ne (unsigned a) {
44  if (a == UINT_MAX) {
45    clang_analyzer_eval(a+1 == 0); // expected-warning{{TRUE}}
46    clang_analyzer_eval(a-1 == UINT_MAX-1); // expected-warning{{TRUE}}
47  } else {
48    clang_analyzer_eval(a+1 != 0); // expected-warning{{TRUE}}
49    clang_analyzer_eval(a-1 != UINT_MAX-1); // expected-warning{{TRUE}}
50  }
51}
52
53// Mixed typed inequalities (part of PR7406)
54// These should not crash.
55void mixed_eq_ne (int a) {
56  if (a == 1) {
57    clang_analyzer_eval(a+1U == 2); // expected-warning{{TRUE}}
58    clang_analyzer_eval(a-1U == 0); // expected-warning{{TRUE}}
59  } else {
60    clang_analyzer_eval(a+1U != 2); // expected-warning{{TRUE}}
61    clang_analyzer_eval(a-1U != 0); // expected-warning{{TRUE}}
62  }
63}
64
65
66// Simple order comparisons with no adjustment
67void baselineGT (unsigned a) {
68  if (a > 0)
69    clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
70  else
71    clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
72}
73
74void baselineGE (unsigned a) {
75  if (a >= UINT_MAX)
76    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
77  else
78    clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
79}
80
81void baselineLT (unsigned a) {
82  if (a < UINT_MAX)
83    clang_analyzer_eval(a != UINT_MAX); // expected-warning{{TRUE}}
84  else
85    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
86}
87
88void baselineLE (unsigned a) {
89  if (a <= 0)
90    clang_analyzer_eval(a == 0); // expected-warning{{TRUE}}
91  else
92    clang_analyzer_eval(a != 0); // expected-warning{{TRUE}}
93}
94
95
96// Adjustment gives each of these an extra solution!
97void adjustedGT (unsigned a) {
98  clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
99}
100
101void adjustedGE (unsigned a) {
102  clang_analyzer_eval(a-1 > UINT_MAX-1); // expected-warning{{UNKNOWN}}
103
104  if (a-1 >= UINT_MAX-1)
105    clang_analyzer_eval(a == UINT_MAX); // expected-warning{{UNKNOWN}}
106}
107
108void adjustedLT (unsigned a) {
109  clang_analyzer_eval(a+1 < 1); // expected-warning{{UNKNOWN}}
110}
111
112void adjustedLE (unsigned a) {
113  clang_analyzer_eval(a+1 <= 1); // expected-warning{{UNKNOWN}}
114
115  if (a+1 <= 1)
116    clang_analyzer_eval(a == 0); // expected-warning{{UNKNOWN}}
117}
118
119
120// Tautologies
121// The negative forms are exercised as well
122// because clang_analyzer_eval tests both possibilities.
123void tautologies(unsigned a) {
124  clang_analyzer_eval(a <= UINT_MAX); // expected-warning{{TRUE}}
125  clang_analyzer_eval(a >= 0); // expected-warning{{TRUE}}
126}
127
128
129// Tautologies from outside the range of the symbol
130void tautologiesOutside(unsigned char a) {
131  clang_analyzer_eval(a <= 0x100); // expected-warning{{TRUE}}
132  clang_analyzer_eval(a < 0x100); // expected-warning{{TRUE}}
133
134  clang_analyzer_eval(a != 0x100); // expected-warning{{TRUE}}
135  clang_analyzer_eval(a != -1); // expected-warning{{TRUE}}
136
137  clang_analyzer_eval(a > -1); // expected-warning{{TRUE}}
138  clang_analyzer_eval(a >= -1); // expected-warning{{TRUE}}
139}
140
141
142// Wraparound with mixed types. Note that the analyzer assumes
143// -fwrapv semantics.
144void mixedWraparoundSanityCheck(int a) {
145  int max = INT_MAX;
146  int min = INT_MIN;
147
148  int b = a + 1;
149  clang_analyzer_eval(a == max && b != min); // expected-warning{{FALSE}}
150}
151
152void mixedWraparoundLE_GT(int a) {
153  int max = INT_MAX;
154  int min = INT_MIN;
155
156  clang_analyzer_eval((a + 2) <= (max + 1LL)); // expected-warning{{TRUE}}
157  clang_analyzer_eval((a - 2) > (min - 1LL)); // expected-warning{{TRUE}}
158  clang_analyzer_eval((a + 2LL) <= max); // expected-warning{{UNKNOWN}}
159}
160
161void mixedWraparoundGE_LT(int a) {
162  int max = INT_MAX;
163  int min = INT_MIN;
164
165  clang_analyzer_eval((a + 2) < (max + 1LL)); // expected-warning{{TRUE}}
166  clang_analyzer_eval((a - 2) >= (min - 1LL)); // expected-warning{{TRUE}}
167  clang_analyzer_eval((a - 2LL) >= min); // expected-warning{{UNKNOWN}}
168}
169
170void mixedWraparoundEQ_NE(int a) {
171  int max = INT_MAX;
172
173  clang_analyzer_eval((a + 2) != (max + 1LL)); // expected-warning{{TRUE}}
174  clang_analyzer_eval((a + 2LL) == (max + 1LL)); // expected-warning{{UNKNOWN}}
175}
176
177
178// Mixed-signedness comparisons.
179void mixedSignedness(int a, unsigned b) {
180  int sMin = INT_MIN;
181  unsigned uMin = INT_MIN;
182
183  clang_analyzer_eval(a == sMin && a != uMin); // expected-warning{{FALSE}}
184  clang_analyzer_eval(b == uMin && b != sMin); // expected-warning{{FALSE}}
185}
186
187void mixedSignedness2(int a) {
188  if (a != -1)
189    return;
190  clang_analyzer_eval(a == UINT_MAX); // expected-warning{{TRUE}}
191}
192
193void mixedSignedness3(unsigned a) {
194  if (a != UINT_MAX)
195    return;
196  clang_analyzer_eval(a == -1); // expected-warning{{TRUE}}
197}
198
199
200void multiplicativeSanityTest(int x) {
201  // At one point we were ignoring the *4 completely -- the constraint manager
202  // would see x < 8 and then declare the assertion to be known false.
203  if (x*4 < 8)
204    return;
205
206  clang_analyzer_eval(x == 3); // expected-warning{{UNKNOWN}}
207}
208