14 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H 15 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H 31 return Solver->getBoolSort();
34 return Solver->getFloatSort(BitWidth);
36 return Solver->getBitvectorSort(BitWidth);
45 return Solver->mkBVNeg(Exp);
48 return Solver->mkBVNot(Exp);
51 return Solver->mkNot(Exp);
55 llvm_unreachable(
"Unimplemented opcode");
64 return Solver->mkFPNeg(Exp);
71 llvm_unreachable(
"Unimplemented opcode");
77 const std::vector<SMTExprRef> &ASTs) {
78 assert(!ASTs.empty());
80 if (Op != BO_LAnd && Op != BO_LOr)
81 llvm_unreachable(
"Unimplemented opcode");
85 res = (Op == BO_LAnd) ? Solver->mkAnd(res, ASTs[i])
86 : Solver->mkOr(res, ASTs[i]);
95 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
96 "AST's must have the same sort!");
101 return Solver->mkBVMul(LHS, RHS);
104 return isSigned ? Solver->mkBVSDiv(LHS, RHS) : Solver->mkBVUDiv(LHS, RHS);
107 return isSigned ? Solver->mkBVSRem(LHS, RHS) : Solver->mkBVURem(LHS, RHS);
111 return Solver->mkBVAdd(LHS, RHS);
114 return Solver->mkBVSub(LHS, RHS);
118 return Solver->mkBVShl(LHS, RHS);
121 return isSigned ? Solver->mkBVAshr(LHS, RHS) : Solver->mkBVLshr(LHS, RHS);
125 return isSigned ? Solver->mkBVSlt(LHS, RHS) : Solver->mkBVUlt(LHS, RHS);
128 return isSigned ? Solver->mkBVSgt(LHS, RHS) : Solver->mkBVUgt(LHS, RHS);
131 return isSigned ? Solver->mkBVSle(LHS, RHS) : Solver->mkBVUle(LHS, RHS);
134 return isSigned ? Solver->mkBVSge(LHS, RHS) : Solver->mkBVUge(LHS, RHS);
138 return Solver->mkEqual(LHS, RHS);
142 fromBinOp(Solver, LHS, BO_EQ, RHS, isSigned));
146 return Solver->mkBVAnd(LHS, RHS);
149 return Solver->mkBVXor(LHS, RHS);
152 return Solver->mkBVOr(LHS, RHS);
156 return Solver->mkAnd(LHS, RHS);
159 return Solver->mkOr(LHS, RHS);
163 llvm_unreachable(
"Unimplemented opcode");
170 const llvm::APFloat::fltCategory &RHS) {
175 case llvm::APFloat::fcInfinity:
176 return Solver->mkFPIsInfinite(LHS);
178 case llvm::APFloat::fcNaN:
179 return Solver->mkFPIsNaN(LHS);
181 case llvm::APFloat::fcNormal:
182 return Solver->mkFPIsNormal(LHS);
184 case llvm::APFloat::fcZero:
185 return Solver->mkFPIsZero(LHS);
196 llvm_unreachable(
"Unimplemented opcode");
204 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
205 "AST's must have the same sort!");
210 return Solver->mkFPMul(LHS, RHS);
213 return Solver->mkFPDiv(LHS, RHS);
216 return Solver->mkFPRem(LHS, RHS);
220 return Solver->mkFPAdd(LHS, RHS);
223 return Solver->mkFPSub(LHS, RHS);
227 return Solver->mkFPLt(LHS, RHS);
230 return Solver->mkFPGt(LHS, RHS);
233 return Solver->mkFPLe(LHS, RHS);
236 return Solver->mkFPGe(LHS, RHS);
240 return Solver->mkFPEqual(LHS, RHS);
249 return fromBinOp(Solver, LHS, Op, RHS,
false);
254 llvm_unreachable(
"Unimplemented opcode");
261 QualType FromTy, uint64_t FromBitWidth) {
269 assert(ToBitWidth > 0 &&
"BitWidth must be positive!");
270 return Solver->mkIte(
271 Exp, Solver->mkBitvector(llvm::APSInt(
"1"), ToBitWidth),
272 Solver->mkBitvector(llvm::APSInt(
"0"), ToBitWidth));
275 if (ToBitWidth > FromBitWidth)
277 ? Solver->mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
278 : Solver->mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
280 if (ToBitWidth < FromBitWidth)
281 return Solver->mkBVExtract(ToBitWidth - 1, 0, Exp);
288 if (ToBitWidth != FromBitWidth)
289 return Solver->mkFPtoFP(Exp, Solver->getFloatSort(ToBitWidth));
295 SMTSortRef Sort = Solver->getFloatSort(ToBitWidth);
297 ? Solver->mkSBVtoFP(Exp, Sort)
298 : Solver->mkUBVtoFP(Exp, Sort);
303 ? Solver->mkFPtoSBV(Exp, ToBitWidth)
304 : Solver->mkFPtoUBV(Exp, ToBitWidth);
306 llvm_unreachable(
"Unsupported explicit type cast!");
311 const llvm::APSInt &V,
QualType ToTy,
313 uint64_t FromWidth) {
320 const QualType &Ty, uint64_t BitWidth) {
321 llvm::Twine Name =
"$" + llvm::Twine(ID);
322 return Solver->mkSymbol(Name.str().c_str(),
mkSort(Solver, Ty, BitWidth));
373 bool *hasComparison,
QualType *RetTy) {
377 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
379 getSymExpr(Solver, Ctx, SIE->getLHS(), <y, hasComparison);
380 llvm::APSInt NewRInt;
381 std::tie(NewRInt, RTy) =
fixAPSInt(Ctx, SIE->getRHS());
382 SMTExprRef RHS = Solver->mkBitvector(NewRInt, NewRInt.getBitWidth());
383 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
386 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
387 llvm::APSInt NewLInt;
388 std::tie(NewLInt, LTy) =
fixAPSInt(Ctx, ISE->getLHS());
389 SMTExprRef LHS = Solver->mkBitvector(NewLInt, NewLInt.getBitWidth());
391 getSymExpr(Solver, Ctx, ISE->getRHS(), &RTy, hasComparison);
392 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
395 if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
397 getSymExpr(Solver, Ctx, SSM->getLHS(), <y, hasComparison);
399 getSymExpr(Solver, Ctx, SSM->getRHS(), &RTy, hasComparison);
400 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
403 llvm_unreachable(
"Unsupported BinarySymExpr type!");
410 bool *hasComparison) {
411 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
419 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
425 getSymExpr(Solver, Ctx, SC->getOperand(), &FromTy, hasComparison);
431 *hasComparison =
false;
435 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
443 llvm_unreachable(
"Unsupported SymbolRef type!");
452 bool *hasComparison =
nullptr) {
454 *hasComparison =
false;
457 return getSymExpr(Solver, Ctx, Sym, RetTy, hasComparison);
469 Solver->mkFloat(Zero));
478 return Assumption ?
fromUnOp(Solver, UO_LNot, Exp) : Exp;
481 Solver, Exp, Assumption ? BO_EQ : BO_NE,
482 Solver->mkBitvector(llvm::APSInt(
"0"), Ctx.
getTypeSize(Ty)),
486 llvm_unreachable(
"Unsupported type for zero value!");
493 const llvm::APSInt &To,
bool InRange) {
496 llvm::APSInt NewFromInt;
497 std::tie(NewFromInt, FromTy) =
fixAPSInt(Ctx, From);
499 Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth());
507 return getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE,
508 FromExp, FromTy,
nullptr);
511 llvm::APSInt NewToInt;
512 std::tie(NewToInt, ToTy) =
fixAPSInt(Ctx, To);
513 SMTExprRef ToExp = Solver->mkBitvector(NewToInt, NewToInt.getBitWidth());
514 assert(FromTy == ToTy &&
"Range values have different types!");
518 getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp,
521 InRange ? BO_LE : BO_GT, ToExp, ToTy,
524 return fromBinOp(Solver, LHS, InRange ? BO_LAnd : BO_LOr, RHS,
531 const llvm::APSInt &Int) {
536 static inline std::pair<llvm::APSInt, QualType>
557 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
563 SMTConv::doIntTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS, LTy,
569 SMTConv::doFloatTypeConversion<SMTExprRef, &fromCast>(Solver, Ctx, LHS,
590 LHS =
fromCast(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
593 RHS =
fromCast(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
604 "Pointer types have different bitwidths!");
629 uint64_t, QualType, uint64_t)>
631 T &LHS, QualType <y, T &RHS,
637 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
643 LHS = (*doCast)(Solver, LHS, NewTy, NewBitWidth, LTy, LBitWidth);
645 LBitWidth = NewBitWidth;
650 RHS = (*doCast)(Solver, RHS, NewTy, NewBitWidth, RTy, RBitWidth);
652 RBitWidth = NewBitWidth;
664 if (isLSignedTy == isRSignedTy) {
667 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
670 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
673 }
else if (order != (isLSignedTy ? 1 : -1)) {
677 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
680 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
683 }
else if (LBitWidth != RBitWidth) {
688 RHS = (doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
691 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
701 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
703 LHS = (doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
711 template <
typename T, T (*doCast)(
SMTSolverRef &Solver,
const T &, QualType,
712 uint64_t, QualType, uint64_t)>
715 QualType <y, T &RHS, QualType &RTy) {
722 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
724 LBitWidth = RBitWidth;
727 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
729 RBitWidth = LBitWidth;
740 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
742 }
else if (order == 0) {
743 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
746 llvm_unreachable(
"Unsupported floating-point type cast!");
static QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int)
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
static SMTExprRef fromNBinOp(SMTSolverRef &Solver, const BinaryOperator::Opcode Op, const std::vector< SMTExprRef > &ASTs)
Construct an SMTExprRef from a n-ary binary operator.
static SMTExprRef getCastExpr(SMTSolverRef &Solver, ASTContext &Ctx, const SMTExprRef &Exp, QualType FromTy, QualType ToTy)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
static SMTExprRef getRangeExpr(SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
static SMTExprRef getBinExpr(SMTSolverRef &Solver, ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, const SMTExprRef &RHS, QualType RTy, QualType *RetTy)
bool isArithmeticType() const
bool isRealFloatingType() const
Floating point categories.
static SMTExprRef getZeroExpr(SMTSolverRef &Solver, ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty, bool Assumption)
static SMTExprRef getExpr(SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy=nullptr, bool *hasComparison=nullptr)
QualType getCorrespondingUnsignedType(QualType T) const
static SMTExprRef fromFloatUnOp(SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const SMTExprRef &Exp)
Constructs an SMTExprRef from a floating-point unary operator.
static SMTSortRef mkSort(SMTSolverRef &Solver, const QualType &Ty, unsigned BitWidth)
static SMTExprRef fromUnOp(SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const SMTExprRef &Exp)
Constructs an SMTExprRef from an unary operator.
static llvm::APSInt castAPSInt(SMTSolverRef &Solver, const llvm::APSInt &V, QualType ToTy, uint64_t ToWidth, QualType FromTy, uint64_t FromWidth)
static std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
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 ...
static SMTExprRef fromData(SMTSolverRef &Solver, const SymbolID ID, const QualType &Ty, uint64_t BitWidth)
Construct an SMTExprRef from a SymbolData.
static SMTExprRef fromCast(SMTSolverRef &Solver, 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.
bool isReferenceType() const
static void doFloatTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
static SMTExprRef getSymExpr(SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, bool *hasComparison)
static SMTExprRef fromFloatSpecialBinOp(SMTSolverRef &Solver, const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS)
Construct an SMTExprRef from a special floating-point binary operator.
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
static SMTExprRef getSymBinExpr(SMTSolverRef &Solver, ASTContext &Ctx, const BinarySymExpr *BSE, bool *hasComparison, QualType *RetTy)
A record of the "type" of an APSInt, used for conversions.
Represents a symbolic expression like 'x' + 3.
virtual QualType getType() const =0
bool isPromotableIntegerType() const
More type predicates useful for type checking/promotion.
static SMTExprRef fromFloatBinOp(SMTSolverRef &Solver, const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS)
Construct an SMTExprRef from a floating-point binary operator.
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
static void doIntTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
bool isNullPtrType() const
Represents a cast expression.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
bool isVoidPointerType() const
bool isComparisonOp() const
QualType getCanonicalType() const
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
static SMTExprRef fromBinOp(SMTSolverRef &Solver, const SMTExprRef &LHS, const BinaryOperator::Opcode Op, const SMTExprRef &RHS, bool isSigned)
Construct an SMTExprRef from a binary operator.
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
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...
Represents a symbolic expression involving a binary operator.
bool isBooleanType() const
std::shared_ptr< SMTSolver > SMTSolverRef
Shared pointer for SMTSolvers.
static void doTypeConversion(SMTSolverRef &Solver, ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS, QualType <y, QualType &RTy)
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
BinaryOperator::Opcode getOpcode() const
std::shared_ptr< SMTExpr > SMTExprRef
Shared pointer for SMTExprs, used by SMTSolver API.
Represents a symbolic expression like 'x' + 'y'.
A symbol representing data which can be stored in a memory location (region).
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth, signed/unsigned.