14#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
15#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
24typedef llvm::ImmutableSet<
25 std::pair<clang::ento::SymbolRef, const llvm::SMTExpr *>>
33 mutable llvm::SMTSolverRef Solver = llvm::CreateZ3Solver();
39 Solver->setBoolParam(
"model",
true);
40 Solver->setUnsignedParam(
"timeout", 15000 );
49 bool Assumption)
override {
55 std::optional<llvm::SMTExprRef> Exp =
67 Assumption ? Exp.value() : Solver->mkNot(Exp.value()));
71 const llvm::APSInt &From,
72 const llvm::APSInt &To,
73 bool InRange)
override {
75 std::optional<llvm::SMTExprRef>
Expr =
83 bool Assumption)
override {
97 std::optional<llvm::SMTExprRef> VarExp =
128 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
144 std::optional<bool> isSat = Solver->check();
145 if (!isSat || !*isSat)
149 if (!Solver->getInterpretation(Exp,
Value))
156 : Solver->mkBitvector(
Value,
Value.getBitWidth()),
159 Solver->addConstraint(NotExp);
161 std::optional<bool> isNotSat = Solver->check();
162 if (!isNotSat || *isNotSat)
169 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
176 const llvm::APSInt *
Value;
182 if (
const auto *USE = dyn_cast<UnarySymExpr>(Sym)) {
183 const llvm::APSInt *
Value;
186 std::optional<APSIntPtr> Res = BVF.
evalAPSInt(USE->getOpcode(), *
Value);
187 return Res ? Res.value().get() :
nullptr;
190 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
191 const llvm::APSInt *LHS, *RHS;
192 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
194 RHS = SIE->getRHS().get();
195 }
else if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
196 LHS = ISE->getLHS().get();
198 }
else if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
201 RHS = LHS ?
getSymVal(State, SSM->getRHS()) :
nullptr;
203 llvm_unreachable(
"Unsupported binary expression to get symbol value!");
209 llvm::APSInt ConvertedLHS, ConvertedRHS;
214 Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
215 std::optional<APSIntPtr> Res =
216 BVF.
evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
217 return Res ? Res.value().get() :
nullptr;
220 llvm_unreachable(
"Unsupported expression to get symbol value!");
225 auto CZ = State->get<ConstraintSMT>();
226 auto &CZFactory = State->get_context<ConstraintSMT>();
228 for (
const auto &Entry : CZ) {
229 if (SymReaper.
isDead(Entry.first))
230 CZ = CZFactory.remove(CZ, Entry);
233 return State->set<ConstraintSMT>(CZ);
237 unsigned int Space = 0,
bool IsDot =
false)
const override {
240 Indent(Out, Space, IsDot) <<
"\"constraints\": ";
241 if (Constraints.isEmpty()) {
242 Out <<
"null," << NL;
248 for (ConstraintSMTType::iterator I = Constraints.begin();
249 I != Constraints.end(); ++I) {
251 <<
"{ \"symbol\": \"" << I->first <<
"\", \"range\": \"";
252 I->second->print(Out);
255 if (std::next(I) != Constraints.end())
261 Indent(Out, Space, IsDot) <<
"],";
266 return S1->get<ConstraintSMT>() == S2->get<ConstraintSMT>();
276 const SymExpr *Sym = SymVal->getSymbol();
290 return Solver->isFPSupported();
297 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
300 if (
const auto *USE = dyn_cast<UnarySymExpr>(Sym))
303 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
304 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
307 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
310 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
315 llvm_unreachable(
"Unsupported expression to reason about!");
318#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
320 LLVM_DUMP_METHOD
void dump()
const { Solver->dump(); }
326 const llvm::SMTExprRef &Exp) {
328 if (
checkModel(State, Sym, Exp).isConstrainedTrue())
329 return State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
338 auto CZ = State->get<ConstraintSMT>();
339 auto I = CZ.begin(), IE = CZ.end();
343 llvm::SMTExprRef Constraint = I++->second;
345 Constraint = Solver->mkAnd(Constraint, I++->second);
348 Solver->addConstraint(Constraint);
354 const llvm::SMTExprRef &Exp)
const {
356 State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
358 llvm::FoldingSetNodeID ID;
359 NewState->get<ConstraintSMT>().Profile(ID);
361 unsigned hash = ID.ComputeHash();
362 auto I =
Cached.find(hash);
369 std::optional<bool> res = Solver->check();
375 mutable llvm::DenseMap<unsigned, ConditionTruthVal>
Cached;
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy.
llvm::ImmutableSet< std::pair< clang::ento::SymbolRef, const llvm::SMTExpr * > > ConstraintSMTType
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
const TargetInfo & getTargetInfo() const
This represents one expression.
A (possibly-)qualified type.
Exposes information about the current target.
const llvm::fltSemantics & getLongDoubleFormat() const
bool isBooleanType() const
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
bool isComplexIntegerType() const
bool isRealFloatingType() const
Floating point categories.
LLVM_ATTRIBUTE_RETURNS_NONNULL const APSInt * get() const
ASTContext & getContext() const
std::optional< APSIntPtr > evalAPSInt(UnaryOperator::Opcode Op, const llvm::APSInt &V1)
APSIntPtr Convert(const llvm::APSInt &To, const llvm::APSInt &From)
Convert - Create a new persistent APSInt with the same value as 'From' but with the bitwidth and sign...
Represents a symbolic expression involving a binary operator.
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
SMTConstraintManager(clang::ento::ExprEngine *EE, clang::ento::SValBuilder &SB)
virtual void addStateConstraints(ProgramStateRef State) const
Given a program state, construct the logical conjunction and add it to the solver.
bool canReasonAbout(SVal X) const override
canReasonAbout - Not all ConstraintManagers can accurately reason about all SVal values.
ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange) override
Given a symbolic expression within the range [From, To], assume that it is true/false and generate th...
LLVM_DUMP_METHOD void dump() const
Dumps SMT formula.
ConditionTruthVal checkModel(ProgramStateRef State, SymbolRef Sym, const llvm::SMTExprRef &Exp) const
const llvm::APSInt * getSymVal(ProgramStateRef State, SymbolRef Sym) const override
If a symbol is perfectly constrained to a constant, attempt to return the concrete value.
ProgramStateRef removeDeadBindings(ProgramStateRef State, SymbolReaper &SymReaper) override
Scan all symbols referenced by the constraints.
ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override
Returns whether or not a symbol is known to be null ("true"), known to be non-null ("false"),...
ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym, bool Assumption) override
Given a symbolic expression that can be reasoned about, assume that it is true/false and generate the...
llvm::DenseMap< unsigned, ConditionTruthVal > Cached
virtual ~SMTConstraintManager()=default
virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, const llvm::SMTExprRef &Exp)
void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\n", unsigned int Space=0, bool IsDot=false) const override
ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, bool Assumption) override
Given a symbolic expression that cannot be reasoned about, assume that it is zero/nonzero and add it ...
bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const override
static std::optional< llvm::SMTExprRef > getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
static llvm::SMTExprRef getZeroExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType Ty, bool Assumption)
static void doIntTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
static std::optional< llvm::SMTExprRef > getExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType &RetTy, bool *hasComparison=nullptr)
static llvm::SMTExprRef fromData(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const SymbolData *Sym)
Construct an SMTSolverRef from a SymbolData.
static llvm::SMTExprRef fromBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS, bool isSigned)
Construct an SMTSolverRef from a binary operator.
static std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SValBuilder & getSValBuilder() const
BasicValueFactory & getBasicVals() const
SimpleConstraintManager(ExprEngine *exprengine, SValBuilder &SB)
virtual QualType getType() const =0
Represents a cast expression.
A symbol representing data which can be stored in a memory location (region).
A class responsible for cleaning up unused symbols.
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
Represents symbolic expression that isn't a location.
Defines the clang::TargetInfo interface.
BinarySymExprImpl< APSIntPtr, const SymExpr *, SymExpr::Kind::IntSymExprKind > IntSymExpr
Represents a symbolic expression like 3 - 'x'.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const SymExpr * SymbolRef
BinarySymExprImpl< const SymExpr *, const SymExpr *, SymExpr::Kind::SymSymExprKind > SymSymExpr
Represents a symbolic expression like 'x' + 'y'.
BinarySymExprImpl< const SymExpr *, APSIntPtr, SymExpr::Kind::SymIntExprKind > SymIntExpr
Represents a symbolic expression like 'x' + 3.
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)