14#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
15#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H
23typedef llvm::ImmutableSet<
24 std::pair<clang::ento::SymbolRef, const llvm::SMTExpr *>>
32 mutable llvm::SMTSolverRef Solver = llvm::CreateZ3Solver();
38 Solver->setBoolParam(
"model",
true);
39 Solver->setUnsignedParam(
"timeout", 15000 );
48 bool Assumption)
override {
54 llvm::SMTExprRef Exp =
64 return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
68 const llvm::APSInt &From,
69 const llvm::APSInt &To,
70 bool InRange)
override {
77 bool Assumption)
override {
92 llvm::SMTExprRef Exp =
96 llvm::SMTExprRef NotExp =
119 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
135 std::optional<bool> isSat = Solver->check();
136 if (!isSat || !*isSat)
140 if (!Solver->getInterpretation(Exp,
Value))
147 : Solver->mkBitvector(
Value,
Value.getBitWidth()),
150 Solver->addConstraint(NotExp);
152 std::optional<bool> isNotSat = Solver->check();
153 if (!isNotSat || *isNotSat)
157 return &BVF.getValue(
Value);
160 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
167 const llvm::APSInt *
Value;
173 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
174 const llvm::APSInt *LHS, *RHS;
175 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
177 RHS = &SIE->getRHS();
178 }
else if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
179 LHS = &ISE->getLHS();
181 }
else if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
184 RHS = LHS ?
getSymVal(State, SSM->getRHS()) :
nullptr;
186 llvm_unreachable(
"Unsupported binary expression to get symbol value!");
192 llvm::APSInt ConvertedLHS, ConvertedRHS;
196 SMTConv::doIntTypeConversion<llvm::APSInt, &SMTConv::castAPSInt>(
197 Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
198 return BVF.
evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
201 llvm_unreachable(
"Unsupported expression to get symbol value!");
206 auto CZ = State->get<ConstraintSMT>();
207 auto &CZFactory = State->get_context<ConstraintSMT>();
209 for (
const auto &Entry : CZ) {
210 if (SymReaper.
isDead(Entry.first))
211 CZ = CZFactory.remove(CZ, Entry);
214 return State->set<ConstraintSMT>(CZ);
218 unsigned int Space = 0,
bool IsDot =
false)
const override {
221 Indent(Out, Space, IsDot) <<
"\"constraints\": ";
222 if (Constraints.isEmpty()) {
223 Out <<
"null," << NL;
229 for (ConstraintSMTType::iterator I = Constraints.begin();
230 I != Constraints.end(); ++I) {
231 Indent(Out, Space, IsDot)
232 <<
"{ \"symbol\": \"" << I->first <<
"\", \"range\": \"";
233 I->second->print(Out);
236 if (std::next(I) != Constraints.end())
242 Indent(Out, Space, IsDot) <<
"],";
247 return S1->get<ConstraintSMT>() == S2->get<ConstraintSMT>();
257 const SymExpr *Sym = SymVal->getSymbol();
271 return Solver->isFPSupported();
273 if (isa<SymbolData>(Sym))
278 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
281 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
282 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
285 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
288 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
293 llvm_unreachable(
"Unsupported expression to reason about!");
297 LLVM_DUMP_METHOD
void dump()
const { Solver->dump(); }
302 const llvm::SMTExprRef &Exp) {
304 if (
checkModel(State, Sym, Exp).isConstrainedTrue())
305 return State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
314 auto CZ = State->get<ConstraintSMT>();
315 auto I = CZ.begin(), IE = CZ.end();
319 std::vector<llvm::SMTExprRef> ASTs;
321 llvm::SMTExprRef Constraint = I++->second;
323 Constraint = Solver->mkAnd(Constraint, I++->second);
326 Solver->addConstraint(Constraint);
332 const llvm::SMTExprRef &Exp)
const {
334 State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
336 llvm::FoldingSetNodeID
ID;
337 NewState->get<ConstraintSMT>().Profile(
ID);
339 unsigned hash =
ID.ComputeHash();
340 auto I =
Cached.find(hash);
347 std::optional<bool> res = Solver->check();
358 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
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.
const llvm::APSInt & 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...
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
ASTContext & getContext() const
Template implementation for all binary symbolic expressions.
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 llvm::SMTExprRef getZeroExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType Ty, bool Assumption)
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
static llvm::SMTExprRef getExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy=nullptr, 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)
DefinedSVal makeSymbolVal(SymbolRef Sym)
Make an SVal that represents the given symbol.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value.
SValBuilder & getSValBuilder() const
BasicValueFactory & getBasicVals() const
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.
The JSON file list parser is used to communicate input to InstallAPI.