mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[SMTChecker]: Update CVC4 to cvc5
This commit is contained in:
parent
facc38097d
commit
43f7a0f1cb
@ -122,15 +122,15 @@ elseif (${Z3_FOUND})
|
|||||||
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
|
message("Z3 SMT solver found. This enables optional SMT checking with Z3.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(CVC4 QUIET)
|
find_package(CVC5 QUIET)
|
||||||
if (${CVC4_FOUND})
|
if (${CVC5_FOUND})
|
||||||
add_definitions(-DHAVE_CVC4)
|
add_definitions(-DHAVE_CVC5)
|
||||||
message("CVC4 SMT solver found. This enables optional SMT checking with CVC4.")
|
message("cvc5 SMT solver found. This enables optional SMT checking with cvc5.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT (${Z3_FOUND} OR ${CVC4_FOUND}))
|
if (NOT (${Z3_FOUND} OR ${CVC5_FOUND}))
|
||||||
message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\
|
message("No SMT solver found (or it has been forcefully disabled). Optional SMT checking will not be available.\
|
||||||
\nPlease install Z3 or CVC4 or remove the option disabling them (USE_Z3, USE_CVC4).")
|
\nPlease install Z3 or cvc5 or remove the option disabling them (USE_Z3, USE_CVC5).")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(libsolutil)
|
add_subdirectory(libsolutil)
|
||||||
|
@ -266,7 +266,7 @@ option(USE_Z3 "Allow compiling with Z3 SMT solver integration" ON)
|
|||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF)
|
option(USE_Z3_DLOPEN "Dynamically load the Z3 SMT solver instead of linking against it." OFF)
|
||||||
endif()
|
endif()
|
||||||
option(USE_CVC4 "Allow compiling with CVC4 SMT solver integration" ON)
|
option(USE_CVC5 "Allow compiling with CVC5 SMT solver integration" ON)
|
||||||
|
|
||||||
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang"))
|
||||||
option(USE_LD_GOLD "Use GNU gold linker" ON)
|
option(USE_LD_GOLD "Use GNU gold linker" ON)
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
if (USE_CVC4)
|
|
||||||
find_path(CVC4_INCLUDE_DIR cvc4/cvc4.h)
|
|
||||||
find_library(CVC4_LIBRARY NAMES cvc4)
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(CVC4 DEFAULT_MSG CVC4_LIBRARY CVC4_INCLUDE_DIR)
|
|
||||||
if(CVC4_FOUND)
|
|
||||||
# CVC4 may depend on either CLN or GMP.
|
|
||||||
# We can assume that the one it requires is present on the system,
|
|
||||||
# so we quietly try to find both and link against them, if they are
|
|
||||||
# present.
|
|
||||||
find_package(CLN QUIET)
|
|
||||||
find_package(GMP QUIET)
|
|
||||||
|
|
||||||
set(CVC4_LIBRARIES ${CVC4_LIBRARY})
|
|
||||||
|
|
||||||
if (CLN_FOUND)
|
|
||||||
set(CVC4_LIBRARIES ${CVC4_LIBRARIES} CLN::CLN)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (GMP_FOUND)
|
|
||||||
set(CVC4_LIBRARIES ${CVC4_LIBRARIES} GMP::GMP)
|
|
||||||
endif ()
|
|
||||||
|
|
||||||
if (NOT TARGET CVC4::CVC4)
|
|
||||||
add_library(CVC4::CVC4 UNKNOWN IMPORTED)
|
|
||||||
set_property(TARGET CVC4::CVC4 PROPERTY IMPORTED_LOCATION ${CVC4_LIBRARY})
|
|
||||||
set_property(TARGET CVC4::CVC4 PROPERTY INTERFACE_LINK_LIBRARIES ${CVC4_LIBRARIES})
|
|
||||||
set_property(TARGET CVC4::CVC4 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CVC4_INCLUDE_DIR})
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
set(CVC4_FOUND FALSE)
|
|
||||||
endif()
|
|
33
cmake/FindCVC5.cmake
Normal file
33
cmake/FindCVC5.cmake
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
if (USE_CVC5)
|
||||||
|
find_path(CVC5_INCLUDE_DIR cvc5/cvc5.h)
|
||||||
|
find_library(CVC5_LIBRARY NAMES cvc5)
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(CVC5 DEFAULT_MSG CVC5_LIBRARY CVC5_INCLUDE_DIR)
|
||||||
|
if(CVC5_FOUND)
|
||||||
|
# CVC5 may depend on either CLN or GMP.
|
||||||
|
# We can assume that the one it requires is present on the system,
|
||||||
|
# so we quietly try to find both and link against them, if they are
|
||||||
|
# present.
|
||||||
|
find_package(CLN QUIET)
|
||||||
|
find_package(GMP QUIET)
|
||||||
|
|
||||||
|
set(CVC5_LIBRARIES ${CVC5_LIBRARY})
|
||||||
|
|
||||||
|
if (CLN_FOUND)
|
||||||
|
set(CVC5_LIBRARIES ${CVC5_LIBRARIES} CLN::CLN)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (GMP_FOUND)
|
||||||
|
set(CVC5_LIBRARIES ${CVC5_LIBRARIES} GMP::GMP)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (NOT TARGET CVC5::CVC5)
|
||||||
|
add_library(CVC5::CVC5 UNKNOWN IMPORTED)
|
||||||
|
set_property(TARGET CVC5::CVC5 PROPERTY IMPORTED_LOCATION ${CVC5_LIBRARY})
|
||||||
|
set_property(TARGET CVC5::CVC5 PROPERTY INTERFACE_LINK_LIBRARIES ${CVC5_LIBRARIES})
|
||||||
|
set_property(TARGET CVC5::CVC5 PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${CVC5_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
set(CVC5_FOUND FALSE)
|
||||||
|
endif()
|
@ -328,10 +328,10 @@ The following are dependencies for all builds of Solidity:
|
|||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
| `z3`_ (version 4.8.16+, Optional) | For use with SMT checker. |
|
| `z3`_ (version 4.8.16+, Optional) | For use with SMT checker. |
|
||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
| `cvc4`_ (Optional) | For use with SMT checker. |
|
| `cvc5`_ (Optional) | For use with SMT checker. |
|
||||||
+-----------------------------------+-------------------------------------------------------+
|
+-----------------------------------+-------------------------------------------------------+
|
||||||
|
|
||||||
.. _cvc4: https://cvc4.cs.stanford.edu/web/
|
.. _cvc5: https://cvc5.github.io/downloads.html
|
||||||
.. _Git: https://git-scm.com/download
|
.. _Git: https://git-scm.com/download
|
||||||
.. _Boost: https://www.boost.org
|
.. _Boost: https://www.boost.org
|
||||||
.. _CMake: https://cmake.org/download/
|
.. _CMake: https://cmake.org/download/
|
||||||
|
@ -821,10 +821,10 @@ which is primarily an SMT solver and makes `Spacer
|
|||||||
<https://github.com/uuverifiers/eldarica>`_ which does both.
|
<https://github.com/uuverifiers/eldarica>`_ which does both.
|
||||||
|
|
||||||
The user can choose which solvers should be used, if available, via the CLI
|
The user can choose which solvers should be used, if available, via the CLI
|
||||||
option ``--model-checker-solvers {all,cvc4,eld,smtlib2,z3}`` or the JSON option
|
option ``--model-checker-solvers {all,cvc5,eld,smtlib2,z3}`` or the JSON option
|
||||||
``settings.modelChecker.solvers=[smtlib2,z3]``, where:
|
``settings.modelChecker.solvers=[smtlib2,z3]``, where:
|
||||||
|
|
||||||
- ``cvc4`` is only available if the ``solc`` binary is compiled with it. Only BMC uses ``cvc4``.
|
- ``cvc5`` is only available if the ``solc`` binary is compiled with it. Only BMC uses ``cvc5``.
|
||||||
- ``eld`` is used via its binary which must be installed in the system. Only CHC uses ``eld``, and only if ``z3`` is not enabled.
|
- ``eld`` is used via its binary which must be installed in the system. Only CHC uses ``eld``, and only if ``z3`` is not enabled.
|
||||||
- ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 <http://smtlib.cs.uiowa.edu/>`_ format.
|
- ``smtlib2`` outputs SMT/Horn queries in the `smtlib2 <http://smtlib.cs.uiowa.edu/>`_ format.
|
||||||
These can be used together with the compiler's `callback mechanism <https://github.com/ethereum/solc-js>`_ so that
|
These can be used together with the compiler's `callback mechanism <https://github.com/ethereum/solc-js>`_ so that
|
||||||
@ -848,7 +848,7 @@ concerned about this option. More advanced users might apply this option to try
|
|||||||
alternative solvers on more complex problems.
|
alternative solvers on more complex problems.
|
||||||
|
|
||||||
Please note that certain combinations of chosen engine and solver will lead to
|
Please note that certain combinations of chosen engine and solver will lead to
|
||||||
the SMTChecker doing nothing, for example choosing CHC and ``cvc4``.
|
the SMTChecker doing nothing, for example choosing CHC and ``cvc5``.
|
||||||
|
|
||||||
*******************************
|
*******************************
|
||||||
Abstraction and False Positives
|
Abstraction and False Positives
|
||||||
|
@ -457,7 +457,7 @@ Input Description
|
|||||||
"showUnsupported": true,
|
"showUnsupported": true,
|
||||||
// Choose which solvers should be used, if available.
|
// Choose which solvers should be used, if available.
|
||||||
// See the Formal Verification section for the solvers description.
|
// See the Formal Verification section for the solvers description.
|
||||||
"solvers": ["cvc4", "smtlib2", "z3"],
|
"solvers": ["cvc5", "smtlib2", "z3"],
|
||||||
// Choose which targets should be checked: constantCondition,
|
// Choose which targets should be checked: constantCondition,
|
||||||
// underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds.
|
// underflow, overflow, divByZero, balance, assert, popEmptyArray, outOfBounds.
|
||||||
// If the option is not given all targets are checked by default,
|
// If the option is not given all targets are checked by default,
|
||||||
|
@ -18,10 +18,10 @@ else()
|
|||||||
set(z3_SRCS)
|
set(z3_SRCS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (${CVC4_FOUND})
|
if (${CVC5_FOUND})
|
||||||
set(cvc4_SRCS CVC4Interface.cpp CVC4Interface.h)
|
set(cvc5_SRCS CVC4Interface.cpp CVC4Interface.h)
|
||||||
else()
|
else()
|
||||||
set(cvc4_SRCS)
|
set(cvc5_SRCS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (${USE_Z3_DLOPEN})
|
if (${USE_Z3_DLOPEN})
|
||||||
@ -36,7 +36,7 @@ if (${USE_Z3_DLOPEN})
|
|||||||
set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h)
|
set(z3_SRCS ${z3_SRCS} ${Z3_WRAPPER} Z3Loader.cpp Z3Loader.h)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(smtutil ${sources} ${z3_SRCS} ${cvc4_SRCS})
|
add_library(smtutil ${sources} ${z3_SRCS} ${cvc5_SRCS})
|
||||||
target_link_libraries(smtutil PUBLIC solutil Boost::boost)
|
target_link_libraries(smtutil PUBLIC solutil Boost::boost)
|
||||||
|
|
||||||
if (${USE_Z3_DLOPEN})
|
if (${USE_Z3_DLOPEN})
|
||||||
@ -46,6 +46,6 @@ elseif (${Z3_FOUND})
|
|||||||
target_link_libraries(smtutil PUBLIC z3::libz3)
|
target_link_libraries(smtutil PUBLIC z3::libz3)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (${CVC4_FOUND})
|
if (${CVC5_FOUND})
|
||||||
target_link_libraries(smtutil PUBLIC CVC4::CVC4)
|
target_link_libraries(smtutil PUBLIC CVC5::CVC5)
|
||||||
endif()
|
endif()
|
||||||
|
@ -18,102 +18,82 @@
|
|||||||
|
|
||||||
#include <libsmtutil/CVC4Interface.h>
|
#include <libsmtutil/CVC4Interface.h>
|
||||||
|
|
||||||
|
#include <libsolutil/CommonData.h>
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
#include <libsolutil/Exceptions.h>
|
#include <libsolutil/Exceptions.h>
|
||||||
|
|
||||||
#include <cvc4/util/bitvector.h>
|
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace solidity;
|
using namespace solidity;
|
||||||
using namespace solidity::util;
|
using namespace solidity::util;
|
||||||
using namespace solidity::smtutil;
|
using namespace solidity::smtutil;
|
||||||
|
|
||||||
CVC4Interface::CVC4Interface(optional<unsigned> _queryTimeout):
|
CVC5Interface::CVC5Interface(optional<unsigned> _queryTimeout):
|
||||||
SolverInterface(_queryTimeout),
|
SolverInterface(_queryTimeout)
|
||||||
m_solver(&m_context)
|
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVC4Interface::reset()
|
void CVC5Interface::reset()
|
||||||
{
|
{
|
||||||
m_variables.clear();
|
m_variables.clear();
|
||||||
m_solver.reset();
|
m_solver.resetAssertions();
|
||||||
m_solver.setOption("produce-models", true);
|
m_solver.setOption("produce-models", "true");
|
||||||
if (m_queryTimeout)
|
if (m_queryTimeout)
|
||||||
m_solver.setTimeLimit(*m_queryTimeout);
|
m_solver.setOption("tlimit-per", std::to_string(*m_queryTimeout));
|
||||||
else
|
else
|
||||||
m_solver.setResourceLimit(resourceLimit);
|
m_solver.setOption("rlimit", std::to_string(resourceLimit));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVC4Interface::push()
|
void CVC5Interface::push()
|
||||||
{
|
{
|
||||||
m_solver.push();
|
m_solver.push();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVC4Interface::pop()
|
void CVC5Interface::pop()
|
||||||
{
|
{
|
||||||
m_solver.pop();
|
m_solver.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVC4Interface::declareVariable(string const& _name, SortPointer const& _sort)
|
void CVC5Interface::declareVariable(string const& _name, SortPointer const& _sort)
|
||||||
{
|
{
|
||||||
smtAssert(_sort, "");
|
smtAssert(_sort, "");
|
||||||
m_variables[_name] = m_context.mkVar(_name.c_str(), cvc4Sort(*_sort));
|
m_variables[_name] = m_solver.mkConst(CVC5Sort(*_sort), _name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CVC4Interface::addAssertion(Expression const& _expr)
|
void CVC5Interface::addAssertion(Expression const& _expr)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_solver.assertFormula(toCVC4Expr(_expr));
|
m_solver.assertFormula(toCVC5Expr(_expr));
|
||||||
}
|
}
|
||||||
catch (CVC4::TypeCheckingException const& _e)
|
catch (cvc5::CVC5ApiException const& _e)
|
||||||
{
|
|
||||||
smtAssert(false, _e.what());
|
|
||||||
}
|
|
||||||
catch (CVC4::LogicException const& _e)
|
|
||||||
{
|
|
||||||
smtAssert(false, _e.what());
|
|
||||||
}
|
|
||||||
catch (CVC4::UnsafeInterruptException const& _e)
|
|
||||||
{
|
|
||||||
smtAssert(false, _e.what());
|
|
||||||
}
|
|
||||||
catch (CVC4::Exception const& _e)
|
|
||||||
{
|
{
|
||||||
smtAssert(false, _e.what());
|
smtAssert(false, _e.what());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const& _expressionsToEvaluate)
|
pair<CheckResult, vector<string>> CVC5Interface::check(vector<Expression> const& _expressionsToEvaluate)
|
||||||
{
|
{
|
||||||
CheckResult result;
|
CheckResult result;
|
||||||
vector<string> values;
|
vector<string> values;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
switch (m_solver.checkSat().isSat())
|
cvc5::Result res = m_solver.checkSat();
|
||||||
{
|
if (res.isSat())
|
||||||
case CVC4::Result::SAT:
|
|
||||||
result = CheckResult::SATISFIABLE;
|
result = CheckResult::SATISFIABLE;
|
||||||
break;
|
else if (res.isUnsat())
|
||||||
case CVC4::Result::UNSAT:
|
|
||||||
result = CheckResult::UNSATISFIABLE;
|
result = CheckResult::UNSATISFIABLE;
|
||||||
break;
|
else if (res.isUnknown())
|
||||||
case CVC4::Result::SAT_UNKNOWN:
|
|
||||||
result = CheckResult::UNKNOWN;
|
result = CheckResult::UNKNOWN;
|
||||||
break;
|
else
|
||||||
default:
|
|
||||||
smtAssert(false, "");
|
smtAssert(false, "");
|
||||||
}
|
|
||||||
|
|
||||||
if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty())
|
if (result == CheckResult::SATISFIABLE && !_expressionsToEvaluate.empty())
|
||||||
{
|
{
|
||||||
for (Expression const& e: _expressionsToEvaluate)
|
for (Expression const& e: _expressionsToEvaluate)
|
||||||
values.push_back(toString(m_solver.getValue(toCVC4Expr(e))));
|
values.push_back(toString(m_solver.getValue(toCVC5Expr(e))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (CVC4::Exception const&)
|
catch (cvc5::CVC5ApiException const&)
|
||||||
{
|
{
|
||||||
result = CheckResult::ERROR;
|
result = CheckResult::ERROR;
|
||||||
values.clear();
|
values.clear();
|
||||||
@ -122,41 +102,41 @@ pair<CheckResult, vector<string>> CVC4Interface::check(vector<Expression> const&
|
|||||||
return make_pair(result, values);
|
return make_pair(result, values);
|
||||||
}
|
}
|
||||||
|
|
||||||
CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
|
cvc5::Term CVC5Interface::toCVC5Expr(Expression const& _expr)
|
||||||
{
|
{
|
||||||
// Variable
|
// Variable
|
||||||
if (_expr.arguments.empty() && m_variables.count(_expr.name))
|
if (_expr.arguments.empty() && m_variables.count(_expr.name))
|
||||||
return m_variables.at(_expr.name);
|
return m_variables.at(_expr.name);
|
||||||
|
|
||||||
vector<CVC4::Expr> arguments;
|
vector<cvc5::Term> arguments;
|
||||||
for (auto const& arg: _expr.arguments)
|
for (auto const& arg: _expr.arguments)
|
||||||
arguments.push_back(toCVC4Expr(arg));
|
arguments.push_back(toCVC5Expr(arg));
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
string const& n = _expr.name;
|
string const& n = _expr.name;
|
||||||
// Function application
|
// Function application
|
||||||
if (!arguments.empty() && m_variables.count(_expr.name))
|
if (!arguments.empty() && m_variables.count(_expr.name))
|
||||||
return m_context.mkExpr(CVC4::kind::APPLY_UF, m_variables.at(n), arguments);
|
return m_solver.mkTerm(cvc5::Kind::APPLY_UF, vector<cvc5::Term>{m_variables.at(n)} + arguments);
|
||||||
// Literal
|
// Literal
|
||||||
else if (arguments.empty())
|
else if (arguments.empty())
|
||||||
{
|
{
|
||||||
if (n == "true")
|
if (n == "true")
|
||||||
return m_context.mkConst(true);
|
return m_solver.mkTrue();
|
||||||
else if (n == "false")
|
else if (n == "false")
|
||||||
return m_context.mkConst(false);
|
return m_solver.mkFalse();
|
||||||
else if (auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort))
|
else if (auto sortSort = dynamic_pointer_cast<SortSort>(_expr.sort))
|
||||||
return m_context.mkVar(n, cvc4Sort(*sortSort->inner));
|
return m_solver.mkVar(CVC5Sort(*sortSort->inner), n);
|
||||||
else
|
else
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return m_context.mkConst(CVC4::Rational(n));
|
return m_solver.mkInteger(n);
|
||||||
}
|
}
|
||||||
catch (CVC4::TypeCheckingException const& _e)
|
catch (cvc5::CVC5ApiRecoverableException const& _e)
|
||||||
{
|
{
|
||||||
smtAssert(false, _e.what());
|
smtAssert(false, _e.what());
|
||||||
}
|
}
|
||||||
catch (CVC4::Exception const& _e)
|
catch (cvc5::CVC5ApiException const& _e)
|
||||||
{
|
{
|
||||||
smtAssert(false, _e.what());
|
smtAssert(false, _e.what());
|
||||||
}
|
}
|
||||||
@ -164,127 +144,127 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
|
|||||||
|
|
||||||
smtAssert(_expr.hasCorrectArity(), "");
|
smtAssert(_expr.hasCorrectArity(), "");
|
||||||
if (n == "ite")
|
if (n == "ite")
|
||||||
return arguments[0].iteExpr(arguments[1], arguments[2]);
|
return arguments[0].iteTerm(arguments[1], arguments[2]);
|
||||||
else if (n == "not")
|
else if (n == "not")
|
||||||
return arguments[0].notExpr();
|
return arguments[0].notTerm();
|
||||||
else if (n == "and")
|
else if (n == "and")
|
||||||
return arguments[0].andExpr(arguments[1]);
|
return arguments[0].andTerm(arguments[1]);
|
||||||
else if (n == "or")
|
else if (n == "or")
|
||||||
return arguments[0].orExpr(arguments[1]);
|
return arguments[0].orTerm(arguments[1]);
|
||||||
else if (n == "=>")
|
else if (n == "=>")
|
||||||
return m_context.mkExpr(CVC4::kind::IMPLIES, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::IMPLIES, {arguments[0], arguments[1]});
|
||||||
else if (n == "=")
|
else if (n == "=")
|
||||||
return m_context.mkExpr(CVC4::kind::EQUAL, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::EQUAL, {arguments[0], arguments[1]});
|
||||||
else if (n == "<")
|
else if (n == "<")
|
||||||
return m_context.mkExpr(CVC4::kind::LT, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::LT, {arguments[0], arguments[1]});
|
||||||
else if (n == "<=")
|
else if (n == "<=")
|
||||||
return m_context.mkExpr(CVC4::kind::LEQ, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::LEQ, {arguments[0], arguments[1]});
|
||||||
else if (n == ">")
|
else if (n == ">")
|
||||||
return m_context.mkExpr(CVC4::kind::GT, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::GT, {arguments[0], arguments[1]});
|
||||||
else if (n == ">=")
|
else if (n == ">=")
|
||||||
return m_context.mkExpr(CVC4::kind::GEQ, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::GEQ, {arguments[0], arguments[1]});
|
||||||
else if (n == "+")
|
else if (n == "+")
|
||||||
return m_context.mkExpr(CVC4::kind::PLUS, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::ADD, {arguments[0], arguments[1]});
|
||||||
else if (n == "-")
|
else if (n == "-")
|
||||||
return m_context.mkExpr(CVC4::kind::MINUS, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::SUB, {arguments[0], arguments[1]});
|
||||||
else if (n == "*")
|
else if (n == "*")
|
||||||
return m_context.mkExpr(CVC4::kind::MULT, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::MULT, {arguments[0], arguments[1]});
|
||||||
else if (n == "div")
|
else if (n == "div")
|
||||||
return m_context.mkExpr(CVC4::kind::INTS_DIVISION_TOTAL, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::INTS_DIVISION, {arguments[0], arguments[1]});
|
||||||
else if (n == "mod")
|
else if (n == "mod")
|
||||||
return m_context.mkExpr(CVC4::kind::INTS_MODULUS, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::INTS_MODULUS, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvnot")
|
else if (n == "bvnot")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_NOT, arguments[0]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_NOT, {arguments[0]});
|
||||||
else if (n == "bvand")
|
else if (n == "bvand")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_AND, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_AND, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvor")
|
else if (n == "bvor")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_OR, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_OR, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvxor")
|
else if (n == "bvxor")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_XOR, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_XOR, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvshl")
|
else if (n == "bvshl")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_SHL, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_SHL, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvlshr")
|
else if (n == "bvlshr")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_LSHR, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_LSHR, {arguments[0], arguments[1]});
|
||||||
else if (n == "bvashr")
|
else if (n == "bvashr")
|
||||||
return m_context.mkExpr(CVC4::kind::BITVECTOR_ASHR, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::BITVECTOR_ASHR, {arguments[0], arguments[1]});
|
||||||
else if (n == "int2bv")
|
else if (n == "int2bv")
|
||||||
{
|
{
|
||||||
size_t size = std::stoul(_expr.arguments[1].name);
|
size_t size = std::stoul(_expr.arguments[1].name);
|
||||||
auto i2bvOp = m_context.mkConst(CVC4::IntToBitVector(static_cast<unsigned>(size)));
|
auto i2bvOp = m_solver.mkOp(cvc5::Kind::INT_TO_BITVECTOR, {static_cast<unsigned>(size)});
|
||||||
// CVC4 treats all BVs as unsigned, so we need to manually apply 2's complement if needed.
|
// CVC5 treats all BVs as unsigned, so we need to manually apply 2's complement if needed.
|
||||||
return m_context.mkExpr(
|
return m_solver.mkTerm(
|
||||||
CVC4::kind::ITE,
|
cvc5::Kind::ITE,
|
||||||
m_context.mkExpr(CVC4::kind::GEQ, arguments[0], m_context.mkConst(CVC4::Rational(0))),
|
{
|
||||||
m_context.mkExpr(CVC4::kind::INT_TO_BITVECTOR, i2bvOp, arguments[0]),
|
m_solver.mkTerm(cvc5::Kind::GEQ, {arguments[0], m_solver.mkInteger(0)}),
|
||||||
m_context.mkExpr(
|
m_solver.mkTerm(i2bvOp, {arguments[0]}),
|
||||||
CVC4::kind::BITVECTOR_NEG,
|
m_solver.mkTerm(
|
||||||
m_context.mkExpr(CVC4::kind::INT_TO_BITVECTOR, i2bvOp, m_context.mkExpr(CVC4::kind::UMINUS, arguments[0]))
|
cvc5::Kind::BITVECTOR_NEG,
|
||||||
)
|
{m_solver.mkTerm(i2bvOp, {m_solver.mkTerm(cvc5::Kind::NEG, {arguments[0]})})}
|
||||||
|
)
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (n == "bv2int")
|
else if (n == "bv2int")
|
||||||
{
|
{
|
||||||
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort);
|
auto intSort = dynamic_pointer_cast<IntSort>(_expr.sort);
|
||||||
smtAssert(intSort, "");
|
smtAssert(intSort, "");
|
||||||
auto nat = m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, arguments[0]);
|
auto nat = m_solver.mkTerm(cvc5::Kind::BITVECTOR_TO_NAT, {arguments[0]});
|
||||||
if (!intSort->isSigned)
|
if (!intSort->isSigned)
|
||||||
return nat;
|
return nat;
|
||||||
|
|
||||||
auto type = arguments[0].getType();
|
auto type = arguments[0].getSort();
|
||||||
smtAssert(type.isBitVector(), "");
|
smtAssert(type.isBitVector(), "");
|
||||||
auto size = CVC4::BitVectorType(type).getSize();
|
auto size = type.getBitVectorSize();
|
||||||
// CVC4 treats all BVs as unsigned, so we need to manually apply 2's complement if needed.
|
// CVC5 treats all BVs as unsigned, so we need to manually apply 2's complement if needed.
|
||||||
auto extractOp = m_context.mkConst(CVC4::BitVectorExtract(size - 1, size - 1));
|
auto extractOp = m_solver.mkOp(cvc5::Kind::BITVECTOR_EXTRACT, {size - 1, size - 1});
|
||||||
return m_context.mkExpr(CVC4::kind::ITE,
|
return m_solver.mkTerm(
|
||||||
m_context.mkExpr(
|
cvc5::Kind::ITE,
|
||||||
CVC4::kind::EQUAL,
|
{
|
||||||
m_context.mkExpr(CVC4::kind::BITVECTOR_EXTRACT, extractOp, arguments[0]),
|
m_solver.mkTerm(
|
||||||
m_context.mkConst(CVC4::BitVector(1, uint64_t{0}))
|
cvc5::Kind::EQUAL,
|
||||||
),
|
{m_solver.mkTerm(extractOp, {arguments[0]}), m_solver.mkBitVector(1, uint64_t{0})}
|
||||||
nat,
|
),
|
||||||
m_context.mkExpr(
|
nat,
|
||||||
CVC4::kind::UMINUS,
|
m_solver.mkTerm(
|
||||||
m_context.mkExpr(CVC4::kind::BITVECTOR_TO_NAT, m_context.mkExpr(CVC4::kind::BITVECTOR_NEG, arguments[0]))
|
cvc5::Kind::NEG,
|
||||||
)
|
{m_solver.mkTerm(cvc5::Kind::BITVECTOR_TO_NAT, {m_solver.mkTerm(cvc5::Kind::BITVECTOR_NEG, {arguments[0]})})}
|
||||||
|
)
|
||||||
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else if (n == "select")
|
else if (n == "select")
|
||||||
return m_context.mkExpr(CVC4::kind::SELECT, arguments[0], arguments[1]);
|
return m_solver.mkTerm(cvc5::Kind::SELECT, {arguments[0], arguments[1]});
|
||||||
else if (n == "store")
|
else if (n == "store")
|
||||||
return m_context.mkExpr(CVC4::kind::STORE, arguments[0], arguments[1], arguments[2]);
|
return m_solver.mkTerm(cvc5::Kind::STORE, {arguments[0], arguments[1], arguments[2]});
|
||||||
else if (n == "const_array")
|
else if (n == "const_array")
|
||||||
{
|
{
|
||||||
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
|
shared_ptr<SortSort> sortSort = std::dynamic_pointer_cast<SortSort>(_expr.arguments[0].sort);
|
||||||
smtAssert(sortSort, "");
|
smtAssert(sortSort, "");
|
||||||
return m_context.mkConst(CVC4::ArrayStoreAll(cvc4Sort(*sortSort->inner), arguments[1]));
|
return m_solver.mkConstArray(CVC5Sort(*sortSort->inner), arguments[1]);
|
||||||
}
|
}
|
||||||
else if (n == "tuple_get")
|
else if (n == "tuple_get")
|
||||||
{
|
{
|
||||||
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.arguments[0].sort);
|
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.arguments[0].sort);
|
||||||
smtAssert(tupleSort, "");
|
smtAssert(tupleSort, "");
|
||||||
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
|
auto tt = m_solver.mkTupleSort(CVC5Sort(tupleSort->components));
|
||||||
CVC4::Datatype const& dt = tt.getDatatype();
|
cvc5::Datatype const& dt = tt.getDatatype();
|
||||||
size_t index = std::stoul(_expr.arguments[1].name);
|
size_t index = std::stoul(_expr.arguments[1].name);
|
||||||
CVC4::Expr s = dt[0][index].getSelector();
|
cvc5::DatatypeSelector s = dt[0][index];
|
||||||
return m_context.mkExpr(CVC4::kind::APPLY_SELECTOR, s, arguments[0]);
|
return m_solver.mkTerm(cvc5::Kind::APPLY_SELECTOR, {s.getTerm(), arguments[0]});
|
||||||
}
|
}
|
||||||
else if (n == "tuple_constructor")
|
else if (n == "tuple_constructor")
|
||||||
{
|
{
|
||||||
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.sort);
|
shared_ptr<TupleSort> tupleSort = std::dynamic_pointer_cast<TupleSort>(_expr.sort);
|
||||||
smtAssert(tupleSort, "");
|
smtAssert(tupleSort, "");
|
||||||
CVC4::DatatypeType tt = m_context.mkTupleType(cvc4Sort(tupleSort->components));
|
auto tt = m_solver.mkTupleSort(CVC5Sort(tupleSort->components));
|
||||||
CVC4::Datatype const& dt = tt.getDatatype();
|
cvc5::Datatype const& dt = tt.getDatatype();
|
||||||
CVC4::Expr c = dt[0].getConstructor();
|
cvc5::DatatypeConstructor c = dt[0];
|
||||||
return m_context.mkExpr(CVC4::kind::APPLY_CONSTRUCTOR, c, arguments);
|
return m_solver.mkTerm(cvc5::Kind::APPLY_CONSTRUCTOR, vector<cvc5::Term>{c.getTerm()} + arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
smtAssert(false);
|
smtAssert(false);
|
||||||
}
|
}
|
||||||
catch (CVC4::TypeCheckingException const& _e)
|
catch (cvc5::CVC5ApiException const& _e)
|
||||||
{
|
|
||||||
smtAssert(false, _e.what());
|
|
||||||
}
|
|
||||||
catch (CVC4::Exception const& _e)
|
|
||||||
{
|
{
|
||||||
smtAssert(false, _e.what());
|
smtAssert(false, _e.what());
|
||||||
}
|
}
|
||||||
@ -295,43 +275,45 @@ CVC4::Expr CVC4Interface::toCVC4Expr(Expression const& _expr)
|
|||||||
util::unreachable();
|
util::unreachable();
|
||||||
}
|
}
|
||||||
|
|
||||||
CVC4::Type CVC4Interface::cvc4Sort(Sort const& _sort)
|
cvc5::Sort CVC5Interface::CVC5Sort(Sort const& _sort)
|
||||||
{
|
{
|
||||||
switch (_sort.kind)
|
switch (_sort.kind)
|
||||||
{
|
{
|
||||||
case Kind::Bool:
|
case Kind::Bool:
|
||||||
return m_context.booleanType();
|
return m_solver.getBooleanSort();
|
||||||
case Kind::Int:
|
case Kind::Int:
|
||||||
return m_context.integerType();
|
return m_solver.getIntegerSort();
|
||||||
case Kind::BitVector:
|
case Kind::BitVector:
|
||||||
return m_context.mkBitVectorType(dynamic_cast<BitVectorSort const&>(_sort).size);
|
return m_solver.mkBitVectorSort(dynamic_cast<BitVectorSort const&>(_sort).size);
|
||||||
case Kind::Function:
|
case Kind::Function:
|
||||||
{
|
{
|
||||||
FunctionSort const& fSort = dynamic_cast<FunctionSort const&>(_sort);
|
FunctionSort const& fSort = dynamic_cast<FunctionSort const&>(_sort);
|
||||||
return m_context.mkFunctionType(cvc4Sort(fSort.domain), cvc4Sort(*fSort.codomain));
|
if (fSort.domain.empty()) // function sort in cvc5 must have nonempty domain
|
||||||
|
return CVC5Sort(*fSort.codomain);
|
||||||
|
return m_solver.mkFunctionSort(CVC5Sort(fSort.domain), CVC5Sort(*fSort.codomain));
|
||||||
}
|
}
|
||||||
case Kind::Array:
|
case Kind::Array:
|
||||||
{
|
{
|
||||||
auto const& arraySort = dynamic_cast<ArraySort const&>(_sort);
|
auto const& arraySort = dynamic_cast<ArraySort const&>(_sort);
|
||||||
return m_context.mkArrayType(cvc4Sort(*arraySort.domain), cvc4Sort(*arraySort.range));
|
return m_solver.mkArraySort(CVC5Sort(*arraySort.domain), CVC5Sort(*arraySort.range));
|
||||||
}
|
}
|
||||||
case Kind::Tuple:
|
case Kind::Tuple:
|
||||||
{
|
{
|
||||||
auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort);
|
auto const& tupleSort = dynamic_cast<TupleSort const&>(_sort);
|
||||||
return m_context.mkTupleType(cvc4Sort(tupleSort.components));
|
return m_solver.mkTupleSort(CVC5Sort(tupleSort.components));
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
smtAssert(false, "");
|
smtAssert(false, "");
|
||||||
// Cannot be reached.
|
// Cannot be reached.
|
||||||
return m_context.integerType();
|
return m_solver.getIntegerSort();
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<CVC4::Type> CVC4Interface::cvc4Sort(vector<SortPointer> const& _sorts)
|
vector<cvc5::Sort> CVC5Interface::CVC5Sort(vector<SortPointer> const& _sorts)
|
||||||
{
|
{
|
||||||
vector<CVC4::Type> cvc4Sorts;
|
vector<cvc5::Sort> CVC5Sorts;
|
||||||
for (auto const& _sort: _sorts)
|
for (auto const& _sort: _sorts)
|
||||||
cvc4Sorts.push_back(cvc4Sort(*_sort));
|
CVC5Sorts.push_back(CVC5Sort(*_sort));
|
||||||
return cvc4Sorts;
|
return CVC5Sorts;
|
||||||
}
|
}
|
||||||
|
@ -20,30 +20,19 @@
|
|||||||
|
|
||||||
#include <libsmtutil/SolverInterface.h>
|
#include <libsmtutil/SolverInterface.h>
|
||||||
|
|
||||||
#if defined(__GLIBC__)
|
#include <cvc5/cvc5.h>
|
||||||
// The CVC4 headers includes the deprecated system headers <ext/hash_map>
|
|
||||||
// and <ext/hash_set>. These headers cause a warning that will break the
|
|
||||||
// build, unless _GLIBCXX_PERMIT_BACKWARD_HASH is set.
|
|
||||||
#define _GLIBCXX_PERMIT_BACKWARD_HASH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <cvc4/cvc4.h>
|
|
||||||
|
|
||||||
#if defined(__GLIBC__)
|
|
||||||
#undef _GLIBCXX_PERMIT_BACKWARD_HASH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace solidity::smtutil
|
namespace solidity::smtutil
|
||||||
{
|
{
|
||||||
|
|
||||||
class CVC4Interface: public SolverInterface
|
class CVC5Interface: public SolverInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Noncopyable.
|
/// Noncopyable.
|
||||||
CVC4Interface(CVC4Interface const&) = delete;
|
CVC5Interface(CVC5Interface const&) = delete;
|
||||||
CVC4Interface& operator=(CVC4Interface const&) = delete;
|
CVC5Interface& operator=(CVC5Interface const&) = delete;
|
||||||
|
|
||||||
CVC4Interface(std::optional<unsigned> _queryTimeout = {});
|
CVC5Interface(std::optional<unsigned> _queryTimeout = {});
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
|
|
||||||
@ -56,17 +45,16 @@ public:
|
|||||||
std::pair<CheckResult, std::vector<std::string>> check(std::vector<Expression> const& _expressionsToEvaluate) override;
|
std::pair<CheckResult, std::vector<std::string>> check(std::vector<Expression> const& _expressionsToEvaluate) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CVC4::Expr toCVC4Expr(Expression const& _expr);
|
cvc5::Term toCVC5Expr(Expression const& _expr);
|
||||||
CVC4::Type cvc4Sort(Sort const& _sort);
|
cvc5::Sort CVC5Sort(Sort const& _sort);
|
||||||
std::vector<CVC4::Type> cvc4Sort(std::vector<SortPointer> const& _sorts);
|
std::vector<cvc5::Sort> CVC5Sort(std::vector<SortPointer> const& _sorts);
|
||||||
|
|
||||||
CVC4::ExprManager m_context;
|
cvc5::Solver m_solver;
|
||||||
CVC4::SmtEngine m_solver;
|
std::map<std::string, cvc5::Term> m_variables;
|
||||||
std::map<std::string, CVC4::Expr> m_variables;
|
|
||||||
|
|
||||||
// CVC4 "basic resources" limit.
|
// CVC5 "basic resources" limit.
|
||||||
// This is used to make the runs more deterministic and platform/machine independent.
|
// This is used to make the runs more deterministic and platform/machine independent.
|
||||||
// The tests start failing for CVC4 with less than 6000,
|
// The tests start failing for CVC5 with less than 6000,
|
||||||
// so using double that.
|
// so using double that.
|
||||||
static int const resourceLimit = 12000;
|
static int const resourceLimit = 12000;
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
#include <libsmtutil/Z3Interface.h>
|
#include <libsmtutil/Z3Interface.h>
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CVC4
|
#ifdef HAVE_CVC5
|
||||||
#include <libsmtutil/CVC4Interface.h>
|
#include <libsmtutil/CVC4Interface.h>
|
||||||
#endif
|
#endif
|
||||||
#include <libsmtutil/SMTLib2Interface.h>
|
#include <libsmtutil/SMTLib2Interface.h>
|
||||||
@ -46,9 +46,9 @@ SMTPortfolio::SMTPortfolio(
|
|||||||
if (_enabledSolvers.z3 && Z3Interface::available())
|
if (_enabledSolvers.z3 && Z3Interface::available())
|
||||||
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout));
|
m_solvers.emplace_back(make_unique<Z3Interface>(m_queryTimeout));
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CVC4
|
#ifdef HAVE_CVC5
|
||||||
if (_enabledSolvers.cvc4)
|
if (_enabledSolvers.cvc5)
|
||||||
m_solvers.emplace_back(make_unique<CVC4Interface>(m_queryTimeout));
|
m_solvers.emplace_back(make_unique<CVC5Interface>(m_queryTimeout));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ namespace solidity::smtutil
|
|||||||
|
|
||||||
struct SMTSolverChoice
|
struct SMTSolverChoice
|
||||||
{
|
{
|
||||||
bool cvc4 = false;
|
bool cvc5 = false;
|
||||||
bool eld = false;
|
bool eld = false;
|
||||||
bool smtlib2 = false;
|
bool smtlib2 = false;
|
||||||
bool z3 = false;
|
bool z3 = false;
|
||||||
|
|
||||||
static constexpr SMTSolverChoice All() noexcept { return {true, true, true, true}; }
|
static constexpr SMTSolverChoice All() noexcept { return {true, true, true, true}; }
|
||||||
static constexpr SMTSolverChoice CVC4() noexcept { return {true, false, false, false}; }
|
static constexpr SMTSolverChoice CVC5() noexcept { return {true, false, false, false}; }
|
||||||
static constexpr SMTSolverChoice ELD() noexcept { return {false, true, false, false}; }
|
static constexpr SMTSolverChoice ELD() noexcept { return {false, true, false, false}; }
|
||||||
static constexpr SMTSolverChoice SMTLIB2() noexcept { return {false, false, true, false}; }
|
static constexpr SMTSolverChoice SMTLIB2() noexcept { return {false, false, true, false}; }
|
||||||
static constexpr SMTSolverChoice Z3() noexcept { return {false, false, false, true}; }
|
static constexpr SMTSolverChoice Z3() noexcept { return {false, false, false, true}; }
|
||||||
@ -65,7 +65,7 @@ struct SMTSolverChoice
|
|||||||
|
|
||||||
SMTSolverChoice& operator&=(SMTSolverChoice const& _other)
|
SMTSolverChoice& operator&=(SMTSolverChoice const& _other)
|
||||||
{
|
{
|
||||||
cvc4 &= _other.cvc4;
|
cvc5 &= _other.cvc5;
|
||||||
eld &= _other.eld;
|
eld &= _other.eld;
|
||||||
smtlib2 &= _other.smtlib2;
|
smtlib2 &= _other.smtlib2;
|
||||||
z3 &= _other.z3;
|
z3 &= _other.z3;
|
||||||
@ -82,7 +82,7 @@ struct SMTSolverChoice
|
|||||||
|
|
||||||
bool operator==(SMTSolverChoice const& _other) const noexcept
|
bool operator==(SMTSolverChoice const& _other) const noexcept
|
||||||
{
|
{
|
||||||
return cvc4 == _other.cvc4 &&
|
return cvc5 == _other.cvc5 &&
|
||||||
eld == _other.eld &&
|
eld == _other.eld &&
|
||||||
smtlib2 == _other.smtlib2 &&
|
smtlib2 == _other.smtlib2 &&
|
||||||
z3 == _other.z3;
|
z3 == _other.z3;
|
||||||
@ -90,11 +90,11 @@ struct SMTSolverChoice
|
|||||||
|
|
||||||
bool setSolver(std::string const& _solver)
|
bool setSolver(std::string const& _solver)
|
||||||
{
|
{
|
||||||
static std::set<std::string> const solvers{"cvc4", "eld", "smtlib2", "z3"};
|
static std::set<std::string> const solvers{"cvc5", "eld", "smtlib2", "z3"};
|
||||||
if (!solvers.count(_solver))
|
if (!solvers.count(_solver))
|
||||||
return false;
|
return false;
|
||||||
if (_solver == "cvc4")
|
if (_solver == "cvc5")
|
||||||
cvc4 = true;
|
cvc5 = true;
|
||||||
if (_solver == "eld")
|
if (_solver == "eld")
|
||||||
eld = true;
|
eld = true;
|
||||||
else if (_solver == "smtlib2")
|
else if (_solver == "smtlib2")
|
||||||
@ -105,8 +105,8 @@ struct SMTSolverChoice
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool none() const noexcept { return !some(); }
|
bool none() const noexcept { return !some(); }
|
||||||
bool some() const noexcept { return cvc4 || eld || smtlib2 || z3; }
|
bool some() const noexcept { return cvc5 || eld || smtlib2 || z3; }
|
||||||
bool all() const noexcept { return cvc4 && eld && smtlib2 && z3; }
|
bool all() const noexcept { return cvc5 && eld && smtlib2 && z3; }
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class CheckResult
|
enum class CheckResult
|
||||||
|
@ -49,15 +49,15 @@ BMC::BMC(
|
|||||||
SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider),
|
SMTEncoder(_context, _settings, _errorReporter, _unsupportedErrorReporter, _charStreamProvider),
|
||||||
m_interface(make_unique<smtutil::SMTPortfolio>(_smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout))
|
m_interface(make_unique<smtutil::SMTPortfolio>(_smtlib2Responses, _smtCallback, _settings.solvers, _settings.timeout))
|
||||||
{
|
{
|
||||||
#if defined (HAVE_Z3) || defined (HAVE_CVC4)
|
#if defined (HAVE_Z3) || defined (HAVE_CVC5)
|
||||||
if (m_settings.solvers.cvc4 || m_settings.solvers.z3)
|
if (m_settings.solvers.cvc5 || m_settings.solvers.z3)
|
||||||
if (!_smtlib2Responses.empty())
|
if (!_smtlib2Responses.empty())
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
5622_error,
|
5622_error,
|
||||||
"SMT-LIB2 query responses were given in the auxiliary input, "
|
"SMT-LIB2 query responses were given in the auxiliary input, "
|
||||||
"but this Solidity binary uses an SMT solver (Z3/CVC4) directly."
|
"but this Solidity binary uses an SMT solver (Z3/cvc5) directly."
|
||||||
"These responses will be ignored."
|
"These responses will be ignored."
|
||||||
"Consider disabling Z3/CVC4 at compilation time in order to use SMT-LIB2 responses."
|
"Consider disabling Z3/cvc5 at compilation time in order to use SMT-LIB2 responses."
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -65,13 +65,13 @@ BMC::BMC(
|
|||||||
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
|
void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<VerificationTargetType>, smt::EncodingContext::IdCompare> _solvedTargets)
|
||||||
{
|
{
|
||||||
// At this point every enabled solver is available.
|
// At this point every enabled solver is available.
|
||||||
if (!m_settings.solvers.cvc4 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
|
if (!m_settings.solvers.cvc5 && !m_settings.solvers.smtlib2 && !m_settings.solvers.z3)
|
||||||
{
|
{
|
||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
7710_error,
|
7710_error,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
"BMC analysis was not possible since no SMT solver was found and enabled."
|
"BMC analysis was not possible since no SMT solver was found and enabled."
|
||||||
" The accepted solvers for BMC are cvc4 and z3."
|
" The accepted solvers for BMC are cvc5 and z3."
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -121,7 +121,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
// If this check is true, Z3 and CVC4 are not available
|
// If this check is true, Z3 and cvc5 are not available
|
||||||
// and the query answers were not provided, since SMTPortfolio
|
// and the query answers were not provided, since SMTPortfolio
|
||||||
// guarantees that SmtLib2Interface is the first solver, if enabled.
|
// guarantees that SmtLib2Interface is the first solver, if enabled.
|
||||||
if (
|
if (
|
||||||
@ -132,7 +132,7 @@ void BMC::analyze(SourceUnit const& _source, map<ASTNode const*, set<Verificatio
|
|||||||
m_errorReporter.warning(
|
m_errorReporter.warning(
|
||||||
8084_error,
|
8084_error,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
"BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available."
|
"BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available."
|
||||||
" None of the installed solvers was enabled."
|
" None of the installed solvers was enabled."
|
||||||
#ifdef HAVE_Z3_DLOPEN
|
#ifdef HAVE_Z3_DLOPEN
|
||||||
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
|
" Install libz3.so." + to_string(Z3_MAJOR_VERSION) + "." + to_string(Z3_MINOR_VERSION) + " to enable Z3."
|
||||||
|
@ -170,8 +170,8 @@ SMTSolverChoice ModelChecker::availableSolvers()
|
|||||||
#ifdef HAVE_Z3
|
#ifdef HAVE_Z3
|
||||||
available.z3 = solidity::smtutil::Z3Interface::available();
|
available.z3 = solidity::smtutil::Z3Interface::available();
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_CVC4
|
#ifdef HAVE_CVC5
|
||||||
available.cvc4 = true;
|
available.cvc5 = true;
|
||||||
#endif
|
#endif
|
||||||
return available;
|
return available;
|
||||||
}
|
}
|
||||||
@ -180,13 +180,13 @@ SMTSolverChoice ModelChecker::checkRequestedSolvers(SMTSolverChoice _enabled, Er
|
|||||||
{
|
{
|
||||||
SMTSolverChoice availableSolvers{ModelChecker::availableSolvers()};
|
SMTSolverChoice availableSolvers{ModelChecker::availableSolvers()};
|
||||||
|
|
||||||
if (_enabled.cvc4 && !availableSolvers.cvc4)
|
if (_enabled.cvc5 && !availableSolvers.cvc5)
|
||||||
{
|
{
|
||||||
_enabled.cvc4 = false;
|
_enabled.cvc5 = false;
|
||||||
_errorReporter.warning(
|
_errorReporter.warning(
|
||||||
4902_error,
|
4902_error,
|
||||||
SourceLocation(),
|
SourceLocation(),
|
||||||
"Solver CVC4 was selected for SMTChecker but it is not available."
|
"Solver cvc5 was selected for SMTChecker but it is not available."
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -855,7 +855,7 @@ General Information)").c_str(),
|
|||||||
)
|
)
|
||||||
(
|
(
|
||||||
g_strModelCheckerSolvers.c_str(),
|
g_strModelCheckerSolvers.c_str(),
|
||||||
po::value<string>()->value_name("cvc4,eld,z3,smtlib2")->default_value("z3"),
|
po::value<string>()->value_name("cvc5,eld,z3,smtlib2")->default_value("z3"),
|
||||||
"Select model checker solvers."
|
"Select model checker solvers."
|
||||||
)
|
)
|
||||||
(
|
(
|
||||||
|
@ -4,4 +4,4 @@ Warning: CHC analysis was not possible. No Horn solver was available. None of th
|
|||||||
|
|
||||||
Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.
|
Warning: BMC: 1 verification condition(s) could not be proved. Enable the model checker option "show unproved" to see all of them. Consider choosing a specific contract to be verified in order to reduce the solving problems. Consider increasing the timeout per query.
|
||||||
|
|
||||||
Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.
|
Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
{
|
{
|
||||||
"component": "general",
|
"component": "general",
|
||||||
"errorCode": "7710",
|
"errorCode": "7710",
|
||||||
"formattedMessage": "Warning: BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc4 and z3.
|
"formattedMessage": "Warning: BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc5 and z3.
|
||||||
|
|
||||||
",
|
",
|
||||||
"message": "BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc4 and z3.",
|
"message": "BMC analysis was not possible since no SMT solver was found and enabled. The accepted solvers for BMC are cvc5 and z3.",
|
||||||
"severity": "warning",
|
"severity": "warning",
|
||||||
"type": "Warning"
|
"type": "Warning"
|
||||||
}
|
}
|
||||||
|
@ -189,10 +189,10 @@
|
|||||||
{
|
{
|
||||||
"component": "general",
|
"component": "general",
|
||||||
"errorCode": "8084",
|
"errorCode": "8084",
|
||||||
"formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.
|
"formattedMessage": "Warning: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.
|
||||||
|
|
||||||
",
|
",
|
||||||
"message": "BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.",
|
"message": "BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.",
|
||||||
"severity": "warning",
|
"severity": "warning",
|
||||||
"type": "Warning"
|
"type": "Warning"
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ protected:
|
|||||||
Set in m_modelCheckerSettings.
|
Set in m_modelCheckerSettings.
|
||||||
SMTShowUnproved: `yes`, `no`, where the default is `yes`.
|
SMTShowUnproved: `yes`, `no`, where the default is `yes`.
|
||||||
Set in m_modelCheckerSettings.
|
Set in m_modelCheckerSettings.
|
||||||
SMTSolvers: `all`, `cvc4`, `z3`, `none`, where the default is `all`.
|
SMTSolvers: `all`, `cvc5`, `z3`, `none`, where the default is `all`.
|
||||||
Set in m_modelCheckerSettings.
|
Set in m_modelCheckerSettings.
|
||||||
BMCLoopIterations: number of loop iterations for BMC engine, the default is 1.
|
BMCLoopIterations: number of loop iterations for BMC engine, the default is 1.
|
||||||
Set in m_modelCheckerSettings.
|
Set in m_modelCheckerSettings.
|
||||||
|
@ -19,8 +19,8 @@ contract C is B {
|
|||||||
// Warning 6328: (b.sol:62-75): CHC: Assertion violation might happen here.
|
// Warning 6328: (b.sol:62-75): CHC: Assertion violation might happen here.
|
||||||
// Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
|
// Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
|
||||||
// Warning 7812: (b.sol:62-75): BMC: Assertion violation might happen here.
|
// Warning 7812: (b.sol:62-75): BMC: Assertion violation might happen here.
|
||||||
// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.
|
// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.
|
||||||
// Warning 6328: (c.sol:68-81): CHC: Assertion violation might happen here.
|
// Warning 6328: (c.sol:68-81): CHC: Assertion violation might happen here.
|
||||||
// Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
|
// Warning 3996: CHC analysis was not possible. No Horn solver was available. None of the installed solvers was enabled.
|
||||||
// Warning 7812: (c.sol:68-81): BMC: Assertion violation might happen here.
|
// Warning 7812: (c.sol:68-81): BMC: Assertion violation might happen here.
|
||||||
// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or CVC4) was available. None of the installed solvers was enabled.
|
// Warning 8084: BMC analysis was not possible. No SMT solver (Z3 or cvc5) was available. None of the installed solvers was enabled.
|
||||||
|
Loading…
Reference in New Issue
Block a user