13#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H
14#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONV_H
19#include "llvm/Support/SMTAPI.h"
29 static inline llvm::SMTSortRef
mkSort(llvm::SMTSolverRef &Solver,
30 const QualType &Ty,
unsigned BitWidth) {
32 return Solver->getBoolSort();
35 return Solver->getFloatSort(BitWidth);
37 return Solver->getBitvectorSort(BitWidth);
41 static inline llvm::SMTExprRef
fromUnOp(llvm::SMTSolverRef &Solver,
43 const llvm::SMTExprRef &Exp) {
46 return Solver->mkBVNeg(Exp);
49 return Solver->mkBVNot(Exp);
52 return Solver->mkNot(Exp);
56 llvm_unreachable(
"Unimplemented opcode");
60 static inline llvm::SMTExprRef
fromFloatUnOp(llvm::SMTSolverRef &Solver,
62 const llvm::SMTExprRef &Exp) {
65 return Solver->mkFPNeg(Exp);
72 llvm_unreachable(
"Unimplemented opcode");
76 static inline llvm::SMTExprRef
78 const std::vector<llvm::SMTExprRef> &ASTs) {
79 assert(!ASTs.empty());
81 if (Op != BO_LAnd && Op != BO_LOr)
82 llvm_unreachable(
"Unimplemented opcode");
84 llvm::SMTExprRef res = ASTs.front();
85 for (std::size_t i = 1; i < ASTs.size(); ++i)
86 res = (Op == BO_LAnd) ? Solver->mkAnd(res, ASTs[i])
87 : Solver->mkOr(res, ASTs[i]);
92 static inline llvm::SMTExprRef
fromBinOp(llvm::SMTSolverRef &Solver,
93 const llvm::SMTExprRef &LHS,
95 const llvm::SMTExprRef &RHS,
97 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
98 "AST's must have the same sort!");
103 return Solver->mkBVMul(LHS, RHS);
106 return isSigned ? Solver->mkBVSDiv(LHS, RHS) : Solver->mkBVUDiv(LHS, RHS);
109 return isSigned ? Solver->mkBVSRem(LHS, RHS) : Solver->mkBVURem(LHS, RHS);
113 return Solver->mkBVAdd(LHS, RHS);
116 return Solver->mkBVSub(LHS, RHS);
120 return Solver->mkBVShl(LHS, RHS);
123 return isSigned ? Solver->mkBVAshr(LHS, RHS) : Solver->mkBVLshr(LHS, RHS);
127 return isSigned ? Solver->mkBVSlt(LHS, RHS) : Solver->mkBVUlt(LHS, RHS);
130 return isSigned ? Solver->mkBVSgt(LHS, RHS) : Solver->mkBVUgt(LHS, RHS);
133 return isSigned ? Solver->mkBVSle(LHS, RHS) : Solver->mkBVUle(LHS, RHS);
136 return isSigned ? Solver->mkBVSge(LHS, RHS) : Solver->mkBVUge(LHS, RHS);
140 return Solver->mkEqual(LHS, RHS);
144 fromBinOp(Solver, LHS, BO_EQ, RHS, isSigned));
148 return Solver->mkBVAnd(LHS, RHS);
151 return Solver->mkBVXor(LHS, RHS);
154 return Solver->mkBVOr(LHS, RHS);
158 return Solver->mkAnd(LHS, RHS);
161 return Solver->mkOr(LHS, RHS);
165 llvm_unreachable(
"Unimplemented opcode");
170 static inline llvm::SMTExprRef
173 const llvm::APFloat::fltCategory &RHS) {
178 case llvm::APFloat::fcInfinity:
179 return Solver->mkFPIsInfinite(LHS);
181 case llvm::APFloat::fcNaN:
182 return Solver->mkFPIsNaN(LHS);
184 case llvm::APFloat::fcNormal:
185 return Solver->mkFPIsNormal(LHS);
187 case llvm::APFloat::fcZero:
188 return Solver->mkFPIsZero(LHS);
199 llvm_unreachable(
"Unimplemented opcode");
204 const llvm::SMTExprRef &LHS,
206 const llvm::SMTExprRef &RHS) {
207 assert(*Solver->getSort(LHS) == *Solver->getSort(RHS) &&
208 "AST's must have the same sort!");
213 return Solver->mkFPMul(LHS, RHS);
216 return Solver->mkFPDiv(LHS, RHS);
219 return Solver->mkFPRem(LHS, RHS);
223 return Solver->mkFPAdd(LHS, RHS);
226 return Solver->mkFPSub(LHS, RHS);
230 return Solver->mkFPLt(LHS, RHS);
233 return Solver->mkFPGt(LHS, RHS);
236 return Solver->mkFPLe(LHS, RHS);
239 return Solver->mkFPGe(LHS, RHS);
243 return Solver->mkFPEqual(LHS, RHS);
252 return fromBinOp(Solver, LHS, Op, RHS,
false);
257 llvm_unreachable(
"Unimplemented opcode");
262 static inline llvm::SMTExprRef
fromCast(llvm::SMTSolverRef &Solver,
263 const llvm::SMTExprRef &Exp,
266 uint64_t FromBitWidth) {
274 assert(ToBitWidth > 0 &&
"BitWidth must be positive!");
275 return Solver->mkIte(
276 Exp, Solver->mkBitvector(llvm::APSInt(
"1"), ToBitWidth),
277 Solver->mkBitvector(llvm::APSInt(
"0"), ToBitWidth));
280 if (ToBitWidth > FromBitWidth)
282 ? Solver->mkBVSignExt(ToBitWidth - FromBitWidth, Exp)
283 : Solver->mkBVZeroExt(ToBitWidth - FromBitWidth, Exp);
285 if (ToBitWidth < FromBitWidth)
286 return Solver->mkBVExtract(ToBitWidth - 1, 0, Exp);
293 if (ToBitWidth != FromBitWidth)
294 return Solver->mkFPtoFP(Exp, Solver->getFloatSort(ToBitWidth));
300 llvm::SMTSortRef Sort = Solver->getFloatSort(ToBitWidth);
302 ? Solver->mkSBVtoFP(Exp, Sort)
303 : Solver->mkUBVtoFP(Exp, Sort);
308 ? Solver->mkFPtoSBV(Exp, ToBitWidth)
309 : Solver->mkFPtoUBV(Exp, ToBitWidth);
311 llvm_unreachable(
"Unsupported explicit type cast!");
315 static inline llvm::APSInt
castAPSInt(llvm::SMTSolverRef &Solver,
318 uint64_t FromWidth) {
324 static inline llvm::SMTExprRef
331 llvm::raw_svector_ostream
OS(Str);
333 return Solver->mkSymbol(Str.c_str(),
mkSort(Solver, Ty, BitWidth));
337 static inline llvm::SMTExprRef
getCastExpr(llvm::SMTSolverRef &Solver,
339 const llvm::SMTExprRef &Exp,
347 static inline llvm::SMTExprRef
349 const llvm::SMTExprRef &LHS,
QualType LTy,
352 llvm::SMTExprRef NewLHS = LHS;
353 llvm::SMTExprRef NewRHS = RHS;
388 if (
const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
389 llvm::SMTExprRef LHS =
390 getSymExpr(Solver, Ctx, SIE->getLHS(), LTy, hasComparison);
391 llvm::APSInt NewRInt;
392 std::tie(NewRInt, RTy) =
fixAPSInt(Ctx, SIE->getRHS());
393 llvm::SMTExprRef RHS =
394 Solver->mkBitvector(NewRInt, NewRInt.getBitWidth());
395 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
398 if (
const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
399 llvm::APSInt NewLInt;
400 std::tie(NewLInt, LTy) =
fixAPSInt(Ctx, ISE->getLHS());
401 llvm::SMTExprRef LHS =
402 Solver->mkBitvector(NewLInt, NewLInt.getBitWidth());
403 llvm::SMTExprRef RHS =
404 getSymExpr(Solver, Ctx, ISE->getRHS(), RTy, hasComparison);
405 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
408 if (
const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
409 llvm::SMTExprRef LHS =
410 getSymExpr(Solver, Ctx, SSM->getLHS(), LTy, hasComparison);
411 llvm::SMTExprRef RHS =
412 getSymExpr(Solver, Ctx, SSM->getRHS(), RTy, hasComparison);
413 return getBinExpr(Solver, Ctx, LHS, LTy, Op, RHS, RTy, RetTy);
416 llvm_unreachable(
"Unsupported BinarySymExpr type!");
421 static inline llvm::SMTExprRef
getSymExpr(llvm::SMTSolverRef &Solver,
424 bool *hasComparison) {
425 if (
const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
431 if (
const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
435 llvm::SMTExprRef Exp =
436 getSymExpr(Solver, Ctx, SC->getOperand(), FromTy, hasComparison);
442 *hasComparison =
false;
446 if (
const UnarySymExpr *USE = dyn_cast<UnarySymExpr>(Sym)) {
450 llvm::SMTExprRef OperandExp =
451 getSymExpr(Solver, Ctx, USE->getOperand(), OperandTy, hasComparison);
457 if (OperandTy == Ctx.
BoolTy && OperandTy != RetTy &&
464 llvm::SMTExprRef UnaryExp =
467 :
fromUnOp(Solver, USE->getOpcode(), OperandExp);
475 *hasComparison =
false;
481 if (
const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
482 llvm::SMTExprRef Exp =
490 llvm_unreachable(
"Unsupported SymbolRef type!");
497 static inline llvm::SMTExprRef
getExpr(llvm::SMTSolverRef &Solver,
500 bool *hasComparison =
nullptr) {
502 *hasComparison =
false;
505 return getSymExpr(Solver, Ctx, Sym, RetTy, hasComparison);
509 static inline llvm::SMTExprRef
getZeroExpr(llvm::SMTSolverRef &Solver,
511 const llvm::SMTExprRef &Exp,
517 Solver->mkFloat(
Zero));
526 return Assumption ?
fromUnOp(Solver, UO_LNot, Exp) : Exp;
529 Solver, Exp, Assumption ? BO_EQ : BO_NE,
530 Solver->mkBitvector(llvm::APSInt(
"0"), Ctx.
getTypeSize(Ty)),
534 llvm_unreachable(
"Unsupported type for zero value!");
539 static inline llvm::SMTExprRef
541 const llvm::APSInt &From,
const llvm::APSInt &To,
bool InRange) {
544 llvm::APSInt NewFromInt;
545 std::tie(NewFromInt, FromTy) =
fixAPSInt(Ctx, From);
546 llvm::SMTExprRef FromExp =
547 Solver->mkBitvector(NewFromInt, NewFromInt.getBitWidth());
551 llvm::SMTExprRef Exp =
getExpr(Solver, Ctx, Sym, SymTy);
556 return getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE,
557 FromExp, FromTy, UnusedRetTy);
561 llvm::APSInt NewToInt;
562 std::tie(NewToInt, ToTy) =
fixAPSInt(Ctx, To);
563 llvm::SMTExprRef ToExp =
564 Solver->mkBitvector(NewToInt, NewToInt.getBitWidth());
565 assert(FromTy == ToTy &&
"Range values have different types!");
569 llvm::SMTExprRef LHS =
570 getBinExpr(Solver, Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, FromExp,
571 FromTy, UnusedRetTy);
572 llvm::SMTExprRef RHS =
getBinExpr(Solver, Ctx, Exp, SymTy,
573 InRange ? BO_LE : BO_GT, ToExp, ToTy,
576 return fromBinOp(Solver, LHS, InRange ? BO_LAnd : BO_LOr, RHS,
583 const llvm::APSInt &Int) {
592 unsigned Pow2DestWidth =
593 std::max(llvm::bit_ceil(Int.getBitWidth()), CharTypeSize);
598 static inline std::pair<llvm::APSInt, QualType>
601 unsigned APSIntBitwidth = Int.getBitWidth();
607 if (APSIntBitwidth == 1 && Ty.
isNull())
610 else if (APSIntBitwidth == 1 && !Ty.
isNull())
613 if (llvm::isPowerOf2_32(APSIntBitwidth) || Ty.
isNull())
623 llvm::SMTExprRef &RHS,
QualType <y,
625 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
632 Solver, Ctx, LHS, LTy, RHS, RTy);
638 Solver, Ctx, LHS, LTy, RHS, RTy);
658 LHS =
fromCast(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
661 RHS =
fromCast(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
672 "Pointer types have different bitwidths!");
696 template <
typename T, T (*doCast)(llvm::SMTSolverRef &Solver,
const T &,
704 assert(!LTy.
isNull() && !RTy.
isNull() &&
"Input type is null!");
710 LHS = (*doCast)(Solver, LHS, NewTy, NewBitWidth, LTy, LBitWidth);
712 LBitWidth = NewBitWidth;
717 RHS = (*doCast)(Solver, RHS, NewTy, NewBitWidth, RTy, RBitWidth);
719 RBitWidth = NewBitWidth;
731 if (isLSignedTy == isRSignedTy) {
734 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
737 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
740 }
else if (order != (isLSignedTy ? 1 : -1)) {
744 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
747 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
750 }
else if (LBitWidth != RBitWidth) {
755 RHS = (doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
758 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
768 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
770 LHS = (doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
778 template <
typename T, T (*doCast)(llvm::SMTSolverRef &Solver,
const T &,
788 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
790 LBitWidth = RBitWidth;
793 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
795 RBitWidth = LBitWidth;
806 RHS = (*doCast)(Solver, RHS, LTy, LBitWidth, RTy, RBitWidth);
808 }
else if (order == 0) {
809 LHS = (*doCast)(Solver, LHS, RTy, RBitWidth, LTy, LBitWidth);
812 llvm_unreachable(
"Unsupported floating-point type cast!");
Expr * getExpr()
Get 'expr' part of the associated expression/statement.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
int getIntegerTypeOrder(QualType LHS, QualType RHS) const
Return the highest ranked integer type, see C99 6.3.1.8p1.
QualType getPointerDiffType() const
Return the unique type for "ptrdiff_t" (C99 7.17) defined in <stddef.h>.
int getFloatingTypeOrder(QualType LHS, QualType RHS) const
Compare the rank of the two specified floating point types, ignoring the domain of the type (i....
QualType getIntTypeForBitwidth(unsigned DestWidth, unsigned Signed) const
getIntTypeForBitwidth - sets integer QualTy according to specified details: bitwidth,...
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
QualType getPromotedIntegerType(QualType PromotableType) const
Return the type that PromotableType will promote to: C99 6.3.1.1p2, assuming that PromotableType is a...
QualType getCorrespondingUnsignedType(QualType T) const
bool isPromotableIntegerType(QualType T) const
More type predicates useful for type checking/promotion.
static bool isLogicalOp(Opcode Opc)
static bool isComparisonOp(Opcode Opc)
bool isComparisonOp() const
BinaryOperatorKind Opcode
A (possibly-)qualified type.
bool isNull() const
Return true if this QualType doesn't point to a type yet.
QualType getCanonicalType() const
bool isBlockPointerType() 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 isVoidPointerType() const
bool isArithmeticType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isReferenceType() const
bool isIntegralOrEnumerationType() const
Determine whether this type is an integral or enumeration type.
bool isObjCObjectPointerType() const
bool isRealFloatingType() const
Floating point categories.
bool isAnyPointerType() const
bool isNullPtrType() const
A record of the "type" of an APSInt, used for conversions.
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.
Represents a symbolic expression involving a binary operator.
BinaryOperator::Opcode getOpcode() const
static llvm::SMTSortRef mkSort(llvm::SMTSolverRef &Solver, const QualType &Ty, unsigned BitWidth)
static llvm::SMTExprRef fromFloatBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS)
Construct an SMTSolverRef from a floating-point binary operator.
static QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int)
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 llvm::SMTExprRef getRangeExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, const llvm::APSInt &From, const llvm::APSInt &To, bool InRange)
static llvm::SMTExprRef fromNBinOp(llvm::SMTSolverRef &Solver, const BinaryOperator::Opcode Op, const std::vector< llvm::SMTExprRef > &ASTs)
Construct an SMTSolverRef from a n-ary binary operator.
static void doTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, llvm::SMTExprRef &LHS, llvm::SMTExprRef &RHS, QualType <y, QualType &RTy)
static llvm::SMTExprRef getSymExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType &RetTy, bool *hasComparison)
static llvm::SMTExprRef fromFloatSpecialBinOp(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &LHS, const BinaryOperator::Opcode Op, const llvm::APFloat::fltCategory &RHS)
Construct an SMTSolverRef from a special floating-point binary operator.
static llvm::SMTExprRef fromData(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const SymbolData *Sym)
Construct an SMTSolverRef from a SymbolData.
static void doFloatTypeConversion(llvm::SMTSolverRef &Solver, ASTContext &Ctx, T &LHS, QualType <y, T &RHS, QualType &RTy)
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 llvm::SMTExprRef getBinExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &LHS, QualType LTy, BinaryOperator::Opcode Op, const llvm::SMTExprRef &RHS, QualType RTy, QualType &RetTy)
static llvm::SMTExprRef getCastExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const llvm::SMTExprRef &Exp, QualType FromTy, QualType ToTy)
static std::pair< llvm::APSInt, QualType > fixAPSInt(ASTContext &Ctx, const llvm::APSInt &Int)
static llvm::SMTExprRef fromCast(llvm::SMTSolverRef &Solver, const llvm::SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, QualType FromTy, uint64_t FromBitWidth)
Construct an SMTSolverRef from a QualType FromTy to a QualType ToTy, and their bit widths.
static llvm::APSInt castAPSInt(llvm::SMTSolverRef &Solver, const llvm::APSInt &V, QualType ToTy, uint64_t ToWidth, QualType FromTy, uint64_t FromWidth)
static llvm::SMTExprRef getSymBinExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, const BinarySymExpr *BSE, bool *hasComparison, QualType &RetTy)
static llvm::SMTExprRef fromFloatUnOp(llvm::SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const llvm::SMTExprRef &Exp)
Constructs an SMTSolverRef from a floating-point unary operator.
static llvm::SMTExprRef fromUnOp(llvm::SMTSolverRef &Solver, const UnaryOperator::Opcode Op, const llvm::SMTExprRef &Exp)
Constructs an SMTSolverRef from an unary operator.
static llvm::SMTExprRef getExpr(llvm::SMTSolverRef &Solver, ASTContext &Ctx, SymbolRef Sym, QualType &RetTy, bool *hasComparison=nullptr)
virtual QualType getType() const =0
SymbolID getSymbolID() const
Get a unique identifier for this symbol.
Represents a cast expression.
A symbol representing data which can be stored in a memory location (region).
virtual StringRef getKindStr() const =0
Get a string representation of the kind of the region.
Represents a symbolic expression involving a unary operator.
BinarySymExprImpl< APSIntPtr, const SymExpr *, SymExpr::Kind::IntSymExprKind > IntSymExpr
Represents a symbolic expression like 3 - 'x'.
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.
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
The JSON file list parser is used to communicate input to InstallAPI.