Go to the documentation of this file.
   26 #include <unordered_set> 
   32   bool _get_array_constraints)
 
   35     log(_message_handler),
 
   36     message_handler(_message_handler)
 
   62     "record_array_equality got equality without matching types",
 
   66     op0.
type().
id() == ID_array,
 
   67     "record_array_equality parameter should be array-typed");
 
   92   if(expr.
id()!=ID_index)
 
   94     if(expr.
id() == ID_array_comprehension)
 
  116     if(array_op_type.
id()==ID_array)
 
  138       array_type == with_expr.
old().
type(),
 
  139       "collect_arrays got 'with' without matching types",
 
  146     for(std::size_t i = 1; i < with_expr.
operands().size(); i += 2)
 
  152   else if(a.
id()==ID_update)
 
  157       array_type == update_expr.
old().
type(),
 
  158       "collect_arrays got 'update' without matching types",
 
  170   else if(a.
id()==ID_if)
 
  176       "collect_arrays got if without matching types",
 
  181       "collect_arrays got if without matching types",
 
  189   else if(a.
id()==ID_symbol)
 
  192   else if(a.
id()==ID_nondet_symbol)
 
  195   else if(a.
id()==ID_member)
 
  200       struct_op.id() == ID_symbol || struct_op.id() == ID_nondet_symbol,
 
  201       "unexpected array expression: member with '" + struct_op.id_string() +
 
  204   else if(a.
id()==ID_constant ||
 
  206           a.
id()==ID_string_constant)
 
  209   else if(a.
id()==ID_array_of)
 
  212   else if(a.
id()==ID_byte_update_little_endian ||
 
  213           a.
id()==ID_byte_update_big_endian)
 
  217       "byte_update should be removed before collect_arrays");
 
  219   else if(a.
id()==ID_typecast)
 
  225       typecast_op.type().id() == ID_array,
 
  226       "unexpected array type cast from " + typecast_op.type().id_string());
 
  231   else if(a.
id()==ID_index)
 
  238   else if(a.
id() == ID_array_comprehension)
 
  245       "unexpected array expression (collect_arrays): '" + a.
id_string() + 
"'");
 
  284   std::set<std::size_t> roots_to_process, updated_roots;
 
  288   while(!roots_to_process.empty())
 
  290     for(std::size_t i = 0; i < 
arrays.
size(); i++)
 
  307     roots_to_process = std::move(updated_roots);
 
  308     updated_roots.clear();
 
  330   std::cout << 
"arrays.size(): " << 
arrays.
size() << 
'\n';
 
  339     std::cout << 
"index_set.size(): " << index_set.size() << 
'\n';
 
  343     for(index_sett::const_iterator
 
  344         i1=index_set.begin();
 
  347       for(index_sett::const_iterator
 
  353           if(i1->is_constant() && i2->is_constant())
 
  364             const typet &subtype =
 
  369             index_expr2.
index()=*i2;
 
  371             equal_exprt values_equal(index_expr1, index_expr2);
 
  379 #if 0 // old code for adding, not significantly faster 
  394   INVARIANT(root_number!=i, 
"is_root_number incorrect?");
 
  399   root_index_set.insert(index_set.begin(), index_set.end());
 
  427     for(
const auto &index : index_entry.second)
 
  428       std::cout << 
"Index set (" << index_entry.first << 
" = " 
  431                 << 
"): " << 
format(index) << 
'\n';
 
  432   std::cout << 
"-----\n";
 
  442   for(
const auto &index : index_set)
 
  444     const typet &element_type1 =
 
  446     index_exprt index_expr1(array_equality.
f1, index, element_type1);
 
  448     const typet &element_type2 =
 
  450     index_exprt index_expr2(array_equality.
f2, index, element_type2);
 
  453       index_expr1.
type()==index_expr2.
type(),
 
  454       "array elements should all have same type");
 
  457     equal.
f1 = index_expr1;
 
  458     equal.
f2 = index_expr2;
 
  459     equal.
l = array_equality.
l;
 
  460     equal_exprt equality_expr(index_expr1, index_expr2);
 
  474   if(expr.
id()==ID_with)
 
  476   else if(expr.
id()==ID_update)
 
  478   else if(expr.
id()==ID_if)
 
  480   else if(expr.
id()==ID_array_of)
 
  482   else if(expr.
id() == ID_array)
 
  484   else if(expr.
id() == ID_array_comprehension)
 
  489   else if(expr.
id()==ID_symbol ||
 
  490           expr.
id()==ID_nondet_symbol ||
 
  491           expr.
id()==ID_constant ||
 
  492           expr.
id()==
"zero_string" ||
 
  493           expr.
id()==ID_string_constant)
 
  497     expr.
id() == ID_member &&
 
  502   else if(expr.
id()==ID_byte_update_little_endian ||
 
  503           expr.
id()==ID_byte_update_big_endian)
 
  505     INVARIANT(
false, 
"byte_update should be removed before arrayst");
 
  507   else if(expr.
id()==ID_typecast)
 
  513     for(
const auto &index : index_set)
 
  516       index_exprt index_expr1(expr, index, element_type);
 
  517       index_exprt index_expr2(expr_typecast_op, index, element_type);
 
  520         index_expr1.
type()==index_expr2.
type(),
 
  521         "array elements should all have same type");
 
  530   else if(expr.
id()==ID_index)
 
  537       "unexpected array expression (add_array_constraints): '" +
 
  548   std::unordered_set<exprt, irep_hash> updated_indices;
 
  551   for(std::size_t i = 1; i + 1 < operands.size(); i += 2)
 
  553     const exprt &index = operands[i];
 
  554     const exprt &value = operands[i + 1];
 
  561       "with-expression operand should match array element type",
 
  569     updated_indices.insert(index);
 
  575   for(
auto other_index : index_set)
 
  577     if(updated_indices.find(other_index) == updated_indices.end())
 
  581       disjuncts.reserve(updated_indices.size());
 
  582       for(
const auto &index : updated_indices)
 
  593         index_exprt index_expr1(expr, other_index, element_type);
 
  596         equal_exprt equality_expr(index_expr1, index_expr2);
 
  605 #if 0 // old code for adding, not significantly faster 
  611           bv.push_back(equality_lit);
 
  612           bv.push_back(guard_lit);
 
  629   const exprt &index=expr.where();
 
  630   const exprt &value=expr.new_value();
 
  637       "update operand should match array element type",
 
  646   for(
auto other_index : index_set)
 
  648     if(other_index!=index)
 
  659         index_exprt index_expr1(expr, other_index, subtype);
 
  660         index_exprt index_expr2(expr.op0(), other_index, subtype);
 
  662         equal_exprt equality_expr(index_expr1, index_expr2);
 
  669         bv.push_back(equality_lit);
 
  670         bv.push_back(guard_lit);
 
  686   for(
const auto &index : index_set)
 
  693       "array_of operand type should match array element type");
 
  710   for(
const auto &index : index_set)
 
  713     const index_exprt index_expr{expr, index, element_type};
 
  715     if(index.is_constant())
 
  723       if(!i.has_value() || *i >= operands.size())
 
  726       const exprt v = operands[*i];
 
  728         index_expr.type() == v.
type(),
 
  729         "array operand type should match array element type");
 
  745       std::vector<std::pair<std::size_t, std::size_t>> ranges;
 
  747       for(std::size_t i = 0; i < operands.size(); ++i)
 
  749         if(ranges.empty() || operands[i] != operands[ranges.back().first])
 
  750           ranges.emplace_back(i, i);
 
  752           ranges.back().second = i;
 
  755       for(
const auto &range : ranges)
 
  757         exprt index_constraint;
 
  759         if(range.first == range.second)
 
  770               index, ID_le, 
from_integer(range.second, index.type())}};
 
  792   for(
const auto &index : index_set)
 
  821   for(
const auto &index : index_set)
 
  824     index_exprt index_expr1(expr, index, element_type);
 
  834 #if 0 // old code for adding, not significantly faster 
  840   for(
const auto &index : index_set)
 
  843     index_exprt index_expr1(expr, index, element_type);
 
  854 #if 0 // old code for adding, not significantly faster 
  865     return "arrayAckermann";
 
  873     return "arrayTypecast";
 
  875     return "arrayConstant";
 
  877     return "arrayComprehension";
 
  879     return "arrayEquality";
 
  891   size_t num_constraints = 0;
 
  897     json_array_theory[contraint_type_string] =
 
  900     num_constraints += it->second;
 
  904   json_result[
"numOfConstraints"] =
 
  
 
Operator to update elements in structs and arrays.
 
#define UNREACHABLE
This should be used to mark dead code.
 
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
 
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
 
static exprt conditional_cast(const exprt &expr, const typet &type)
 
const typet & subtype() const
 
std::unordered_set< irep_idt > array_comprehension_args
 
literalt record_array_equality(const equal_exprt &expr)
 
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
 
The type of an expression, extends irept.
 
std::vector< literalt > bvt
 
mstreamt & status() const
 
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
 
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
 
The trinary if-then-else operator.
 
void collect_arrays(const exprt &a)
 
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
 
Base class for all expressions.
 
void set_to_true(const exprt &expr)
For a Boolean expression expr, add the constraint 'expr'.
 
const array_typet & type() const
 
const symbol_exprt & arg() const
 
void l_set_to_true(literalt a)
 
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
 
std::set< std::size_t > update_indices
 
json_objectt & make_object()
 
array_constraint_countt array_constraint_count
 
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
 
size_type number(const T &a)
 
typet & type()
Return the type of the expression.
 
const array_typet & type() const
 
void add_array_constraints_with(const index_sett &index_set, const with_exprt &expr)
 
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
 
size_type find_number(const_iterator it) const
 
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
 
bool make_union(const T &a, const T &b)
 
void add_array_constraints()
 
std::list< lazy_constraintt > lazy_array_constraints
 
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
 
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
 
#define forall_operands(it, expr)
 
const exprt & struct_op() const
 
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
 
const irep_idt & get_identifier() const
 
auto lazy(funt fun) -> lazyt< decltype(fun())>
Delay the computation of fun to the next time the force method is called.
 
Array constructor from single element.
 
array_equalitiest array_equalities
 
const std::string & id_string() const
 
const exprt & body() const
 
literalt const_literal(bool value)
 
virtual bool is_unbounded_array(const typet &type) const =0
 
std::set< exprt > index_sett
 
std::map< exprt, bool > expr_map
 
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
 
bool is_root_number(size_type a) const
 
const irep_idt & id() const
 
std::vector< exprt > operandst
 
void record_array_index(const index_exprt &expr)
 
nonstd::optional< T > optionalt
 
void add_array_Ackermann_constraints()
 
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
 
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
 
Operator to update elements in structs and arrays.
 
void display_array_constraint_count()
 
void add_array_constraints_update(const index_sett &index_set, const update_exprt &expr)
 
bool replace_expr(const exprt &what, const exprt &by, exprt &dest)
 
void add_array_constraints_comprehension(const index_sett &index_set, const array_comprehension_exprt &expr)
 
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
 
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
 
void add_array_constraints_array_constant(const index_sett &index_set, const array_exprt &exprt)
 
void add_array_constraints_array_of(const index_sett &index_set, const array_of_exprt &exprt)
 
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
 
void update_index_map(bool update_all)
 
union_find< exprt, irep_hash > arrays
 
Expression to define a mapping from an argument (index) to elements.
 
void add_array_constraint(const lazy_constraintt &lazy, bool refine=true)
adds array constraints (refine=true...lazily for the refinement loop)
 
bool get_array_constraints
 
Array constructor from list of elements.
 
void add_array_constraints_equality(const index_sett &index_set, const array_equalityt &array_equality)
 
arrayst(const namespacet &_ns, propt &_prop, message_handlert &message_handler, bool get_array_constraints=false)
 
void lcnf(literalt l0, literalt l1)
 
virtual literalt equality(const exprt &e1, const exprt &e2)
 
std::string enum_to_string(constraint_typet)
 
const typet & element_type() const
The type of the elements of the array.
 
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
 
void add_array_constraints_if(const index_sett &index_set, const if_exprt &exprt)