ProgramStateRef ProgramState::assumeInBound(DefinedOrUnknownSVal Idx, DefinedOrUnknownSVal UpperBound, bool Assumption, QualType indexTy) const { if (Idx.isUnknown() || UpperBound.isUnknown()) return this; // Build an expression for 0 <= Idx < UpperBound. // This is the same as Idx + MIN < UpperBound + MIN, if overflow is allowed. // FIXME: This should probably be part of SValBuilder. ProgramStateManager &SM = getStateManager(); SValBuilder &svalBuilder = SM.getSValBuilder(); ASTContext &Ctx = svalBuilder.getContext(); // Get the offset: the minimum value of the array index type. BasicValueFactory &BVF = svalBuilder.getBasicValueFactory(); // FIXME: This should be using ValueManager::ArrayindexTy...somehow. if (indexTy.isNull()) indexTy = Ctx.IntTy; nonloc::ConcreteInt Min(BVF.getMinValue(indexTy)); // Adjust the index. SVal newIdx = svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(Idx), Min, indexTy); if (newIdx.isUnknownOrUndef()) return this; // Adjust the upper bound. SVal newBound = svalBuilder.evalBinOpNN(this, BO_Add, cast<NonLoc>(UpperBound), Min, indexTy); if (newBound.isUnknownOrUndef()) return this; // Build the actual comparison. SVal inBound = svalBuilder.evalBinOpNN(this, BO_LT, cast<NonLoc>(newIdx), cast<NonLoc>(newBound), Ctx.IntTy); if (inBound.isUnknownOrUndef()) return this; // Finally, let the constraint manager take care of it. ConstraintManager &CM = SM.getConstraintManager(); return CM.assume(this, cast<DefinedSVal>(inBound), Assumption); }