mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-16 17:16:42 +00:00

Generalize the SymbolIDs used for SymbolData to all SymExprs and use these IDs for comparison SymbolRef keys in various containers, such as ConstraintMap. These IDs are superior to raw pointer values because they are more controllable and are not randomized across executions (unlike [pointers](https://en.wikipedia.org/wiki/Address_space_layout_randomization)). These IDs order is stable across runs because SymExprs are allocated in the same order. Stability of the constraint order is important for the stability of the analyzer results. I evaluated this change on a set of 200+ open-source C and C++ projects with the total number of ~78 000 symbolic-execution issues passing Z3 refutation. This patch reduced the run-to-run churn (flakiness) in SE issues from 80-90 to 30-40 (out of 78K) in our CSA deployment (in our setting flaky issues are mostly due to Z3 refutation instability). Note, most of the issue churn (flakiness) is caused by the mentioned Z3 refutation. With Z3 refutation disabled, issue churn goes down to ~10 issues out of 83K and this patch has no effect on appearing/disappearing issues between runs. It however, seems to reduce the volatility of the execution flow: before we had 40-80 issues with changed execution flow, after - 10-30. Importantly, this change is necessary for the next step in stabilizing analysis results by caching Z3 query outcomes between analysis runs (work in progress). Across our admittedly noisy CI runs, I detected no significant effect on memory footprint or analysis time. This PR reapplies https://github.com/llvm/llvm-project/pull/121551 with a fix to a g++ compiler error reported on some build bots CPP-5919
75 lines
2.3 KiB
C
75 lines
2.3 KiB
C
// RUN: %clang_analyze_cc1 %s \
|
|
// RUN: -analyzer-checker=core,debug.ExprInspection \
|
|
// RUN: -analyzer-config eagerly-assume=false \
|
|
// RUN: -verify
|
|
|
|
void clang_analyzer_eval(int);
|
|
void clang_analyzer_dump(int);
|
|
|
|
int test(int x, int y) {
|
|
|
|
clang_analyzer_dump(-x); // expected-warning{{-reg_$0<int x>}}
|
|
clang_analyzer_dump(~x); // expected-warning{{~reg_$0<int x>}}
|
|
int z = x + y;
|
|
clang_analyzer_dump(-z); // expected-warning{{-((reg_$0<int x>) + (reg_$3<int y>))}}
|
|
clang_analyzer_dump(-(x + y)); // expected-warning{{-((reg_$0<int x>) + (reg_$3<int y>))}}
|
|
clang_analyzer_dump(-x + y); // expected-warning{{(-reg_$0<int x>) + (reg_$3<int y>)}}
|
|
|
|
if (-x == 0) {
|
|
clang_analyzer_eval(-x == 0); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-x > 0); // expected-warning{{FALSE}}
|
|
clang_analyzer_eval(-x < 0); // expected-warning{{FALSE}}
|
|
}
|
|
if (~y == 0) {
|
|
clang_analyzer_eval(~y == 0); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(~y > 0); // expected-warning{{FALSE}}
|
|
clang_analyzer_eval(~y < 0); // expected-warning{{FALSE}}
|
|
}
|
|
(void)(x);
|
|
return 42;
|
|
}
|
|
|
|
void test_svalbuilder_simplification_add(int x, int y) {
|
|
if (x + y != 3)
|
|
return;
|
|
clang_analyzer_eval(-(x + y) == -3); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-(y + x) == -3); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void test_svalbuilder_simplification_mul(int x, int y) {
|
|
if (x * y != 3)
|
|
return;
|
|
clang_analyzer_eval(-(x * y) == -3); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-(y * x) == -3); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void test_svalbuilder_simplification_and(int x, int y) {
|
|
if ((x & y) != 3)
|
|
return;
|
|
clang_analyzer_eval(-(x & y) == -3); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-(y & x) == -3); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void test_svalbuilder_simplification_or(int x, int y) {
|
|
if ((x | y) != 3)
|
|
return;
|
|
clang_analyzer_eval(-(x | y) == -3); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-(y | x) == -3); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
void test_svalbuilder_simplification_xor(int x, int y) {
|
|
if ((x ^ y) != 3)
|
|
return;
|
|
clang_analyzer_eval(-(x ^ y) == -3); // expected-warning{{TRUE}}
|
|
clang_analyzer_eval(-(y ^ x) == -3); // expected-warning{{TRUE}}
|
|
}
|
|
|
|
int test_fp(int flag) {
|
|
int value;
|
|
if (flag == 0)
|
|
value = 1;
|
|
if (-flag == 0)
|
|
return value; // no-warning
|
|
return 42;
|
|
}
|