1 //== SMTConstraintManager.cpp -----------------------------------*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h"
11 #include "clang/Basic/TargetInfo.h"
12 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
13 #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
15 using namespace clang;
18 ProgramStateRef SMTConstraintManager::assumeSym(ProgramStateRef State,
21 ASTContext &Ctx = getBasicVals().getContext();
26 SMTExprRef Exp = Solver->getExpr(Ctx, Sym, &RetTy, &hasComparison);
28 // Create zero comparison for implicit boolean cast, with reversed assumption
29 if (!hasComparison && !RetTy->isBooleanType())
30 return assumeExpr(State, Sym,
31 Solver->getZeroExpr(Ctx, Exp, RetTy, !Assumption));
33 return assumeExpr(State, Sym, Assumption ? Exp : Solver->mkNot(Exp));
36 ProgramStateRef SMTConstraintManager::assumeSymInclusiveRange(
37 ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From,
38 const llvm::APSInt &To, bool InRange) {
39 ASTContext &Ctx = getBasicVals().getContext();
40 return assumeExpr(State, Sym,
41 Solver->getRangeExpr(Ctx, Sym, From, To, InRange));
45 SMTConstraintManager::assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym,
47 // Skip anything that is unsupported
51 ConditionTruthVal SMTConstraintManager::checkNull(ProgramStateRef State,
53 ASTContext &Ctx = getBasicVals().getContext();
56 // The expression may be casted, so we cannot call getZ3DataExpr() directly
57 SMTExprRef VarExp = Solver->getExpr(Ctx, Sym, &RetTy);
58 SMTExprRef Exp = Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/true);
60 // Negate the constraint
62 Solver->getZeroExpr(Ctx, VarExp, RetTy, /*Assumption=*/false);
65 addStateConstraints(State);
68 Solver->addConstraint(Exp);
69 ConditionTruthVal isSat = Solver->check();
72 Solver->addConstraint(NotExp);
73 ConditionTruthVal isNotSat = Solver->check();
75 // Zero is the only possible solution
76 if (isSat.isConstrainedTrue() && isNotSat.isConstrainedFalse())
79 // Zero is not a solution
80 if (isSat.isConstrainedFalse() && isNotSat.isConstrainedTrue())
83 // Zero may be a solution
84 return ConditionTruthVal();
87 const llvm::APSInt *SMTConstraintManager::getSymVal(ProgramStateRef State,
88 SymbolRef Sym) const {
89 BasicValueFactory &BVF = getBasicVals();
90 ASTContext &Ctx = BVF.getContext();
92 if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) {
93 QualType Ty = Sym->getType();
94 assert(!Ty->isRealFloatingType());
95 llvm::APSInt Value(Ctx.getTypeSize(Ty),
96 !Ty->isSignedIntegerOrEnumerationType());
99 Solver->fromData(SD->getSymbolID(), Ty, Ctx.getTypeSize(Ty));
102 addStateConstraints(State);
104 // Constraints are unsatisfiable
105 ConditionTruthVal isSat = Solver->check();
106 if (!isSat.isConstrainedTrue())
109 // Model does not assign interpretation
110 if (!Solver->getInterpretation(Exp, Value))
113 // A value has been obtained, check if it is the only value
114 SMTExprRef NotExp = Solver->fromBinOp(
116 Ty->isBooleanType() ? Solver->fromBoolean(Value.getBoolValue())
117 : Solver->fromAPSInt(Value),
120 Solver->addConstraint(NotExp);
122 ConditionTruthVal isNotSat = Solver->check();
123 if (isNotSat.isConstrainedTrue())
126 // This is the only solution, store it
127 return &BVF.getValue(Value);
130 if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) {
131 SymbolRef CastSym = SC->getOperand();
132 QualType CastTy = SC->getType();
133 // Skip the void type
134 if (CastTy->isVoidType())
137 const llvm::APSInt *Value;
138 if (!(Value = getSymVal(State, CastSym)))
140 return &BVF.Convert(SC->getType(), *Value);
143 if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) {
144 const llvm::APSInt *LHS, *RHS;
145 if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) {
146 LHS = getSymVal(State, SIE->getLHS());
147 RHS = &SIE->getRHS();
148 } else if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) {
149 LHS = &ISE->getLHS();
150 RHS = getSymVal(State, ISE->getRHS());
151 } else if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) {
152 // Early termination to avoid expensive call
153 LHS = getSymVal(State, SSM->getLHS());
154 RHS = LHS ? getSymVal(State, SSM->getRHS()) : nullptr;
156 llvm_unreachable("Unsupported binary expression to get symbol value!");
162 llvm::APSInt ConvertedLHS, ConvertedRHS;
164 std::tie(ConvertedLHS, LTy) = Solver->fixAPSInt(Ctx, *LHS);
165 std::tie(ConvertedRHS, RTy) = Solver->fixAPSInt(Ctx, *RHS);
166 Solver->doIntTypeConversion<llvm::APSInt, &SMTSolver::castAPSInt>(
167 Ctx, ConvertedLHS, LTy, ConvertedRHS, RTy);
168 return BVF.evalAPSInt(BSE->getOpcode(), ConvertedLHS, ConvertedRHS);
171 llvm_unreachable("Unsupported expression to get symbol value!");
175 SMTConstraintManager::checkModel(ProgramStateRef State,
176 const SMTExprRef &Exp) const {
178 Solver->addConstraint(Exp);
179 addStateConstraints(State);
180 return Solver->check();