15 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H 16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H 38 LLVM_DUMP_METHOD
void dump()
const {
print(llvm::errs()); }
53 llvm_unreachable(
"Unsupported floating-point bitwidth!");
81 llvm_unreachable(
"Unimplemented opcode");
96 llvm_unreachable(
"Unimplemented opcode");
101 const std::vector<SMTExprRef> &ASTs) {
102 assert(!ASTs.empty());
104 if (Op != BO_LAnd && Op != BO_LOr)
105 llvm_unreachable(
"Unimplemented opcode");
109 res = (Op == BO_LAnd) ?
mkAnd(res, ASTs[i]) :
mkOr(res, ASTs[i]);
116 assert(*
getSort(LHS) == *
getSort(RHS) &&
"AST's must have the same sort!");
175 return mkAnd(LHS, RHS);
178 return mkOr(LHS, RHS);
182 llvm_unreachable(
"Unimplemented opcode");
188 const llvm::APFloat::fltCategory &RHS) {
193 case llvm::APFloat::fcInfinity:
196 case llvm::APFloat::fcNaN:
199 case llvm::APFloat::fcNormal:
202 case llvm::APFloat::fcZero:
213 llvm_unreachable(
"Unimplemented opcode");
220 assert(*
getSort(LHS) == *
getSort(RHS) &&
"AST's must have the same sort!");
268 llvm_unreachable(
"Unimplemented opcode");
274 QualType FromTy, uint64_t FromBitWidth) {
282 assert(ToBitWidth > 0 &&
"BitWidth must be positive!");
287 if (ToBitWidth > FromBitWidth)
292 if (ToBitWidth < FromBitWidth)
300 if (ToBitWidth != FromBitWidth)
317 llvm_unreachable(
"Unsupported explicit type cast!");
323 uint64_t FromWidth) {
334 bool *hasComparison =
nullptr) {
336 *hasComparison =
false;
339 return getSymExpr(Ctx, Sym, RetTy, hasComparison);
358 return Assumption ?
fromUnOp(UO_LNot, Exp) : Exp;
360 return fromBinOp(Exp, Assumption ? BO_EQ : BO_NE,
364 llvm_unreachable(
"Unsupported type for zero value!");
370 bool *hasComparison) {
371 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
379 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
385 getSymExpr(Ctx, SC->getOperand(), &FromTy, hasComparison);
390 *hasComparison =
false;
394 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
402 llvm_unreachable(
"Unsupported SymbolRef type!");
415 bool *hasComparison,
QualType *RetTy) {
419 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
421 llvm::APSInt NewRInt;
422 std::tie(NewRInt, RTy) =
fixAPSInt(Ctx, SIE->getRHS());
424 return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
427 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
428 llvm::APSInt NewLInt;
429 std::tie(NewLInt, LTy) =
fixAPSInt(Ctx, ISE->getLHS());
432 return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
435 if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
438 return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
441 llvm_unreachable(
"Unsupported BinarySymExpr type!");
481 const llvm::APSInt &From,
const llvm::APSInt &To,
485 llvm::APSInt NewFromInt;
486 std::tie(NewFromInt, FromTy) =
fixAPSInt(Ctx, From);
495 return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp,
499 llvm::APSInt NewToInt;
500 std::tie(NewToInt, ToTy) =
fixAPSInt(Ctx, To);
502 assert(FromTy == ToTy &&
"Range values have different types!");
506 FromExp, FromTy,
nullptr);
508 getBinExpr(Ctx, Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy,
511 return fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS,
523 const llvm::APSInt &Int) {
542 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
548 doIntTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy, RHS,
554 doFloatTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy,
575 LHS =
fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth);
578 RHS =
fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth);
589 "Pointer types have different bitwidths!");
621 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
627 LHS = (this->*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth);
629 LBitWidth = NewBitWidth;
634 RHS = (this->*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth);
636 RBitWidth = NewBitWidth;
648 if (isLSignedTy == isRSignedTy) {
651 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
654 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
657 }
else if (order != (isLSignedTy ? 1 : -1)) {
661 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
664 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
667 }
else if (LBitWidth != RBitWidth) {
672 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
675 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
685 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
687 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
695 template <
typename T, T (
SMTSolver::*doCast)(
const T &, QualType, uint64_t,
705 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
707 LBitWidth = RBitWidth;
710 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
712 RBitWidth = LBitWidth;
723 RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth);
725 }
else if (order == 0) {
726 LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth);
729 llvm_unreachable(
"Unsupported floating-point type cast!");
935 bool isUnsigned) = 0;
954 llvm::APFloat &Float) = 0;
970 uint64_t BitWidth) = 0;
976 virtual void push() = 0;
979 virtual void pop(
unsigned NumStates = 1) = 0;
982 virtual void reset()
const = 0;
984 virtual void print(raw_ostream &OS)
const = 0;
virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector multiplication operation.
virtual void print(raw_ostream &OS) const =0
virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point less-than-or-equal operation.
A (possibly-)qualified type.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
bool isBlockPointerType() const
virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float)=0
Construct an SMTExprRef value from a finite APFloat.
virtual SMTSortRef getBoolSort()=0
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
SMTSortRef getFloatSort(unsigned BitWidth)
void doIntTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
bool isArithmeticType() const
bool isRealFloatingType() const
Floating point categories.
virtual ConditionTruthVal check() const =0
Check if the constraints are satisfiable.
virtual bool getBoolean(const SMTExprRef &Exp)=0
SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth)
virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort)=0
Creates a new symbol, given a name and a sort.
virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a boolean or operation.
virtual SMTSortRef getFloat16Sort()=0
void doTypeConversion(ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, QualType &RTy)
QualType getCorrespondingUnsignedType(QualType T) const
virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed less-than operation.
virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point remainder operation.
std::unique_ptr< SMTSolver > CreateZ3Solver()
Convenience method to create and Z3Solver object.
virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp)=0
Creates a floating-point isZero operation.
virtual ~SMTSolver()=default
Generic base class for SMT exprs.
virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth)=0
Creates a floating-point conversion from unsigned bitvector to floatint-point operation.
virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point subtraction operation.
virtual SMTSortRef getSort(const SMTExprRef &AST)=0
virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point multiplication operation.
virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int)=0
Construct an SMTExprRef value from an APSInt.
std::shared_ptr< SMTSort > SMTSortRef
Shared pointer for SMTSorts, used by SMTSolver API.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isReferenceType() const
virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty, uint64_t BitWidth)=0
Construct an SMTExprRef from a SymbolData.
SMTExprRef fromFloatBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS)
Construct an SMTExprRef from a floating-point binary operator.
virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp)=0
Creates a bitvector negation operation.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
virtual SMTExprRef mkBoolean(const bool b)=0
Constructs an SMTExprRef from a boolean.
SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp)
Constructs an SMTExprRef from a floating-point unary operator.
SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS)
Construct an SMTExprRef from a special floating-point binary operator.
llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, uint64_t ToWidth, QualType FromTy, uint64_t FromWidth)
SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op, const std::vector< SMTExprRef > &ASTs)
Construct an SMTExprRef from a n-ary binary operator.
virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed greater-than operation.
virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth)=0
Creates a floating-point conversion from signed bitvector to floatint-point operation.
virtual SMTExprRef fromBoolean(const bool Bool)=0
Construct an SMTExprRef value from a boolean.
virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a boolean and operation.
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
SMTExprRef getExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy=nullptr, bool *hasComparison=nullptr)
virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector subtraction operation.
virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed division operation.
virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp)=0
Creates a bitvector zero extension operation.
QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int)
virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector addition operation.
virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, const SMTExprRef &F)=0
Creates a boolean ite operation.
virtual QualType getType() const =0
virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector concat operation.
bool isPromotableIntegerType() const
More type predicates useful for type checking/promotion.
virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point division operation.
virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed less-equal-than operation.
LLVM_DUMP_METHOD void dump() const
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
virtual SMTSortRef getFloat64Sort()=0
virtual SMTSortRef getBitvectorSort(const unsigned BitWidth)=0
virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector logical shift right operation.
virtual SMTExprRef newExprRef(const SMTExpr &E) const =0
bool isNullPtrType() const
virtual SMTExprRef mkNot(const SMTExprRef &Exp)=0
Creates a boolean not operation.
virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp)=0
Creates a bitvector sign extension operation.
virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector and operation.
virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed modulus operation.
Represents a cast expression.
virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector signed greater-equal-than operation.
virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned greater-equal-than operation.
SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp)
Constructs an SMTExprRef from an unary operator.
virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth)=0
Construct an SMTExprRef value from an integer.
virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a boolean equality operation.
virtual void pop(unsigned NumStates=1)=0
Pop the previous solver state.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, const SMTExprRef &RHS, QualType RTy, QualType *RetTy)
virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector logical shift left operation.
virtual SMTSortRef getFloat128Sort()=0
virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, const SMTSortRef &To)=0
Creates a floating-point conversion from floatint-point to signed bitvector operation.
bool isVoidPointerType() const
bool isComparisonOp() const
virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point addition operation.
QualType getCanonicalType() const
virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point greater-than-or-equal operation.
virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned less-than operation.
virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector or operation.
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'.
bool isObjCObjectPointerType() const
bool isAnyPointerType() const
SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
virtual SMTSortRef getFloat32Sort()=0
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS, bool isSigned)
Construct an SMTExprRef from a binary operator.
virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector arithmetic shift right operation.
llvm::APSInt convert(const llvm::APSInt &Value) const LLVM_READONLY
Convert and return a new APSInt with the given value, but this type's bit width and signedness...
Dataflow Directional Tag Classes.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i...
virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp)=0
Creates a floating-point isNaN operation.
virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned division operation.
Represents a symbolic expression involving a binary operator.
SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, bool *hasComparison)
bool isBooleanType() const
virtual void addConstraint(const SMTExprRef &Exp) const =0
Given a constraint, adds it to the solver.
std::shared_ptr< SMTSolver > SMTSolverRef
Shared pointer for SMTSolvers.
virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp)=0
Creates a floating-point isInfinite operation.
Generic base class for SMT Solvers.
virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector xor operation.
virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int)=0
Given an expression, extract the value of this operand in the model.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point equality operation.
SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty, bool Assumption)
virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp)=0
Creates a floating-point isNormal operation.
SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, QualType FromTy, uint64_t FromBitWidth)
Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and their bit widths.
virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned modulus operation.
BinaryOperator::Opcode getOpcode() const
virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, const SMTSortRef &To)=0
Creates a floating-point conversion from floatint-point to unsigned bitvector operation.
virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned greater-than operation.
virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point greater-than operation.
virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low, const SMTExprRef &Exp)=0
Creates a bitvector extract operation.
virtual SMTExprRef mkFloat(const llvm::APFloat Float)=0
Constructs an SMTExprRef from a finite APFloat.
virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, bool isUnsigned)=0
std::shared_ptr< SMTExpr > SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
virtual SMTExprRef getFloatRoundingMode()=0
virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth)=0
Constructs an SMTExprRef from an APSInt and its bit width.
virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To)=0
Creates a floating-point conversion from floatint-point to floating-point operation.
SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType FromTy, QualType ToTy)
virtual void reset() const =0
Reset the solver and remove all constraints.
void doFloatTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
virtual void push()=0
Push the current solver state.
SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE, bool *hasComparison, QualType *RetTy)
virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a floating-point less-than operation.
virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS)=0
Creates a bitvector unsigned less-equal-than operation.
Represents a symbolic expression like 'x' + 'y'.
A symbol representing data which can be stored in a memory location (region).
virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp)=0
Creates a floating-point negation operation.
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth, signed/unsigned.
virtual SMTExprRef mkBVNot(const SMTExprRef &Exp)=0
Creates a bitvector not operation.