forked from OSchip/llvm-project
164 lines
4.2 KiB
C++
164 lines
4.2 KiB
C++
|
// RUN: %clang_analyze_cc1 %s \
|
||
|
// RUN: -analyzer-checker=core \
|
||
|
// RUN: -analyzer-checker=debug.ExprInspection \
|
||
|
// RUN: -analyzer-config eagerly-assume=false \
|
||
|
// RUN: -verify
|
||
|
|
||
|
void clang_analyzer_eval(bool);
|
||
|
void clang_analyzer_warnIfReached();
|
||
|
|
||
|
int test_legacy_behavior(int x, int y) {
|
||
|
if (y != 0)
|
||
|
return 0;
|
||
|
if (x + y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
|
||
|
return y / (x + y); // expected-warning{{Division by zero}}
|
||
|
}
|
||
|
|
||
|
int test_rhs_further_constrained(int x, int y) {
|
||
|
if (x + y != 0)
|
||
|
return 0;
|
||
|
if (y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int test_lhs_further_constrained(int x, int y) {
|
||
|
if (x + y != 0)
|
||
|
return 0;
|
||
|
if (x != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int test_lhs_and_rhs_further_constrained(int x, int y) {
|
||
|
if (x % y != 1)
|
||
|
return 0;
|
||
|
if (x != 1)
|
||
|
return 0;
|
||
|
if (y != 2)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x % y == 1); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(y == 2); // expected-warning{{TRUE}}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int test_commutativity(int x, int y) {
|
||
|
if (x + y != 0)
|
||
|
return 0;
|
||
|
if (y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(y + x == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int test_binop_when_height_is_2_r(int a, int x, int y, int z) {
|
||
|
switch (a) {
|
||
|
case 1: {
|
||
|
if (x + y + z != 0)
|
||
|
return 0;
|
||
|
if (z != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
|
||
|
break;
|
||
|
}
|
||
|
case 2: {
|
||
|
if (x + y + z != 0)
|
||
|
return 0;
|
||
|
if (y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
|
||
|
break;
|
||
|
}
|
||
|
case 3: {
|
||
|
if (x + y + z != 0)
|
||
|
return 0;
|
||
|
if (x != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
|
||
|
break;
|
||
|
}
|
||
|
case 4: {
|
||
|
if (x + y + z != 0)
|
||
|
return 0;
|
||
|
if (x + y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
|
||
|
break;
|
||
|
}
|
||
|
case 5: {
|
||
|
if (z != 0)
|
||
|
return 0;
|
||
|
if (x + y + z != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
if (y != 0)
|
||
|
return 0;
|
||
|
clang_analyzer_eval(y == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void test_equivalence_classes_are_updated(int a, int b, int c, int d) {
|
||
|
if (a + b != c)
|
||
|
return;
|
||
|
if (a != d)
|
||
|
return;
|
||
|
if (b != 0)
|
||
|
return;
|
||
|
clang_analyzer_eval(c == d); // expected-warning{{TRUE}}
|
||
|
// Keep the symbols and the constraints! alive.
|
||
|
(void)(a * b * c * d);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void test_contradiction(int a, int b, int c, int d) {
|
||
|
if (a + b != c)
|
||
|
return;
|
||
|
if (a == c)
|
||
|
return;
|
||
|
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
|
||
|
|
||
|
// Bring in the contradiction.
|
||
|
if (b != 0)
|
||
|
return;
|
||
|
clang_analyzer_warnIfReached(); // no-warning, i.e. UNREACHABLE
|
||
|
// Keep the symbols and the constraints! alive.
|
||
|
(void)(a * b * c * d);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
void test_deferred_contradiction(int e0, int b0, int b1) {
|
||
|
|
||
|
int e1 = e0 - b0; // e1 is bound to (reg_$0<int e0>) - (reg_$1<int b0>)
|
||
|
(void)(b0 == 2); // bifurcate
|
||
|
|
||
|
int e2 = e1 - b1;
|
||
|
if (e2 > 0) { // b1 != e1
|
||
|
clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
|
||
|
// Here, e1 is still bound to (reg_$0<int e0>) - (reg_$1<int b0>) but we
|
||
|
// should be able to simplify it to (reg_$0<int e0>) - 2 and thus realize
|
||
|
// the contradiction.
|
||
|
if (b1 == e1) {
|
||
|
clang_analyzer_warnIfReached(); // no-warning, i.e. UNREACHABLE
|
||
|
(void)(b0 * b1 * e0 * e1 * e2);
|
||
|
}
|
||
|
}
|
||
|
}
|