#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
namespace clang {
namespace ento {
SimpleConstraintManager::~SimpleConstraintManager() {}
ProgramStateRef SimpleConstraintManager::assumeInternal(ProgramStateRef State,
DefinedSVal Cond,
bool Assumption) {
if (Optional<Loc> LV = Cond.getAs<Loc>()) {
SValBuilder &SVB = State->getStateManager().getSValBuilder();
QualType T;
const MemRegion *MR = LV->getAsRegion();
if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
T = TR->getLocationType();
else
T = SVB.getContext().VoidPtrTy;
Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
}
return assume(State, Cond.castAs<NonLoc>(), Assumption);
}
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef State,
NonLoc Cond, bool Assumption) {
State = assumeAux(State, Cond, Assumption);
if (EE)
return EE->processAssume(State, Cond, Assumption);
return State;
}
ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef State,
NonLoc Cond,
bool Assumption) {
if (!canReasonAbout(Cond)) {
SymbolRef Sym = Cond.getAsSymbol();
assert(Sym);
return assumeSymUnsupported(State, Sym, Assumption);
}
switch (Cond.getSubKind()) {
default:
llvm_unreachable("'Assume' not implemented for this NonLoc");
case nonloc::SymbolValKind: {
nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
SymbolRef Sym = SV.getSymbol();
assert(Sym);
return assumeSym(State, Sym, Assumption);
}
case nonloc::ConcreteIntKind: {
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
bool isFeasible = b ? Assumption : !Assumption;
return isFeasible ? State : nullptr;
}
case nonloc::PointerToMemberKind: {
bool IsNull = !Cond.castAs<nonloc::PointerToMember>().isNullMemberPointer();
bool IsFeasible = IsNull ? Assumption : !Assumption;
return IsFeasible ? State : nullptr;
}
case nonloc::LocAsIntegerKind:
return assumeInternal(State, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
Assumption);
} }
ProgramStateRef SimpleConstraintManager::assumeInclusiveRangeInternal(
ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
const llvm::APSInt &To, bool InRange) {
assert(From.isUnsigned() == To.isUnsigned() &&
From.getBitWidth() == To.getBitWidth() &&
"Values should have same types!");
if (!canReasonAbout(Value)) {
SymbolRef Sym = Value.getAsSymbol();
assert(Sym);
return assumeSymInclusiveRange(State, Sym, From, To, InRange);
}
switch (Value.getSubKind()) {
default:
llvm_unreachable("'assumeInclusiveRange' is not implemented"
"for this NonLoc");
case nonloc::LocAsIntegerKind:
case nonloc::SymbolValKind: {
if (SymbolRef Sym = Value.getAsSymbol())
return assumeSymInclusiveRange(State, Sym, From, To, InRange);
return State;
}
case nonloc::ConcreteIntKind: {
const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
bool IsInRange = IntVal >= From && IntVal <= To;
bool isFeasible = (IsInRange == InRange);
return isFeasible ? State : nullptr;
}
} }
}
}