3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 06:03:23 +00:00
This commit is contained in:
Nikolaj Bjorner 2017-07-24 09:18:27 -07:00
commit ae5e39a8b8
20 changed files with 282 additions and 86 deletions

View file

@ -266,6 +266,8 @@ The following useful options can be passed to CMake whilst configuring.
Disabling this is useful for faster incremental builds. The documentation can be manually built by invoking the ``api_docs`` target.
* ``LINK_TIME_OPTIMIZATION`` - BOOL. If set to ``TRUE`` link time optimization will be enabled.
* ``API_LOG_SYNC`` - BOOL. If set to ``TRUE`` will enable experimental API log sync feature.
* ``WARNINGS_AS_ERRORS`` - STRING. If set to ``TRUE`` compiler warnings will be treated as errors. If set to ``False`` compiler warnings will not be treated as errors.
If set to ``SERIOUS_ONLY`` a subset of compiler warnings will be treated as errors.
On the command line these can be passed to ``cmake`` using the ``-D`` option. In ``ccmake`` and ``cmake-gui`` these can be set in the user interface.
@ -381,3 +383,13 @@ It is tempting use file-globbing in ``CMakeLists.txt`` to find a set for files m
use them as the sources to build a target. This however is a bad idea because it prevents CMake from knowing when it needs to rerun itself. This is why source file names are explicitly listed in the ``CMakeLists.txt`` so that when changes are made the source files used to build a target automatically triggers a rerun of CMake.
Long story short. Don't use file globbing.
### Serious warning flags
By default the `WARNINGS_AS_ERRORS` flag is set to `SERIOUS_ONLY` which means
some warnings will be treated as errors. These warnings are controlled by the
relevant `*_WARNINGS_AS_ERRORS` list defined in
`cmake/compiler_warnings.cmake`.
Additional warnings should only be added here if the warnings has no false
positives.

View file

@ -1,3 +1,7 @@
################################################################################
# Compiler warning flags
################################################################################
# These are passed to relevant compiler provided they are supported
set(GCC_AND_CLANG_WARNINGS
"-Wall"
)
@ -5,13 +9,53 @@ set(GCC_ONLY_WARNINGS "")
set(CLANG_ONLY_WARNINGS "")
set(MSVC_WARNINGS "/W3")
################################################################################
# Serious warnings
################################################################################
# This declares the flags that are passed to the compiler when
# `WARNINGS_AS_ERRORS` is set to `SERIOUS_ONLY`. Only flags that are supported
# by the compiler are used.
#
# In effect this a "whitelist" approach where we explicitly tell the compiler
# which warnings we want to be treated as errors. The alternative would be a
# "blacklist" approach where we ask the compiler to treat all warnings are
# treated as errors but then we explicitly list which warnings which should be
# allowed.
#
# The "whitelist" approach seems simpiler because we can incrementally add
# warnings we "think are serious".
# TODO: Add more warnings that are considered serious enough that we should
# treat them as errors.
set(GCC_AND_CLANG_WARNINGS_AS_ERRORS
# https://clang.llvm.org/docs/DiagnosticsReference.html#wodr
"-Werror=odr"
)
set(GCC_WARNINGS_AS_ERRORS
""
)
set(CLANG_WARNINGS_AS_ERRORS
# https://clang.llvm.org/docs/DiagnosticsReference.html#wdelete-non-virtual-dtor
"-Werror=delete-non-virtual-dtor"
# https://clang.llvm.org/docs/DiagnosticsReference.html#woverloaded-virtual
"-Werror=overloaded-virtual"
)
################################################################################
# Test warning/error flags
################################################################################
set(WARNING_FLAGS_TO_CHECK "")
set(WARNING_AS_ERROR_FLAGS_TO_CHECK "")
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU")
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS})
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_ONLY_WARNINGS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_WARNINGS_AS_ERRORS})
elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
list(APPEND WARNING_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS})
list(APPEND WARNING_FLAGS_TO_CHECK ${CLANG_ONLY_WARNINGS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${GCC_AND_CLANG_WARNINGS_AS_ERRORS})
list(APPEND WARNING_AS_ERROR_FLAGS_TO_CHECK ${CLANG_WARNINGS_AS_ERRORS})
# FIXME: Remove "x.." when CMP0054 is set to NEW
elseif ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
list(APPEND WARNING_FLAGS_TO_CHECK ${MSVC_WARNINGS})
@ -31,8 +75,40 @@ foreach (flag ${WARNING_FLAGS_TO_CHECK})
z3_add_cxx_flag("${flag}")
endforeach()
option(WARNINGS_AS_ERRORS "Treat compiler warnings as errors" OFF)
if (WARNINGS_AS_ERRORS)
# TODO: Remove this eventually.
# Detect legacy `WARNINGS_AS_ERRORS` boolean option and covert to new
# to new option type.
get_property(
WARNINGS_AS_ERRORS_CACHE_VAR_TYPE
CACHE
WARNINGS_AS_ERRORS
PROPERTY
TYPE
)
if ("${WARNINGS_AS_ERRORS_CACHE_VAR_TYPE}" STREQUAL "BOOL")
message(WARNING "Detected legacy WARNINGS_AS_ERRORS option. Upgrading")
set(WARNINGS_AS_ERRORS_DEFAULT "${WARNINGS_AS_ERRORS}")
# Delete old entry
unset(WARNINGS_AS_ERRORS CACHE)
else()
set(WARNINGS_AS_ERRORS_DEFAULT "SERIOUS_ONLY")
endif()
set(WARNINGS_AS_ERRORS
${WARNINGS_AS_ERRORS_DEFAULT}
CACHE STRING
"Treat warnings as errors. ON, OFF, or SERIOUS_ONLY"
)
# Set GUI options
set_property(
CACHE
WARNINGS_AS_ERRORS
PROPERTY STRINGS
"ON;OFF;SERIOUS_ONLY"
)
if ("${WARNINGS_AS_ERRORS}" STREQUAL "ON")
message(STATUS "Treating compiler warnings as errors")
if (("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") OR ("${CMAKE_CXX_COMPILER_ID}" MATCHES "GNU"))
list(APPEND Z3_COMPONENT_CXX_FLAGS "-Werror")
# FIXME: Remove "x.." when CMP0054 is set to NEW
@ -41,8 +117,14 @@ if (WARNINGS_AS_ERRORS)
else()
message(AUTHOR_WARNING "Unknown compiler")
endif()
message(STATUS "Treating compiler warnings as errors")
else()
elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "SERIOUS_ONLY")
message(STATUS "Treating only serious compiler warnings as errors")
# Loop through the flags
foreach (flag ${WARNING_AS_ERROR_FLAGS_TO_CHECK})
# Add globally because some flags need to be passed at link time.
z3_add_cxx_flag("${flag}" GLOBAL)
endforeach()
elseif ("${WARNINGS_AS_ERRORS}" STREQUAL "OFF")
message(STATUS "Not treating compiler warnings as errors")
# FIXME: Remove "x.." when CMP0054 is set to NEW
if ("x${CMAKE_CXX_COMPILER_ID}" STREQUAL "xMSVC")
@ -51,4 +133,8 @@ else()
# build system.
list(APPEND Z3_COMPONENT_CXX_FLAGS "/WX-")
endif()
else()
message(FATAL_ERROR
"WARNINGS_AS_ERRORS set to unsupported value \"${WARNINGS_AS_ERRORS}\""
)
endif()

View file

@ -2,7 +2,7 @@ include(CheckCXXCompilerFlag)
include(CMakeParseArguments)
function(z3_add_cxx_flag flag)
CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED" "" "" ${ARGN})
CMAKE_PARSE_ARGUMENTS(z3_add_flag "REQUIRED;GLOBAL" "" "" ${ARGN})
string(REPLACE "-" "_" SANITIZED_FLAG_NAME "${flag}")
string(REPLACE "/" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}")
string(REPLACE "=" "_" SANITIZED_FLAG_NAME "${SANITIZED_FLAG_NAME}")
@ -16,8 +16,13 @@ function(z3_add_cxx_flag flag)
endif()
if (HAS_${SANITIZED_FLAG_NAME})
message(STATUS "C++ compiler supports ${flag}")
if (z3_add_flag_GLOBAL)
# Set globally
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${flag} " PARENT_SCOPE)
else()
list(APPEND Z3_COMPONENT_CXX_FLAGS "${flag}")
set(Z3_COMPONENT_CXX_FLAGS "${Z3_COMPONENT_CXX_FLAGS}" PARENT_SCOPE)
endif()
else()
message(STATUS "C++ compiler does not support ${flag}")
endif()

View file

@ -28,6 +28,7 @@ ARG Z3_INSTALL_PREFIX=/usr
ARG Z3_STATIC_BUILD=0
# Blank default indicates use latest.
ARG Z3_SYSTEM_TEST_GIT_REVISION
ARG Z3_WARNINGS_AS_ERRORS=SERIOUS_ONLY
ARG Z3_VERBOSE_BUILD_OUTPUT=0
ENV \
@ -55,6 +56,7 @@ ENV \
Z3_STATIC_BUILD=${Z3_STATIC_BUILD} \
Z3_SYSTEM_TEST_DIR=/home/user/z3_system_test \
Z3_SYSTEM_TEST_GIT_REVISION=${Z3_SYSTEM_TEST_GIT_REVISION} \
Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \
Z3_INSTALL_PREFIX=${Z3_INSTALL_PREFIX}
# We add context across incrementally to maximal cache reuse

View file

@ -43,6 +43,7 @@ the future.
* `Z3_VERBOSE_BUILD_OUTPUT` - Show compile commands in CMake builds (`0` or `1`)
* `Z3_STATIC_BUILD` - Build Z3 binaries and libraries statically (`0` or `1`)
* `Z3_SYSTEM_TEST_GIT_REVISION` - Git revision of [z3test](https://github.com/Z3Prover/z3test). If empty lastest revision will be used.
* `Z3_WARNINGS_AS_ERRORS` - Set the `WARNINGS_AS_ERRORS` CMake option pased to Z3 (`OFF`, `ON`, or `SERIOUS_ONLY`)
### Linux

View file

@ -20,7 +20,8 @@ set -o pipefail
: ${DOTNET_BINDINGS?"DOTNET_BINDINGS must be specified"}
: ${JAVA_BINDINGS?"JAVA_BINDINGS must be specified"}
: ${USE_LTO?"USE_LTO must be specified"}
: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX"}
: ${Z3_INSTALL_PREFIX?"Z3_INSTALL_PREFIX must be specified"}
: ${Z3_WARNINGS_AS_ERRORS?"Z3_WARNINGS_AS_ERRORS must be specified"}
ADDITIONAL_Z3_OPTS=()
@ -120,6 +121,7 @@ cmake \
-DCMAKE_BUILD_TYPE=${Z3_BUILD_TYPE} \
-DPYTHON_EXECUTABLE=${PYTHON_EXECUTABLE} \
-DCMAKE_INSTALL_PREFIX=${Z3_INSTALL_PREFIX} \
-DWARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS} \
"${ADDITIONAL_Z3_OPTS[@]}" \
"${Z3_SRC_DIR}"

View file

@ -120,6 +120,13 @@ if [ -n "${NO_SUPPRESS_OUTPUT}" ]; then
)
fi
if [ -n "${Z3_WARNINGS_AS_ERRORS}" ]; then
BUILD_OPTS+=( \
"--build-arg" \
"Z3_WARNINGS_AS_ERRORS=${Z3_WARNINGS_AS_ERRORS}" \
)
fi
case ${LINUX_BASE} in
ubuntu_14.04)
BASE_DOCKER_FILE="${DOCKER_FILE_DIR}/z3_base_ubuntu_14.04.Dockerfile"

View file

@ -6054,6 +6054,24 @@ class Solver(Z3PPObject):
"""
Z3_solver_pop(self.ctx.ref(), self.solver, num)
def num_scopes(self):
"""Return the current number of backtracking points.
>>> s = Solver()
>>> s.num_scopes()
0L
>>> s.push()
>>> s.num_scopes()
1L
>>> s.push()
>>> s.num_scopes()
2L
>>> s.pop()
>>> s.num_scopes()
1L
"""
return Z3_solver_get_num_scopes(self.ctx.ref(), self.solver)
def reset(self):
"""Remove all asserted constraints and backtracking points created using `push()`.

View file

@ -421,7 +421,7 @@ typedef enum
It has the same semantics as Z3_OP_BUREM, but created in a context where the second operand can be assumed to be non-zero.
- Z3_OP_BSMOD_I: Binary signed modulus.
It has the same semantics as Z3_OP_BSMOND, but created in a context where the second operand can be assumed to be non-zero.
It has the same semantics as Z3_OP_BSMOD, but created in a context where the second operand can be assumed to be non-zero.
- Z3_OP_PR_UNDEF: Undef/Null proof object.

View file

@ -732,7 +732,7 @@ void bv_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const
op_names.push_back(builtin_name("bvudiv_i", OP_BUDIV_I));
op_names.push_back(builtin_name("bvsrem_i", OP_BSREM_I));
op_names.push_back(builtin_name("bvurem_i", OP_BUREM_I));
op_names.push_back(builtin_name("bvumod_i", OP_BSMOD_I));
op_names.push_back(builtin_name("bvsmod_i", OP_BSMOD_I));
op_names.push_back(builtin_name("ext_rotate_left",OP_EXT_ROTATE_LEFT));
op_names.push_back(builtin_name("ext_rotate_right",OP_EXT_ROTATE_RIGHT));

View file

@ -1632,8 +1632,6 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
res_exp = e_exp;
// Result could overflow into 4.xxx ...
family_id bvfid = m_bv_util.get_fid();
expr_ref res_sgn_c1(m), res_sgn_c2(m), res_sgn_c3(m);
expr_ref not_e_sgn(m), not_f_sgn(m), not_sign_bv(m);
@ -1646,11 +1644,34 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
expr * res_sgn_or_args[3] = { res_sgn_c1, res_sgn_c2, res_sgn_c3 };
res_sgn = m_bv_util.mk_bv_or(3, res_sgn_or_args);
// Result could have overflown into 4.xxx.
SASSERT(m_bv_util.get_bv_size(sig_abs) == 2 * sbits + 2);
expr_ref ovfl_into_4(m);
ovfl_into_4 = m.mk_eq(m_bv_util.mk_extract(2 * sbits + 1, 2 * sbits, sig_abs),
m_bv_util.mk_numeral(1, 2));
dbg_decouple("fpa2bv_fma_ovfl_into_4", ovfl_into_4);
if (sbits > 5) {
sticky_raw = m_bv_util.mk_extract(sbits - 5, 0, sig_abs);
sticky = m_bv_util.mk_zero_extend(sbits + 3, m.mk_app(bvfid, OP_BREDOR, sticky_raw.get()));
expr * res_or_args[2] = { m_bv_util.mk_extract(2 * sbits - 1, sbits - 4, sig_abs), sticky };
res_sig = m_bv_util.mk_bv_or(2, res_or_args);
expr_ref sticky_raw(m), sig_upper(m), sticky_redd(m), res_sig_norm(m);
sticky_raw = m_bv_util.mk_extract(sbits - 4, 0, sig_abs);
sig_upper = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs);
SASSERT(m_bv_util.get_bv_size(sig_upper) == sbits + 4);
sticky_redd = m.mk_app(bvfid, OP_BREDOR, sticky_raw.get());
sticky = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd);
expr * res_or_args[2] = { sig_upper, sticky };
res_sig_norm = m_bv_util.mk_bv_or(2, res_or_args);
expr_ref sticky_raw_ovfl(m), sig_upper_ovfl(m), sticky_redd_ovfl(m), sticky_ovfl(m), res_sig_ovfl(m);
sticky_raw_ovfl = m_bv_util.mk_extract(sbits - 4, 0, sig_abs);
sig_upper_ovfl = m_bv_util.mk_extract(2 * sbits, sbits - 3, sig_abs);
SASSERT(m_bv_util.get_bv_size(sig_upper_ovfl) == sbits + 4);
sticky_redd_ovfl = m.mk_app(bvfid, OP_BREDOR, sticky_raw_ovfl.get());
sticky_ovfl = m_bv_util.mk_zero_extend(sbits + 3, sticky_redd_ovfl);
expr * res_or_args_ovfl[2] = { sig_upper_ovfl, sticky_ovfl };
res_sig_ovfl = m_bv_util.mk_bv_or(2, res_or_args_ovfl);
res_sig = m.mk_ite(ovfl_into_4, res_sig_ovfl, res_sig_norm);
res_exp = m.mk_ite(ovfl_into_4, m_bv_util.mk_bv_add(res_exp, m_bv_util.mk_numeral(1, ebits+2)),
res_exp);
}
else {
unsigned too_short = 6 - sbits;
@ -1658,6 +1679,8 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
res_sig = m_bv_util.mk_extract(sbits + 3, 0, sig_abs);
}
dbg_decouple("fpa2bv_fma_add_sum_sticky", sticky);
dbg_decouple("fpa2bv_fma_sig_abs", sig_abs);
dbg_decouple("fpa2bv_fma_res_sig", res_sig);
SASSERT(m_bv_util.get_bv_size(res_sig) == sbits + 4);
expr_ref is_zero_sig(m), nil_sbits4(m);

View file

@ -56,6 +56,7 @@ namespace sat {
sat = false;
continue;
}
if (sat)
continue;
bool sign = l.sign();
@ -237,4 +238,22 @@ namespace sat {
}
}
unsigned model_converter::max_var(unsigned min) const {
unsigned result = min;
vector<entry>::const_iterator it = m_entries.begin();
vector<entry>::const_iterator end = m_entries.end();
for (; it != end; ++it) {
literal_vector::const_iterator lvit = it->m_clauses.begin();
literal_vector::const_iterator lvend = it->m_clauses.end();
for (; lvit != lvend; ++lvit) {
literal l = *lvit;
if (l != null_literal) {
if (l.var() > result)
result = l.var();
}
}
}
return result;
}
};

View file

@ -74,6 +74,7 @@ namespace sat {
void copy(model_converter const & src);
void collect_vars(bool_var_set & s) const;
unsigned max_var(unsigned min) const;
};
};

View file

@ -2628,7 +2628,7 @@ namespace sat {
unsigned j = 0;
for (unsigned i = 0; i < clauses.size(); ++i) {
clause & c = *(clauses[i]);
if (c.contains(lit)) {
if (c.contains(lit) || c.contains(~lit)) {
detach_clause(c);
del_clause(c);
}
@ -2684,6 +2684,7 @@ namespace sat {
w = max_var(m_clauses, w);
w = max_var(true, w);
w = max_var(false, w);
v = m_mc.max_var(w);
for (unsigned i = 0; i < m_trail.size(); ++i) {
if (m_trail[i].var() > w) w = m_trail[i].var();
}

View file

@ -61,7 +61,17 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e
return;
}
SASSERT(entry->get_data().m_value == 0);
try {
m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result);
}
catch (...) {
// CMW: The var_subst reducer was interrupted and m_instances is
// in an inconsistent state; we need to remove (new_key, 0).
m_instances.remove(new_key);
throw; // Throw on to smt::qi_queue/smt::solver.
}
// cache result
entry->get_data().m_value = result;
@ -74,6 +84,3 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e
m_refs.push_back(new_key->m_bindings[i]);
m_refs.push_back(result);
}

View file

@ -101,8 +101,9 @@ protected:
stats_type & m_stats;
obj_hashtable<sort> m_seen_sorts;
obj_hashtable<func_decl> m_seen_func_decls;
unsigned m_qdepth;
collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s) {}
collect_proc(ast_manager & m, stats_type & s) : m(m), m_stats(s), m_qdepth(0) {}
void operator()(var * v) {
m_stats["bound-variables"]++;
@ -113,7 +114,18 @@ protected:
m_stats["quantifiers"]++;
SASSERT(is_app(q->get_expr()));
app * body = to_app(q->get_expr());
if (q->is_forall())
m_stats["forall-variables"] += q->get_num_decls();
else
m_stats["exists-variables"] += q->get_num_decls();
m_stats["patterns"] += q->get_num_patterns();
m_stats["no-patterns"] += q->get_num_no_patterns();
m_qdepth++;
if (m_stats.find("max-quantification-depth") == m_stats.end() ||
m_stats["max-quantification-depth"] < m_qdepth)
m_stats["max-quantification-depth"] = m_qdepth;
this->operator()(body);
m_qdepth--;
}
void operator()(app * n) {