3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-29 09:28:45 +00:00

Issue #354. Fix unsoundness in Array theory based on missing propagation of selects over ite expressions

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-01-10 17:11:12 -08:00
parent 0df4931c4b
commit fce286db91
10 changed files with 112 additions and 10 deletions

View file

@ -44,7 +44,9 @@ namespace smt {
void theory_array::merge_eh(theory_var v1, theory_var v2, theory_var, theory_var) {
// v1 is the new root
TRACE("array", tout << "merging v" << v1 << " v" << v2 << "\n"; display_var(tout, v1););
TRACE("array",
tout << "merging v" << v1 << " v" << v2 << "\n"; display_var(tout, v1);
tout << mk_pp(get_enode(v1)->get_owner(), get_manager()) << " <- " << mk_pp(get_enode(v2)->get_owner(), get_manager()) << "\n";);
SASSERT(v1 == find(v1));
var_data * d1 = m_var_data[v1];
var_data * d2 = m_var_data[v2];
@ -70,21 +72,41 @@ namespace smt {
}
theory_var theory_array::mk_var(enode * n) {
ast_manager& m = get_manager();
context& ctx = get_context();
theory_var r = theory_array_base::mk_var(n);
theory_var r2 = m_find.mk_var();
SASSERT(r == r2);
SASSERT(r == static_cast<int>(m_var_data.size()));
m_var_data.push_back(alloc(var_data));
var_data * d = m_var_data[r];
TRACE("array", tout << mk_bounded_pp(n->get_owner(), get_manager()) << "\nis_array: " << is_array_sort(n) << ", is_select: " << is_select(n) <<
TRACE("array", tout << mk_bounded_pp(n->get_owner(), m) << "\nis_array: " << is_array_sort(n) << ", is_select: " << is_select(n) <<
", is_store: " << is_store(n) << "\n";);
d->m_is_array = is_array_sort(n);
if (d->m_is_array)
register_sort(get_manager().get_sort(n->get_owner()));
register_sort(m.get_sort(n->get_owner()));
d->m_is_select = is_select(n);
expr* e1, *e2, *e3;
if (is_store(n))
d->m_stores.push_back(n);
get_context().attach_th_var(n, this, r);
else if (m.is_ite(n->get_owner(), e1, e2, e3)) {
ptr_vector<expr> todo;
todo.push_back(e2);
todo.push_back(e3);
while (!todo.empty()) {
e1 = todo.back();
todo.pop_back();
if (is_app(e1) && is_store(to_app(e1))) {
d->m_stores.push_back(ctx.get_enode(e1));
}
else if (m.is_ite(e1, e1, e2, e3)) {
todo.push_back(e2);
todo.push_back(e3);
}
}
}
ctx.attach_th_var(n, this, r);
if (m_params.m_array_laziness <= 1 && is_store(n))
instantiate_axiom1(n);
return r;
@ -97,6 +119,7 @@ namespace smt {
v = find(v);
var_data * d = m_var_data[v];
d->m_parent_selects.push_back(s);
TRACE("array", tout << mk_pp(s->get_owner(), get_manager()) << " " << mk_pp(get_enode(v)->get_owner(), get_manager()) << "\n";);
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d->m_parent_selects));
ptr_vector<enode>::iterator it = d->m_stores.begin();
ptr_vector<enode>::iterator end = d->m_stores.end();
@ -109,8 +132,13 @@ namespace smt {
for (; it != end; ++it) {
enode * store = *it;
SASSERT(is_store(store));
if (!m_params.m_array_cg || store->is_cgr())
std::cout << mk_pp(store->get_owner(), get_manager()) << " " << mk_pp(s->get_owner(), get_manager()) << "\n";
if (!m_params.m_array_cg || store->is_cgr()) {
instantiate_axiom2b(s, store);
}
else {
std::cout << mk_pp(store->get_owner(), get_manager()) << "\n";
}
}
}
}
@ -331,6 +359,9 @@ namespace smt {
void theory_array::relevant_eh(app * n) {
if (m_params.m_array_laziness == 0)
return;
if (get_manager().is_ite(n)) {
TRACE("array", tout << "relevant ite " << mk_pp(n, get_manager()) << "\n";);
}
if (!is_store(n) && !is_select(n))
return;
context & ctx = get_context();