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