Files
codeql/cpp/ql/test/library-tests/rangeanalysis/SimpleRangeAnalysis/test.c
2025-11-14 12:26:23 +01:00

954 lines
22 KiB
C

struct List {
struct List* next;
};
int test1(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count = count+1;
}
return count;
}
int test2(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count = (count+1) % 10;
}
return count;
}
int test3(struct List* p) {
int count = 0;
for (; p; p = p->next) {
count++;
count = count % 10;
}
return count;
}
int test4() {
int i = 0;
int total = 0;
for (i = 0; i < 2; i = i+1) {
total += i;
}
return total + i;
}
int test5() {
int i = 0;
int total = 0;
for (i = 0; i < 2; i++) {
total += i;
}
return total + i;
}
int test6() {
int i = 0;
int total = 0;
for (i = 0; i+2 < 4; i = i+1) {
total += i;
}
return total + i;
}
int test7(int i) {
if (i < 4) {
if (i < 5) {
return i;
}
}
return 1;
}
int test8(int x, int y) {
if (-1000 < y && y < 10) {
if (x < y-2) {
return x;
}
}
return y;
}
int test9(int x, int y) {
if (y == 0) {
if (x < 4) {
return 0;
}
} else {
if (x < 4) {
return 1;
}
}
return x;
}
int test10(int x, int y) {
if (y > 7) {
if (x < y) {
return 0;
}
return x;
}
return 1;
}
int test11(char *p) {
char c;
c = *p;
if (c != '\0')
*p++ = '\0';
if (c == ':') {
c = *p;
if (c != '\0')
*p++ = '\0';
if (c != ',')
return 1;
}
return 0;
}
typedef unsigned long long size_type;
size_type test12_helper() {
static size_type n = 0;
return n++;
}
int test12() {
size_type Start = 0;
while (Start <= test12_helper()-1)
{
const size_type Length = test12_helper();
Start += Length + 1;
}
return 1;
}
// Tests for overflow conditions.
int test13(char c, int i) {
unsigned char uc = c;
unsigned int x = 0;
unsigned int y = x-1;
int z = i+1;
return (double)(c + i + uc + x + y + z);
}
// Regression test for ODASA-6013.
int test14(int x) {
int x0 = (int)(char)x;
int x1 = (int)(unsigned char)x;
int x2 = (int)(unsigned short)x;
int x3 = (int)(unsigned int)x;
char c0 = x;
unsigned short s0 = x;
return x0 + x1 + x2 + x3 + c0 + s0;
}
long long test15(long long x) {
return (x > 0 && x == (int)x) ? x : -1;
}
// Tests for unary operators.
int test_unary(int a) {
int total = 0;
if (3 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (0 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 11) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 1) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= 0) {
int b = +a;
int c = -a;
total += b+c;
}
if (-7 <= a && a <= -2) {
int b = +a;
int c = -a;
total += b+c;
}
return total;
}
// Tests for multiplication.
int test_mult01(int a, int b) {
int total = 0;
if (3 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // 15 .. 253
total += r;
}
if (3 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -143 .. 253
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 0
total += r;
}
if (3 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. -21
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult02(int a, int b) {
int total = 0;
if (0 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (0 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -143 .. 253
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 0
total += r;
}
if (0 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. 0
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult03(int a, int b) {
int total = 0;
if (-17 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 253
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= 0) {
int r = a*b; // -143 .. 221
total += r;
}
if (-17 <= a && a <= 11 && -13 <= b && b <= -7) {
int r = a*b; // -143 .. 221
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult04(int a, int b) {
int total = 0;
if (-17 <= a && a <= 0 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= 0 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 221
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= 0) {
int r = a*b; // 0 .. 221
total += r;
}
if (-17 <= a && a <= 0 && -13 <= b && b <= -7) {
int r = a*b; // 0 .. 221
total += r;
}
return total;
}
// Tests for multiplication.
int test_mult05(int a, int b) {
int total = 0;
if (-17 <= a && a <= -2 && 5 <= b && b <= 23) {
int r = a*b; // -391 .. -10
total += r;
}
if (-17 <= a && a <= -2 && 0 <= b && b <= 23) {
int r = a*b; // -391 .. 0
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= 23) {
int r = a*b; // -391 .. 221
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= 0) {
int r = a*b; // 0 .. 221
total += r;
}
if (-17 <= a && a <= -2 && -13 <= b && b <= -7) {
int r = a*b; // 14 .. 221
total += r;
}
return total;
}
int test16(int x) {
int d, i = 0;
if (x < 0) {
return -1;
}
while (i < 3) {
i++;
}
d = i;
if (x < 0) { // Comparison is always false.
if (d > -x) { // Unreachable code.
return 1;
}
}
return 0;
}
// Test ternary expression upper bounds.
unsigned int test_ternary01(unsigned int x) {
unsigned int y1, y2, y3, y4, y5, y6, y7, y8;
y1 = x < 100 ? x : 10; // y1 < 100
y2 = x >= 100 ? 10 : x; // y2 < 100
y3 = 0;
y4 = 0;
y5 = 0;
y6 = 0;
y7 = 0;
y8 = 0;
if (x < 300) {
y3 = x ?: 5; // y3 < 300
y4 = x ?: 500; // y4 <= 500
y5 = (x+1) ?: 500; // y5 <= 300
y6 = ((unsigned char)(x+1)) ?: 5; // y6 < 256
y7 = ((unsigned char)(x+1)) ?: 500; // y7 <= 500
y8 = ((unsigned short)(x+1)) ?: 500; // y8 <= 300
}
return y1 + y2 + y3 + y4 + y5 + y6 + y7 + y8;
}
// Test ternary expression lower bounds.
unsigned int test_ternary02(unsigned int x) {
unsigned int y1, y2, y3, y4, y5;
y1 = x > 100 ? x : 110; // y1 > 100
y2 = x <= 100 ? 110 : x; // y2 > 100
y3 = 1000;
y4 = 1000;
y5 = 1000;
if (x >= 300) {
y3 = (x-300) ?: 5; // y3 >= 0
y4 = (x-200) ?: 5; // y4 >= 100
y5 = ((unsigned char)(x-200)) ?: 5; // y6 >= 0
}
return y1 + y2 + y3 + y4 + y5;
}
// Test that nested ternary expressions of literals doesn't cause performance blow up.
double test_ternary_nested_of_literals(double m, double n, double o, double p, double q) {
double a = m ? n ? o ? p ? q ? 0.47438827 : 0.14333887 : 0.35279203 : 0.39206458 : 0.21540225 : 0.40496805;
double b = m ? n ? o ? p ? q ? 0.34183348 : 0.35334640 : 0.22247853 : 0.32661893 : 0.59270465 : 0.52977410;
double c = m ? n ? o ? p ? q ? 0.77429603 : 0.31478084 : 0.31235514 : 0.05121256 : 0.79310745 : 0.67981451;
double d = m ? n ? o ? p ? q ? 0.44729556 : 0.80599202 : 0.98997262 : 0.59952732 : 0.36976948 : 0.83866835;
double e = m ? n ? o ? p ? q ? 0.49311828 : 0.90389911 : 0.10597712 : 0.21778426 : 0.72485966 : 0.68734874;
double f = m ? n ? o ? p ? q ? 0.47452848 : 0.10786650 : 0.11884576 : 0.76164052 : 0.34808892 : 0.58440865;
double g = m ? n ? o ? p ? q ? 0.02524326 : 0.82905046 : 0.95823075 : 0.12516558 : 0.85235179 : 0.36232384;
double h = m ? n ? o ? p ? q ? 0.38708626 : 0.32876044 : 0.14963485 : 0.45041108 : 0.48640909 : 0.84331272;
double i = m ? n ? o ? p ? q ? 0.15755063 : 0.77086833 : 0.26428481 : 0.14800508 : 0.37428143 : 0.05328182;
double j = m ? n ? o ? p ? q ? 0.41736536 : 0.76826628 : 0.27643238 : 0.55679274 : 0.39468857 : 0.69072144;
double k = m ? n ? o ? p ? q ? 0.88955345 : 0.29904824 : 0.76242583 : 0.20519110 : 0.88745559 : 0.81372798;
double l = m ? n ? o ? p ? q ? 0.42186276 : 0.53843358 : 0.44996679 : 0.13204114 : 0.52031241 : 0.42762647;
// Since the abstract interpretation of `+` produces a product of the bounds
// of the input operands, `output` will have k^12 bounds, where `k` is the
// number of bounds that each of the variables above have. This blows up
// unless `k` is 1.
double output = a + b + c + d + e + f + g + h + i + j + k + l;
return output;
}
int repeated_if_statements(unsigned int rhs) {
// Test how many bounds we estimate for `if` statements without `else`
// branches where the following node is both a normal phi node and a guard phi
// node.
if (rhs < 12) { rhs << 1; }
if (rhs < 13) { rhs << 1; }
if (rhs < 14) { rhs << 1; }
if (rhs < 15) { rhs << 1; }
if (rhs < 16) { rhs << 1; }
return rhs; // rhs has 6 bounds
}
int ne_phi_nodes(int a, int b) {
if (a == 17) {
if (b == 23) {
a += b;
}
if (a == 18) {
b = 10;
}
}
// The statement below is an NE phi node for the access `a` in both `a == 17`
// and `a == 18`.
int c = a + b;
return a + b;
}
unsigned int conditional_nested_guards(unsigned int ip) {
// This tests a combinatorial explosion that can happen from a large number of
// nested linear guards.
unsigned int special_number =
(14 * ip > (2 * ip + 1) * 17 + (2 * ip + 1 + 1) * 17
? 14 * ip
: (2 * ip + 1) * 14 + (2 * ip + 1 + 1) * 17) >
(2 * (ip * 14 + 32) +
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 > (17 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
2 * ip * 14 + (2 * ip + 1) * 17
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 2 * ip * 14 + (2 * ip + 1) * 17) >
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 > (17 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
(14 * ip > (ip + 1) * 17 ? 17 * ip : (ip + 1) * 17)
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 > (17 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 14 * ip > (ip + 1) * 17
? 14 * ip
: (ip + 1) * 14)
? 2 * (ip * 14 + 32) +
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
2 * ip * 14 + (2 * ip + 1) * 17
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 2 * ip * 14 + (2 * ip + 1) * 17)
: 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
(14 * ip > (ip + 1) * 17 ? 17 * ip : (ip + 1) * 17)
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 14 * ip > (ip + 1) * 17
? 14 * ip
: (ip + 1) * 14)
? 14 * ip > (2 * ip + 1) * 17 + (2 * ip + 1 + 1) * 17
? 14 * ip
: (2 * ip + 1) * 14 + (2 * ip + 1 + 1) * 17
: 2 * (ip * 14 + 32) +
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
2 * ip * 14 + (2 * ip + 1) * 17
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 2 * ip * 14 + (2 * ip + 1) * 17) >
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
(14 * ip > (ip + 1) * 17 ? 17 * ip : (ip + 1) * 17)
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 14 * ip > (ip + 1) * 17
? 14 * ip
: (ip + 1) * 14)
? 2 * (ip * 14 + 32) +
(4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
2 * ip * 14 + (2 * ip + 1) * 17
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 2 * ip * 14 + (2 * ip + 1) * 17)
: 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip) >
(14 * ip > (ip + 1) * 17 ? 17 * ip : (ip + 1) * 17)
? 4 * (ip * 14 + 32) +
(2 * ip * 14 + 32) +
2 * (ip * 14 + 64) +
((2 * ip + 1) * 14 >
(14 * (2 * ip) > 17 * ip ? 17 * (2 * ip) : 17 * ip)
? (2 * ip + 1) * 14
: 14 * (2 * ip) > 17 * ip
? 14 * (2 * ip)
: 14 * ip)
: 14 * ip > (ip + 1) * 17
? 14 * ip
: (ip + 1) * 14;
return special_number;
}
int many_conditional_assignments(int c1, int c2, int c3, int c4, int c5) {
// This tests a combinatorial explosion that can happen from many conditional
// assignments, since each conditional assignment doubles the number of
// bounds.
int x = 0;
if (c1) { x += 748596; }
if (c2) { x += 84652395; }
if (c3) { x += 3675895; }
if (c4) { x += 98634; }
if (c5) { x += 7834985; }
if (c1 && c2) { x += 938457398; }
if (c1 && c3) { x += 73895648; }
if (c1 && c4) { x += 12345432; }
if (c1 && c5) { x += 38847; }
if (c2 && c3) { x += 234; }
// x now has 2^10 bounds, the 10 additions below give (2^10)^10 bounds
int y = x + x + x + x + x + x + x + x + x + x + x + x;
return y;
}
// Test the comma expression.
unsigned int test_comma01(unsigned int x) {
unsigned int y = x < 100 ? x : 100;
unsigned int y1;
unsigned int y2;
y1 = (++y, y);
y2 = (y++, y += 3, y);
return y1 + y2;
}
void out(int i);
void test17() {
int i, j;
i = 10;
out(i); // 10
i = 10;
i += 10;
out(i); // 20
i = 40;
i -= 10;
out(i); // 30
i = j = 40;
out(i); // 40
i = (j += 10);
out(i); // 50
i = 20 + (j -= 10);
out(i); // 60
}
// Tests for unsigned multiplication.
int test_unsigned_mult01(unsigned int a, unsigned b) {
int total = 0;
if (3 <= a && a <= 11 && 5 <= b && b <= 23) {
int r = a*b; // 15 .. 253
total += r;
}
if (3 <= a && a <= 11 && 0 <= b && b <= 23) {
int r = a*b; // 0 .. 253
total += r;
}
if (3 <= a && a <= 11 && 13 <= b && b <= 23) {
int r = a*b; // 39 .. 253
total += r;
}
return total;
}
int test_unsigned_mult02(unsigned b) {
int total = 0;
if (5 <= b && b <= 23) {
int r = 11*b; // 55 .. 253
total += r;
}
if (0 <= b && b <= 23) {
int r = 11*b; // 0 .. 253
total += r;
}
if (13 <= b && b <= 23) {
int r = 11*b; // 143 .. 253
total += r;
}
return total;
}
unsigned long mult_rounding() {
unsigned long x, y, xy;
x = y = 1000000003UL; // 1e9 + 3
xy = x * y;
return xy; // BUG: upper bound should be >= 1000000006000000009UL
}
unsigned long mult_overflow() {
unsigned long x, y, xy;
x = 274177UL;
y = 67280421310721UL;
xy = x * y;
return xy; // BUG: upper bound should be >= 18446744073709551617UL
}
unsigned long mult_lower_bound(unsigned int ui, unsigned long ul) {
if (ui >= 10) {
unsigned long result = (unsigned long)ui * ui;
return result; // BUG: upper bound should be >= 18446744065119617025
}
if (ul >= 10) {
unsigned long result = ul * ul;
return result; // lower bound is correctly 0 (overflow is possible)
}
return 0;
}
unsigned long mul_assign(unsigned int ui) {
if (ui <= 10 && ui >= 2) {
ui *= ui + 0;
return ui; // 4 .. 100
}
unsigned int uiconst = 10;
uiconst *= 4;
unsigned long ulconst = 10;
ulconst *= 4;
return uiconst + ulconst; // 40 .. 40 for both
}
int mul_by_constant(int i, int j) {
if (i >= -1 && i <= 2) {
i = 5 * i;
out(i); // -5 .. 10
i = i * -3;
out(i); // -30 .. 15
i *= 7;
out(i); // -210 .. 105
i *= -11;
out(i); // -1155 .. 2310
}
if (i == -1) {
i = i * (int)0xffFFffFF; // fully converted literal is -1
out(i); // 1 .. 1
}
i = i * -1;
out( i); // -2^31 .. 2^31-1
signed char sc = 1;
i = (*&sc *= 2);
out(sc); // demonstrate that we couldn't analyze the LHS of the `*=` above...
out(i); // -128 .. 127 // ... but we can still bound its result by its type.
return 0;
}
int notequal_type_endpoint(unsigned n) {
out(n); // 0 ..
if (n > 0) {
out(n); // 1 ..
}
if (n != 0) {
out(n); // 1 ..
} else {
out(n); // 0 .. 0
}
if (!n) {
out(n); // 0 .. 0
} else {
out(n); // 1 ..
}
while (n != 0) {
n--; // 1 ..
}
out(n); // 0 .. 0
}
void notequal_refinement(short n) {
if (n < 0)
return;
if (n == 0) {
out(n); // 0 .. 0
} else {
out(n); // 1 ..
}
if (n) {
out(n); // 1 ..
} else {
out(n); // 0 .. 0
}
while (n != 0) {
n--; // 1 ..
}
out(n); // 0 .. 0
}
void notequal_variations(short n, float f) {
if (n != 0) {
if (n >= 0) {
out(n); // 1 .. [BUG: we can't handle `!=` coming first]
}
}
if (n >= 5) {
if (2 * n - 10 == 0) { // Same as `n == 10/2` (modulo overflow)
return;
}
out(n); // 6 ..
}
if (n != -32768 && n != -32767) {
out(n); // -32766 ..
}
if (n >= 0) {
n ? n : n; // ? 1.. : 0..0
!n ? n : n; // ? 0..0 : 1..
}
}
void two_bounds_from_one_test(short ss, unsigned short us) {
// These tests demonstrate how the range analysis is often able to deduce
// both an upper bound and a lower bound even when there is only one
// inequality in the source. For example `signedInt < 4U` establishes that
// `signedInt >= 0` since if `signedInt` were negative then it would be
// greater than 4 in the unsigned comparison.
if (ss < sizeof(int)) { // Lower bound added in `linearBoundFromGuard`
out(ss); // 0 .. 3
}
if (ss < 0x8001) { // Lower bound removed in `getDefLowerBounds`
out(ss); // -32768 .. 32767
}
if ((short)us >= 0) {
out(us); // 0 .. 32767
}
if ((short)us >= -1) {
out(us); // 0 .. 65535
}
if (ss >= sizeof(int)) { // test is true for negative numbers
out(ss); // -32768 .. 32767
}
if (ss + 1 < sizeof(int)) {
out(ss); // -1 .. 2
}
}
void widen_recursive_expr() {
int s;
for (s = 0; s < 10; s++) {
int result = s + s; // 0 .. 9 [BUG: upper bound is 15 due to widening]
out(result); // 0 .. 18 [BUG: upper bound is 127 due to double widening]
}
}
void guard_bound_out_of_range(void) {
int i = 0;
if (i < 0) {
out(i); // unreachable [BUG: is -max .. +max]
}
unsigned int u = 0;
if (u < 0) {
out(u); // unreachable [BUG: is 0 .. +max]
}
}
void test_mod(int s) {
int s2 = s % 5;
out(s2); // -4 .. 4
}
void exit(int);
void guard_with_exit(int x, int y) {
if (x) {
if (y != 0) {
exit(0);
}
}
out(y); // ..
// This test ensures that we correctly identify
// that the upper bound for y is max_int when calling `out(y)`.
// The RangeSsa will place guardPhi on `out(y)`, and consequently there is no
// frontier phi node at out(y).
}
void test(int x) {
if (x >= 10) {
return;
}
// The basic block below has two predecessors.
label:
out(x);
goto label;
}
void test_overflow() {
const int x = 2147483647; // 2^31-1
const int y = 256;
if ((x + y) <= 512) {
out(x);
out(y);
}
}