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