14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H 21 typedef llvm::ImmutableSet<
22 std::pair<clang::ento::SymbolRef, const llvm::SMTExpr *>>
30 mutable llvm::SMTSolverRef Solver = llvm::CreateZ3Solver();
42 bool Assumption)
override {
48 llvm::SMTExprRef Exp =
58 return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
62 const llvm::APSInt &From,
63 const llvm::APSInt &To,
64 bool InRange)
override {
71 bool Assumption)
override {
86 llvm::SMTExprRef Exp =
90 llvm::SMTExprRef NotExp =
113 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
123 llvm::SMTExprRef Exp =
131 if (!isSat.hasValue() || !isSat.getValue())
135 if (!Solver->getInterpretation(Exp,
Value))
142 : Solver->mkBitvector(
Value,
Value.getBitWidth()),
145 Solver->addConstraint(NotExp);
148 if (!isSat.hasValue() || isNotSat.getValue())
152 return &BVF.getValue(
Value);
155 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
162 const llvm::APSInt *
Value;
163 if (!(Value =
getSymVal(State, CastSym)))
168 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
169 const llvm::APSInt *LHS, *RHS;
170 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
172 RHS = &SIE->getRHS();
173 }
else if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
174 LHS = &ISE->getLHS();
176 }
else if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
179 RHS = LHS ?
getSymVal(State, SSM->getRHS()) :
nullptr;
181 llvm_unreachable(
"Unsupported binary expression to get symbol value!");
187 llvm::APSInt ConvertedLHS, ConvertedRHS;
191 SMTConv::doIntTypeConversion<llvm::APSInt, &SMTConv::castAPSInt>(
192 Solver, Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
193 return BVF.
evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
196 llvm_unreachable(
"Unsupported expression to get symbol value!");
201 auto CZ = State->get<ConstraintSMT>();
202 auto &CZFactory = State->get_context<ConstraintSMT>();
204 for (
auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
205 if (SymReaper.
isDead(I->first))
206 CZ = CZFactory.remove(CZ, *I);
209 return State->set<ConstraintSMT>(CZ);
213 unsigned int Space = 0,
bool IsDot =
false)
const override {
216 Indent(Out, Space, IsDot) <<
"\"constraints\": ";
217 if (Constraints.isEmpty()) {
218 Out <<
"null," << NL;
224 for (ConstraintSMTType::iterator I = Constraints.begin();
225 I != Constraints.end(); ++I) {
227 <<
"{ \"symbol\": \"" << I->first <<
"\", \"range\": \"";
228 I->second->print(Out);
231 if (std::next(I) != Constraints.end())
237 Indent(Out, Space, IsDot) <<
"],";
242 return S1->get<ConstraintSMT>() == S2->get<ConstraintSMT>();
252 const SymExpr *Sym = SymVal->getSymbol();
266 return Solver->isFPSupported();
268 if (isa<SymbolData>(Sym))
273 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym))
276 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
277 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE))
280 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE))
283 if (
const SymSymExpr *SSE = dyn_cast<SymSymExpr>(BSE))
288 llvm_unreachable(
"Unsupported expression to reason about!");
292 LLVM_DUMP_METHOD
void dump()
const { Solver->dump(); }
297 const llvm::SMTExprRef &Exp) {
299 if (
checkModel(State, Sym, Exp).isConstrainedTrue())
300 return State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
309 auto CZ = State->get<ConstraintSMT>();
310 auto I = CZ.begin(), IE = CZ.end();
314 std::vector<llvm::SMTExprRef> ASTs;
316 llvm::SMTExprRef Constraint = I++->second;
318 Constraint = Solver->mkAnd(Constraint, I++->second);
321 Solver->addConstraint(Constraint);
327 const llvm::SMTExprRef &Exp)
const {
329 State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
331 llvm::FoldingSetNodeID
ID;
332 NewState->get<ConstraintSMT>().Profile(ID);
334 unsigned hash = ID.ComputeHash();
335 auto I =
Cached.find(hash);
353 mutable llvm::DenseMap<unsigned, ConditionTruthVal>
Cached;
bool isConstrainedFalse() const
Return true if the constraint is perfectly constrained to 'false'.
A (possibly-)qualified type.
SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB)
bool isDead(SymbolRef sym)
Returns whether or not a symbol has been confirmed dead.
bool isRealFloatingType() const
Floating point categories.
const TargetInfo & getTargetInfo() const
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::ImmutableSet< std::pair< clang::ento::SymbolRef, const llvm::SMTExpr * > > ConstraintSMTType
static std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
SVal makeSymbolVal(SymbolRef Sym)
Make an SVal that represents the given symbol.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isSpecificBuiltinType(unsigned K) const
Test for a particular builtin type.
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...
void printJson(raw_ostream &Out, ProgramStateRef State, const char *NL="\, unsigned int Space=0, bool IsDot=false) const override
Represents a symbolic expression like 'x' + 3.
virtual QualType getType() const =0
bool isConstrainedTrue() const
Return true if the constraint is perfectly constrained to 'true'.
virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, const llvm::SMTExprRef &Exp)
bool isComplexType() const
isComplexType() does not include complex integers (a GCC extension).
const llvm::fltSemantics & getLongDoubleFormat() const
Exposes information about the current target.
BasicValueFactory & getBasicVals() const
ProgramStateRef removeDeadBindings(ProgramStateRef State, SymbolReaper &SymReaper) override
Scan all symbols referenced by the constraints.
static llvm::SMTExprRef getZeroExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType Ty, bool Assumption)
ASTContext & getContext() const
Represents a cast expression.
SValBuilder & getSValBuilder() const
virtual ~SMTConstraintManager()=default
Optional< T > getAs() const
Convert to the specified SVal type, returning None if this SVal is not of the desired type...
#define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type)
Declares a program state trait for type Type called Name, and introduce a type named NameTy...
static llvm::SMTExprRef getExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy=nullptr, bool *hasComparison=nullptr)
bool canReasonAbout(SVal X) const override
canReasonAbout - Not all ConstraintManagers can accurately reason about all SVal values.
SVal - This represents a symbolic expression, which can be either an L-value or an R-value...
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Represents a symbolic expression like 3 - 'x'.
A class responsible for cleaning up unused symbols.
const llvm::APSInt * evalAPSInt(BinaryOperator::Opcode Op, const llvm::APSInt &V1, const llvm::APSInt &V2)
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 ...
Dataflow Directional Tag Classes.
Represents a symbolic expression involving a binary operator.
LLVM_DUMP_METHOD void dump() const
Dumps SMT formula.
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.
bool isBooleanType() const
Represents symbolic expression that isn't a location.
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...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
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...
static llvm::SMTExprRef fromData(llvm::SMTSolverRef &Solver, const SymbolID ID, const QualType &Ty, uint64_t BitWidth)
Construct an SMTSolverRef from a SymbolData.
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
llvm::DenseMap< unsigned, ConditionTruthVal > Cached
virtual void addStateConstraints(ProgramStateRef State) const
Given a program state, construct the logical conjunction and add it to the solver.
bool isComplexIntegerType() const
raw_ostream & Indent(raw_ostream &Out, const unsigned int Space, bool IsDot)
bool haveEqualConstraints(ProgramStateRef S1, ProgramStateRef S2) const override
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")...
Represents a symbolic expression like 'x' + 'y'.
A symbol representing data which can be stored in a memory location (region).
static llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)