[clang] d49aa40 - [analyzer] `SValBuilder::evalBinOpLN`: try simplifying the RHS first (#161537)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 14 01:25:52 PDT 2025
Author: guillem-bartrina-sonarsource
Date: 2025-10-14T10:25:48+02:00
New Revision: d49aa40fc703d061f48e520b9c1b63e6646c6907
URL: https://github.com/llvm/llvm-project/commit/d49aa40fc703d061f48e520b9c1b63e6646c6907
DIFF: https://github.com/llvm/llvm-project/commit/d49aa40fc703d061f48e520b9c1b63e6646c6907.diff
LOG: [analyzer] `SValBuilder::evalBinOpLN`: try simplifying the RHS first (#161537)
The first thing `SValBuilder::evalBinOpNN` does is simplify both
operators
([here](https://github.com/llvm/llvm-project/blob/main/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp#L430-L437)),
why wouldn't we simplify the RHS in `SValBuilder::evalBinOpLN`?
When the LHS is an `Element`, the right side is simplified incidentally
when calling `evalBinOpNN`
([here](https://github.com/llvm/llvm-project/blob/main/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp#L1169-L1170)).
Without this patch, the “base_complex” test case is **UNKNOWN** instead of **TRUE**.
Added:
clang/test/Analysis/loc-folding.cpp
Modified:
clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
Removed:
################################################################################
diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 84a9c43d3572e..6108931f737d4 100644
--- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -1111,6 +1111,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
assert(!BinaryOperator::isComparisonOp(op) &&
"arguments to comparison ops must be of the same type");
+ SVal simplifiedRhs = simplifySVal(state, rhs);
+ if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs<NonLoc>())
+ rhs = *simplifiedRhsAsNonLoc;
+
// Special case: rhs is a zero constant.
if (rhs.isZeroConstant())
return lhs;
diff --git a/clang/test/Analysis/loc-folding.cpp b/clang/test/Analysis/loc-folding.cpp
new file mode 100644
index 0000000000000..1fcb0668e50fe
--- /dev/null
+++ b/clang/test/Analysis/loc-folding.cpp
@@ -0,0 +1,61 @@
+// RUN: %clang_analyze_cc1 -verify %s -analyzer-config eagerly-assume=false \
+// RUN: -analyzer-checker=core,debug.ExprInspection
+
+void clang_analyzer_eval(bool);
+
+void element_constant() {
+ char arr[10];
+ clang_analyzer_eval(arr + 1 > arr); // expected-warning{{TRUE}}
+}
+
+void element_known() {
+ char arr[10];
+ int off = 1;
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
+}
+
+void element_constrained(int off) {
+ char arr[10];
+ if (off == 1) {
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
+ }
+}
+
+void element_unknown(int off) {
+ char arr[10];
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{UNKNOWN}}
+}
+
+void element_complex(int off) {
+ char arr[10];
+ int comp = off * 2;
+ if (off == 1) {
+ clang_analyzer_eval(arr + comp); // expected-warning{{TRUE}}
+ }
+}
+
+void base_constant(int *arr) {
+ clang_analyzer_eval(arr + 1 > arr); // expected-warning{{TRUE}}
+}
+
+void base_known(int *arr) {
+ int off = 1;
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
+}
+
+void base_constrained(int *arr, int off) {
+ if (off == 1) {
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
+ }
+}
+
+void base_unknown(int *arr, int off) {
+ clang_analyzer_eval(arr + off > arr); // expected-warning{{UNKNOWN}}
+}
+
+void base_complex(int *arr, int off) {
+ int comp = off * 2;
+ if (off == 1) {
+ clang_analyzer_eval(arr + comp > arr); // expected-warning{{TRUE}}
+ }
+}
More information about the cfe-commits
mailing list