This diff attempts to address a crash (triggered assert) on the newly-added test case.
The assert being discussed is inside SValBuilder::evalBinOp
if (Optional<Loc> RV = rhs.getAs<Loc>()) {
// Support pointer arithmetic where the addend is on the left
// and the pointer on the right.
assert(op == BO_Add);but the root cause seems to be in a different place
(if I'm not missing smth).
The method simplifySVal appears to be doing the wrong thing for SVal "(char*)End - (char*)Begin".
Call stack: evalIntegralCast -> evalBinOpNN -> simplifySVal -> ... -> simplifySVal -> Simplifier::VisitSymSymExpr -> ...
Inside Simplifier::VisitSymSymExpr the call Visit(S->getLHS()) returns a NonLoc
(where S->getLHS() represents char* End) while the call Visit(S->getRHS()) returns a Loc.
For Visit(S->getRHS()) this happens because in VisitSymbolData(const SymbolData *S) the "if" condition
if (const llvm::APSInt *I = SVB.getKnownValue(State, nonloc::SymbolVal(S)))
is satisfied and Loc is correctly chosen.
For Visit(S->getLHS()) nonloc::SymbolVal(S) is used instead.
Next those values will passed to SValBuilder::evalBinOp and the code path
if (Optional<Loc> RV = rhs.getAs<Loc>()) {
// Support pointer arithmetic where the addend is on the left
// and the pointer on the right.
assert(op == BO_Add);
// Commute the operands.
return evalBinOpLN(state, op, *RV, lhs.castAs<NonLoc>(), type);
}will be executed instead of the correct one
if (Optional<Loc> LV = lhs.getAs<Loc>()) {
if (Optional<Loc> RV = rhs.getAs<Loc>())
return evalBinOpLL(state, op, *LV, *RV, type);
return evalBinOpLN(state, op, *LV, rhs.castAs<NonLoc>(), type);
}Test plan: make check-all (green)