#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h"
#include "clang/StaticAnalyzer/Core/PathSensitive/SMTConv.h"
+typedef llvm::ImmutableSet<
+ std::pair<clang::ento::SymbolRef, const clang::ento::SMTExpr *>>
+ ConstraintSMTTy;
+REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintSMT, ConstraintSMTTy)
+
namespace clang {
namespace ento {
-template <typename ConstraintSMT, typename SMTExprTy>
class SMTConstraintManager : public clang::ento::SimpleConstraintManager {
SMTSolverRef &Solver;
OS << nl << sep << "Constraints:";
for (auto I = CZ.begin(), E = CZ.end(); I != E; ++I) {
OS << nl << ' ' << I->first << " : ";
- I->second.print(OS);
+ I->second->print(OS);
}
OS << nl;
}
const SMTExprRef &Exp) {
// Check the model, avoid simplifying AST to save time
if (checkModel(State, Sym, Exp).isConstrainedTrue())
- return State->add<ConstraintSMT>(
- std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp)));
+ return State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
return nullptr;
}
if (I != IE) {
std::vector<SMTExprRef> ASTs;
- SMTExprRef Constraint = Solver->newExprRef(I++->second);
+ SMTExprRef Constraint = I++->second;
while (I != IE) {
- Constraint = Solver->mkAnd(Constraint, Solver->newExprRef(I++->second));
+ Constraint = Solver->mkAnd(Constraint, I++->second);
}
Solver->addConstraint(Constraint);
// Generate and check a Z3 model, using the given constraint.
ConditionTruthVal checkModel(ProgramStateRef State, SymbolRef Sym,
const SMTExprRef &Exp) const {
- ProgramStateRef NewState = State->add<ConstraintSMT>(
- std::make_pair(Sym, static_cast<const SMTExprTy &>(*Exp)));
+ ProgramStateRef NewState =
+ State->add<ConstraintSMT>(std::make_pair(Sym, Exp));
llvm::FoldingSetNodeID ID;
NewState->get<ConstraintSMT>().Profile(ID);
Z3_dec_ref(Context.Context, reinterpret_cast<Z3_ast>(Sort));
}
+ void Profile(llvm::FoldingSetNodeID &ID) const {
+ ID.AddInteger(
+ Z3_get_ast_id(Context.Context, reinterpret_cast<Z3_ast>(Sort)));
+ }
+
bool isBitvectorSortImpl() const override {
return (Z3_get_sort_kind(Context.Context, Sort) == Z3_BV_SORT);
}
}
void Profile(llvm::FoldingSetNodeID &ID) const override {
- ID.AddInteger(Z3_get_ast_hash(Context.Context, AST));
+ ID.AddInteger(Z3_get_ast_id(Context.Context, AST));
}
/// Comparison of AST equality, not model equivalence.
llvm::APFloat::semanticsSizeInBits(RHS));
}
-} // end anonymous namespace
-
-typedef llvm::ImmutableSet<std::pair<SymbolRef, Z3Expr>> ConstraintZ3Ty;
-REGISTER_TRAIT_WITH_PROGRAMSTATE(ConstraintZ3, ConstraintZ3Ty)
-
-namespace {
-
class Z3Solver : public SMTSolver {
friend class Z3ConstraintManager;
Z3_solver Solver;
+ // Cache Sorts
+ std::set<Z3Sort> CachedSorts;
+
+ // Cache Exprs
+ std::set<Z3Expr> CachedExprs;
+
public:
Z3Solver() : Solver(Z3_mk_simple_solver(Context.Context)) {
Z3_solver_inc_ref(Context.Context, Solver);
Z3_solver_assert(Context.Context, Solver, toZ3Expr(*Exp).AST);
}
+ // Given an SMTSort, adds/retrives it from the cache and returns
+ // an SMTSortRef to the SMTSort in the cache
+ SMTSortRef newSortRef(const SMTSort &Sort) {
+ auto It = CachedSorts.insert(toZ3Sort(Sort));
+ return &(*It.first);
+ }
+
+ // Given an SMTExpr, adds/retrives it from the cache and returns
+ // an SMTExprRef to the SMTExpr in the cache
+ SMTExprRef newExprRef(const SMTExpr &Exp) {
+ auto It = CachedExprs.insert(toZ3Expr(Exp));
+ return &(*It.first);
+ }
+
SMTSortRef getBoolSort() override {
- return std::make_shared<Z3Sort>(Context, Z3_mk_bool_sort(Context.Context));
+ return newSortRef(Z3Sort(Context, Z3_mk_bool_sort(Context.Context)));
}
SMTSortRef getBitvectorSort(unsigned BitWidth) override {
- return std::make_shared<Z3Sort>(Context,
- Z3_mk_bv_sort(Context.Context, BitWidth));
+ return newSortRef(
+ Z3Sort(Context, Z3_mk_bv_sort(Context.Context, BitWidth)));
}
SMTSortRef getSort(const SMTExprRef &Exp) override {
- return std::make_shared<Z3Sort>(
- Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST));
+ return newSortRef(
+ Z3Sort(Context, Z3_get_sort(Context.Context, toZ3Expr(*Exp).AST)));
}
SMTSortRef getFloat16Sort() override {
- return std::make_shared<Z3Sort>(Context,
- Z3_mk_fpa_sort_16(Context.Context));
+ return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_16(Context.Context)));
}
SMTSortRef getFloat32Sort() override {
- return std::make_shared<Z3Sort>(Context,
- Z3_mk_fpa_sort_32(Context.Context));
+ return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_32(Context.Context)));
}
SMTSortRef getFloat64Sort() override {
- return std::make_shared<Z3Sort>(Context,
- Z3_mk_fpa_sort_64(Context.Context));
+ return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_64(Context.Context)));
}
SMTSortRef getFloat128Sort() override {
- return std::make_shared<Z3Sort>(Context,
- Z3_mk_fpa_sort_128(Context.Context));
- }
-
- SMTExprRef newExprRef(const SMTExpr &E) const override {
- return std::make_shared<Z3Expr>(toZ3Expr(E));
+ return newSortRef(Z3Sort(Context, Z3_mk_fpa_sort_128(Context.Context)));
}
SMTExprRef mkBVNeg(const SMTExprRef &Exp) override {
}
}; // end class Z3Solver
-class Z3ConstraintManager : public SMTConstraintManager<ConstraintZ3, Z3Expr> {
+class Z3ConstraintManager : public SMTConstraintManager {
SMTSolverRef Solver = CreateZ3Solver();
public: