[clang] 0a17896 - [Analyzer][Core] Make SValBuilder to better simplify svals with 3 symbols in the tree
Gabor Marton via cfe-commits
cfe-commits at lists.llvm.org
Tue Nov 30 02:27:33 PST 2021
Author: Gabor Marton
Date: 2021-11-30T11:24:59+01:00
New Revision: 0a17896fe6fdbbde1f9d3ffbb10a4f3bfa8960f9
URL: https://github.com/llvm/llvm-project/commit/0a17896fe6fdbbde1f9d3ffbb10a4f3bfa8960f9
DIFF: https://github.com/llvm/llvm-project/commit/0a17896fe6fdbbde1f9d3ffbb10a4f3bfa8960f9.diff
LOG: [Analyzer][Core] Make SValBuilder to better simplify svals with 3 symbols in the tree
Add the capability to simplify more complex constraints where there are 3
symbols in the tree. In this change I extend simplifySVal to query constraints
of children sub-symbols in a symbol tree. (The constraint for the parent is
asked in getKnownValue.)
Differential Revision: https://reviews.llvm.org/D103317
Added:
clang/test/Analysis/svalbuilder-simplify-compound-svals.cpp
Modified:
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
clang/test/Analysis/taint-tester.c
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index e179ecc33481..4ca35dd06ae5 100644
--- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1102,7 +1102,6 @@ const llvm::APSInt *SimpleSValBuilder::getKnownValue(ProgramStateRef state,
if (SymbolRef Sym = V.getAsSymbol())
return state->getConstraintManager().getSymVal(state, Sym);
- // FIXME: Add support for SymExprs.
return nullptr;
}
@@ -1134,6 +1133,24 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
return cache(Sym, SVB.makeSymbolVal(Sym));
}
+ // Return the known const value for the Sym if available, or return Undef
+ // otherwise.
+ SVal getConst(SymbolRef Sym) {
+ const llvm::APSInt *Const =
+ State->getConstraintManager().getSymVal(State, Sym);
+ if (Const)
+ return Loc::isLocType(Sym->getType()) ? (SVal)SVB.makeIntLocVal(*Const)
+ : (SVal)SVB.makeIntVal(*Const);
+ return UndefinedVal();
+ }
+
+ SVal getConstOrVisit(SymbolRef Sym) {
+ const SVal Ret = getConst(Sym);
+ if (Ret.isUndef())
+ return Visit(Sym);
+ return Ret;
+ }
+
public:
Simplifier(ProgramStateRef State)
: State(State), SVB(State->getStateManager().getSValBuilder()) {}
@@ -1147,15 +1164,14 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
return SVB.makeSymbolVal(S);
}
- // TODO: Support SymbolCast. Support IntSymExpr when/if we actually
- // start producing them.
+ // TODO: Support SymbolCast.
SVal VisitSymIntExpr(const SymIntExpr *S) {
auto I = Cached.find(S);
if (I != Cached.end())
return I->second;
- SVal LHS = Visit(S->getLHS());
+ SVal LHS = getConstOrVisit(S->getLHS());
if (isUnchanged(S->getLHS(), LHS))
return skip(S);
@@ -1187,9 +1203,10 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
if (I != Cached.end())
return I->second;
- SVal RHS = Visit(S->getRHS());
+ SVal RHS = getConstOrVisit(S->getRHS());
if (isUnchanged(S->getRHS(), RHS))
return skip(S);
+
SVal LHS = SVB.makeIntVal(S->getLHS());
return cache(
S, SVB.evalBinOp(State, S->getOpcode(), LHS, RHS, S->getType()));
@@ -1208,8 +1225,9 @@ SVal SimpleSValBuilder::simplifySVal(ProgramStateRef State, SVal V) {
Loc::isLocType(S->getRHS()->getType()))
return skip(S);
- SVal LHS = Visit(S->getLHS());
- SVal RHS = Visit(S->getRHS());
+ SVal LHS = getConstOrVisit(S->getLHS());
+ SVal RHS = getConstOrVisit(S->getRHS());
+
if (isUnchanged(S->getLHS(), LHS) && isUnchanged(S->getRHS(), RHS))
return skip(S);
diff --git a/clang/test/Analysis/svalbuilder-simplify-compound-svals.cpp b/clang/test/Analysis/svalbuilder-simplify-compound-svals.cpp
new file mode 100644
index 000000000000..0417507476ee
--- /dev/null
+++ b/clang/test/Analysis/svalbuilder-simplify-compound-svals.cpp
@@ -0,0 +1,76 @@
+// RUN: %clang_analyze_cc1 %s \
+// RUN: -analyzer-checker=core \
+// RUN: -analyzer-checker=debug.ExprInspection \
+// RUN: -analyzer-config eagerly-assume=false \
+// RUN: -verify
+
+// Here we test whether the SValBuilder is capable to simplify existing
+// compound SVals (where there are at leaset 3 symbols in the tree) based on
+// newly added constraints.
+
+void clang_analyzer_eval(bool);
+void clang_analyzer_warnIfReached();
+
+void test_left_tree_constrained(int x, int y, int z) {
+ if (x + y + z != 0)
+ return;
+ if (x + y != 0)
+ return;
+ clang_analyzer_eval(x + y + z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x + y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
+ x = y = z = 1;
+ return;
+}
+
+void test_right_tree_constrained(int x, int y, int z) {
+ if (x + y * z != 0)
+ return;
+ if (y * z != 0)
+ return;
+ clang_analyzer_eval(x + y * z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(y * z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x == 0); // expected-warning{{TRUE}}
+ return;
+}
+
+void test_left_tree_constrained_minus(int x, int y, int z) {
+ if (x - y - z != 0)
+ return;
+ if (x - y != 0)
+ return;
+ clang_analyzer_eval(x - y - z == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(x - y == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval(z == 0); // expected-warning{{TRUE}}
+ x = y = z = 1;
+ return;
+}
+
+void test_SymInt_constrained(int x, int y, int z) {
+ if (x * y * z != 4)
+ return;
+ if (z != 2)
+ return;
+ if (x * y == 3) {
+ clang_analyzer_warnIfReached(); // no-warning
+ return;
+ }
+ (void)(x * y * z);
+}
+
+void test_SValBuilder_simplifies_IntSym(int x, int y, int z) {
+ // Most IntSym BinOps are transformed to SymInt in SimpleSValBuilder.
+ // Division is one exception.
+ x = 77 / (y + z);
+ if (y + z != 1)
+ return;
+ clang_analyzer_eval(x == 77); // expected-warning{{TRUE}}
+ (void)(x * y * z);
+}
+
+void recurring_symbol(int b) {
+ if (b * b != b)
+ if ((b * b) * b * b != (b * b) * b)
+ if (b * b == 1) // no-crash (assert should not fire)
+ clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}
+}
diff --git a/clang/test/Analysis/taint-tester.c b/clang/test/Analysis/taint-tester.c
index 3a8cc1825a02..cbb2ad6c9744 100644
--- a/clang/test/Analysis/taint-tester.c
+++ b/clang/test/Analysis/taint-tester.c
@@ -59,7 +59,7 @@ void taintTracking(int x) {
int tty = xy.y; // expected-warning + {{tainted}}
}
-void BitwiseOp(int in, char inn) {
+void BitwiseOp(int in, char inn, int zz) {
// Taint on bitwise operations, integer to integer cast.
int m;
int x = 0;
@@ -67,11 +67,12 @@ void BitwiseOp(int in, char inn) {
int y = (in << (x << in)) * 5;// expected-warning + {{tainted}}
// The next line tests integer to integer cast.
int z = y & inn; // expected-warning + {{tainted}}
- if (y == 5) // expected-warning + {{tainted}}
+ if (y == zz) { // expected-warning + {{tainted}}
m = z | z;// expected-warning + {{tainted}}
+ }
else
m = inn;
- int mm = m; // expected-warning + {{tainted}}
+ int mm = m; // expected-warning 1 {{tainted}}
}
// Test getenv.
More information about the cfe-commits
mailing list