Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 17 additions & 0 deletions clang/lib/StaticAnalyzer/Core/RangeConstraintManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1249,6 +1249,8 @@ class SymbolicRangeInferrer
// calculate the effective range set by intersecting the range set
// for A - B and the negated range set of B - A.
getRangeForNegatedSymSym(SSE),
// If commutative, we may have constaints for the commuted variant.
getRangeCommutativeSymSym(SSE),
// If Sym is a comparison expression (except <=>),
// find any other comparisons with the same operands.
// See function description.
Expand Down Expand Up @@ -1485,6 +1487,21 @@ class SymbolicRangeInferrer
Sym->getType());
}

std::optional<RangeSet> getRangeCommutativeSymSym(const SymSymExpr *SSE) {
auto Op = SSE->getOpcode();
bool IsCommutative = llvm::is_contained(
// ==, !=, |, &, +, *, ^
{BO_EQ, BO_NE, BO_Or, BO_And, BO_Add, BO_Mul, BO_Xor}, Op);
if (!IsCommutative)
return std::nullopt;

SymbolRef Commuted = State->getSymbolManager().getSymSymExpr(
SSE->getRHS(), Op, SSE->getLHS(), SSE->getType());
if (const RangeSet *Range = getConstraint(State, Commuted))
return *Range;
return std::nullopt;
}

// Returns ranges only for binary comparison operators (except <=>)
// when left and right operands are symbolic values.
// Finds any other comparisons with the same operands.
Expand Down
33 changes: 30 additions & 3 deletions clang/test/Analysis/unary-sym-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,39 @@ int test(int x, int y) {
return 42;
}

void test_svalbuilder_simplification(int x, int y) {
void test_svalbuilder_simplification_add(int x, int y) {
if (x + y != 3)
return;
clang_analyzer_eval(-(x + y) == -3); // expected-warning{{TRUE}}
// FIXME Commutativity is not supported yet.
clang_analyzer_eval(-(y + x) == -3); // expected-warning{{UNKNOWN}}
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) {
Expand Down
Loading