Skip to content

Commit d49aa40

Browse files
[analyzer] SValBuilder::evalBinOpLN: try simplifying the RHS first (llvm#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**.
1 parent a8057ff commit d49aa40

File tree

2 files changed

+65
-0
lines changed

2 files changed

+65
-0
lines changed

clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1111,6 +1111,10 @@ SVal SimpleSValBuilder::evalBinOpLN(ProgramStateRef state,
11111111
assert(!BinaryOperator::isComparisonOp(op) &&
11121112
"arguments to comparison ops must be of the same type");
11131113

1114+
SVal simplifiedRhs = simplifySVal(state, rhs);
1115+
if (auto simplifiedRhsAsNonLoc = simplifiedRhs.getAs<NonLoc>())
1116+
rhs = *simplifiedRhsAsNonLoc;
1117+
11141118
// Special case: rhs is a zero constant.
11151119
if (rhs.isZeroConstant())
11161120
return lhs;
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// RUN: %clang_analyze_cc1 -verify %s -analyzer-config eagerly-assume=false \
2+
// RUN: -analyzer-checker=core,debug.ExprInspection
3+
4+
void clang_analyzer_eval(bool);
5+
6+
void element_constant() {
7+
char arr[10];
8+
clang_analyzer_eval(arr + 1 > arr); // expected-warning{{TRUE}}
9+
}
10+
11+
void element_known() {
12+
char arr[10];
13+
int off = 1;
14+
clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
15+
}
16+
17+
void element_constrained(int off) {
18+
char arr[10];
19+
if (off == 1) {
20+
clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
21+
}
22+
}
23+
24+
void element_unknown(int off) {
25+
char arr[10];
26+
clang_analyzer_eval(arr + off > arr); // expected-warning{{UNKNOWN}}
27+
}
28+
29+
void element_complex(int off) {
30+
char arr[10];
31+
int comp = off * 2;
32+
if (off == 1) {
33+
clang_analyzer_eval(arr + comp); // expected-warning{{TRUE}}
34+
}
35+
}
36+
37+
void base_constant(int *arr) {
38+
clang_analyzer_eval(arr + 1 > arr); // expected-warning{{TRUE}}
39+
}
40+
41+
void base_known(int *arr) {
42+
int off = 1;
43+
clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
44+
}
45+
46+
void base_constrained(int *arr, int off) {
47+
if (off == 1) {
48+
clang_analyzer_eval(arr + off > arr); // expected-warning{{TRUE}}
49+
}
50+
}
51+
52+
void base_unknown(int *arr, int off) {
53+
clang_analyzer_eval(arr + off > arr); // expected-warning{{UNKNOWN}}
54+
}
55+
56+
void base_complex(int *arr, int off) {
57+
int comp = off * 2;
58+
if (off == 1) {
59+
clang_analyzer_eval(arr + comp > arr); // expected-warning{{TRUE}}
60+
}
61+
}

0 commit comments

Comments
 (0)