3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-16 12:05:43 +00:00
z3/src/smt/smt_checker.cpp
davedets 6ac3075022
Remove unnecessary semicolons (Attempt 2) (#10020)
This is another PR towards the goal of getting Z3 to compile cleanly
when included via FetchContents into clang-tidy, which uses a pretty
strict set of warnings.

This is a second version of https://github.com/Z3Prover/z3/pull/9957. I
address @NikolajBjorner 's comments about not changing the semicolons
after macro invocations, because some editors work better with them
present. It now, to the best of my ability, only deletes semis:

* after the closing brace of namespace decl.
* after the closing brace of an extern "C" decl.
* after a function definition.

This PR is very large, but it consists entirely of deletions of
semicolons in these situations.

(If there was a way to update the previous PR, which had been closed,
and that is preferable, please let me know. I couldn't figure it out.)
2026-07-02 12:47:29 -07:00

188 lines
6.3 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
smt_checker.cpp
Abstract:
<abstract>
Author:
Leonardo de Moura (leonardo) 2008-06-20.
Revision History:
--*/
#include "smt/smt_context.h"
#include "smt/smt_checker.h"
#include "ast/ast_ll_pp.h"
namespace smt {
bool checker::all_args(app *a, unsigned depth, bool is_true) {
for (expr* arg : *a) {
if (!check(arg, depth + 1, is_true))
return false;
}
return true;
}
bool checker::any_arg(app *a, unsigned depth, bool is_true) {
for (expr* arg : *a) {
if (check(arg, depth + 1, is_true))
return true;
}
return false;
}
bool checker::check_core(expr *n, unsigned depth, bool is_true) {
if (depth > 600)
return false;
SASSERT(m_manager.is_bool(n));
if (m_context.b_internalized(n) && m_context.is_relevant(n)) {
lbool val = m_context.get_assignment(n);
return val != l_undef && is_true == (val == l_true);
}
if (!is_app(n))
return false;
app * a = to_app(n);
if (a->get_family_id() == m_manager.get_basic_family_id()) {
switch (a->get_decl_kind()) {
case OP_TRUE:
return is_true;
case OP_FALSE:
return !is_true;
case OP_NOT:
return check(a->get_arg(0), depth + 1, !is_true);
case OP_OR:
return is_true ? any_arg(a, depth, true) : all_args(a, depth, false);
case OP_AND:
return is_true ? all_args(a, depth, true) : any_arg(a, depth, false);
case OP_EQ:
if (!m_manager.is_iff(a)) {
enode * lhs = get_enode_eq_to(a->get_arg(0));
enode * rhs = get_enode_eq_to(a->get_arg(1));
if (lhs && rhs && m_context.is_relevant(lhs) && m_context.is_relevant(rhs)) {
if (is_true && lhs->get_root() == rhs->get_root())
return true;
// if (!is_true && m_context.is_ext_diseq(lhs, rhs, 2))
if (!is_true && m_context.is_diseq(lhs, rhs))
return true;
}
return false;
}
else if (is_true) {
return
(check(a->get_arg(0), depth + 1, true) &&
check(a->get_arg(1), depth + 1, true)) ||
(check(a->get_arg(0), depth + 1, false) &&
check(a->get_arg(1), depth + 1, false));
}
else {
return
(check(a->get_arg(0), depth + 1, true) &&
check(a->get_arg(1), depth + 1, false)) ||
(check(a->get_arg(0), depth + 1, false) &&
check(a->get_arg(1), depth + 1, true));
}
case OP_ITE: {
if (m_context.lit_internalized(a->get_arg(0)) && m_context.is_relevant(a->get_arg(0))) {
switch (m_context.get_assignment(a->get_arg(0))) {
case l_false: return check(a->get_arg(2), depth + 1, is_true);
case l_undef: return false;
case l_true: return check(a->get_arg(1), depth + 1, is_true);
}
}
return check(a->get_arg(1), depth + 1, is_true) && check(a->get_arg(2), depth + 1, is_true);
}
default:
break;
}
}
enode * e = get_enode_eq_to(a);
if (e && e->is_bool() && m_context.is_relevant(e)) {
lbool val = m_context.get_assignment(e->get_expr());
return val != l_undef && is_true == (val == l_true);
}
return false;
}
bool checker::check(expr *n, unsigned depth, bool is_true) {
bool r;
if (n->get_ref_count() > 1 && m_is_true_cache[is_true].find(n, r))
return r;
r = check_core(n, depth, is_true);
if (n->get_ref_count() > 1)
m_is_true_cache[is_true].insert(n, r);
return r;
}
enode * checker::get_enode_eq_to_core(app * n) {
ptr_buffer<enode> buffer;
unsigned num = n->get_num_args();
for (unsigned i = 0; i < num; ++i) {
enode * arg = get_enode_eq_to(n->get_arg(i));
if (arg == nullptr)
return nullptr;
buffer.push_back(arg);
}
enode * e = m_context.get_enode_eq_to(n->get_decl(), num, buffer.data());
if (e == nullptr)
return nullptr;
return m_context.is_relevant(e) ? e : nullptr;
}
enode * checker::get_enode_eq_to(expr * n) {
if (is_var(n)) {
unsigned idx = to_var(n)->get_idx();
if (idx >= m_num_bindings)
return nullptr;
return m_bindings[m_num_bindings - idx - 1];
}
if (m_context.e_internalized(n) && m_context.is_relevant(n))
return m_context.get_enode(n);
if (!is_app(n) || to_app(n)->get_num_args() == 0)
return nullptr;
enode * r = nullptr;
if (n->get_ref_count() > 1 && m_to_enode_cache.find(n, r))
return r;
r = get_enode_eq_to_core(to_app(n));
if (n->get_ref_count() > 1)
m_to_enode_cache.insert(n, r);
return r;
}
bool checker::is_sat(expr * n, unsigned num_bindings, enode * const * bindings) {
flet<unsigned> l1(m_num_bindings, num_bindings);
flet<enode * const *> l2(m_bindings, bindings);
bool r = check(n, 0, true);
m_is_true_cache[0].reset();
m_is_true_cache[1].reset();
m_to_enode_cache.reset();
return r;
}
bool checker::is_unsat(expr * n, unsigned num_bindings, enode * const * bindings) {
flet<unsigned> l1(m_num_bindings, num_bindings);
flet<enode * const *> l2(m_bindings, bindings);
bool r = check(n, 0,false);
m_is_true_cache[0].reset();
m_is_true_cache[1].reset();
m_to_enode_cache.reset();
return r;
}
checker::checker(context & c):
m_context(c),
m_manager(c.get_manager()),
m_num_bindings(0),
m_bindings(nullptr) {
}
}