[clang] [analyzer] Improve solver (PR #112583)
Balazs Benics via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 18 04:49:55 PDT 2024
https://github.com/steakhal updated https://github.com/llvm/llvm-project/pull/112583
>From dfb86a3ddad88a9a97fff054af1bf86d746ee49d Mon Sep 17 00:00:00 2001
From: Balazs Benics <benicsbalazs at gmail.com>
Date: Wed, 16 Oct 2024 15:52:31 +0200
Subject: [PATCH] [analyzer][Solver] Improve getSymVal and friends (1/2)
Instead of just doing a lookup in the existing constraints,
let's use `getRange()` for dissambling SymSymExprs and inferring from
the constraint system what end range set we can simplify.
This means that `getSymVal` gets more expensive while getting smarter.
I don't expect it to be an issue as this API is only rarely used, and
`getRange` is used a lot more often - yet without any observable hit on
performance.
This patch also removes dead declarations of EQClass overloads.
---
.../Checkers/BitwiseShiftChecker.cpp | 3 +-
.../Core/RangeConstraintManager.cpp | 21 +++++---------
clang/test/Analysis/infeasible-sink.c | 29 +++----------------
3 files changed, 14 insertions(+), 39 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp
index 339927c165fe00..17f1214195b3ee 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BitwiseShiftChecker.cpp
@@ -177,7 +177,8 @@ BugReportPtr BitwiseShiftValidator::checkOvershift() {
RightOpStr = formatv(" '{0}'", ConcreteRight->getValue());
else {
SValBuilder &SVB = Ctx.getSValBuilder();
- if (const llvm::APSInt *MinRight = SVB.getMinValue(FoldedState, Right)) {
+ if (const llvm::APSInt *MinRight = SVB.getMinValue(FoldedState, Right);
+ MinRight && *MinRight >= LHSBitWidth) {
LowerBoundStr = formatv(" >= {0},", MinRight->getExtValue());
}
}
diff --git a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
index 70d5a609681790..ecf7974c838650 100644
--- a/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
+++ b/clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
@@ -1939,11 +1939,8 @@ class RangeConstraintManager : public RangedConstraintManager {
RangeSet::Factory F;
RangeSet getRange(ProgramStateRef State, SymbolRef Sym);
- RangeSet getRange(ProgramStateRef State, EquivalenceClass Class);
ProgramStateRef setRange(ProgramStateRef State, SymbolRef Sym,
RangeSet Range);
- ProgramStateRef setRange(ProgramStateRef State, EquivalenceClass Class,
- RangeSet Range);
RangeSet getSymLTRange(ProgramStateRef St, SymbolRef Sym,
const llvm::APSInt &Int,
@@ -2866,24 +2863,22 @@ ConditionTruthVal RangeConstraintManager::checkNull(ProgramStateRef State,
const llvm::APSInt *RangeConstraintManager::getSymVal(ProgramStateRef St,
SymbolRef Sym) const {
- const RangeSet *T = getConstraint(St, Sym);
- return T ? T->getConcreteValue() : nullptr;
+ auto &MutableSelf = const_cast<RangeConstraintManager &>(*this);
+ return MutableSelf.getRange(St, Sym).getConcreteValue();
}
const llvm::APSInt *RangeConstraintManager::getSymMinVal(ProgramStateRef St,
SymbolRef Sym) const {
- const RangeSet *T = getConstraint(St, Sym);
- if (!T || T->isEmpty())
- return nullptr;
- return &T->getMinValue();
+ auto &MutableSelf = const_cast<RangeConstraintManager &>(*this);
+ RangeSet Range = MutableSelf.getRange(St, Sym);
+ return Range.isEmpty() ? nullptr : &Range.getMinValue();
}
const llvm::APSInt *RangeConstraintManager::getSymMaxVal(ProgramStateRef St,
SymbolRef Sym) const {
- const RangeSet *T = getConstraint(St, Sym);
- if (!T || T->isEmpty())
- return nullptr;
- return &T->getMaxValue();
+ auto &MutableSelf = const_cast<RangeConstraintManager &>(*this);
+ RangeSet Range = MutableSelf.getRange(St, Sym);
+ return Range.isEmpty() ? nullptr : &Range.getMaxValue();
}
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Analysis/infeasible-sink.c b/clang/test/Analysis/infeasible-sink.c
index 9cb66fcac0b6be..a88ca42f27e441 100644
--- a/clang/test/Analysis/infeasible-sink.c
+++ b/clang/test/Analysis/infeasible-sink.c
@@ -38,7 +38,7 @@ void test1(int x) {
}
int a, b, c, d, e;
-void test2() {
+void test2(void) {
if (a == 0)
return;
@@ -50,31 +50,10 @@ void test2() {
b = d;
a -= d;
- if (a != 0)
- return;
-
- clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+ clang_analyzer_warnIfReached(); // expected-warning {{REACHABLE}}
- /* The BASELINE passes these checks ('wrning' is used to avoid lit to match)
- // The parent state is already infeasible, look at this contradiction:
- clang_analyzer_eval(b > 0); // expected-wrning{{FALSE}}
- clang_analyzer_eval(b <= 0); // expected-wrning{{FALSE}}
- // Crashes with expensive checks.
- if (b > 0) {
- clang_analyzer_warnIfReached(); // no-warning, OK
+ if (a != 0)
return;
- }
- // Should not be reachable.
- clang_analyzer_warnIfReached(); // expected-wrning{{REACHABLE}}
- */
- // The parent state is already infeasible, but we realize that only if b is
- // constrained.
- clang_analyzer_eval(b > 0); // expected-warning{{UNKNOWN}}
- clang_analyzer_eval(b <= 0); // expected-warning{{UNKNOWN}}
- if (b > 0) {
- clang_analyzer_warnIfReached(); // no-warning
- return;
- }
- clang_analyzer_warnIfReached(); // no-warning
+ clang_analyzer_warnIfReached(); // no-warning: Unreachable due to contradiction.
}
More information about the cfe-commits
mailing list