CBMC
arrays.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module:
4 
5 Author: Daniel Kroening, kroening@kroening.com
6 
7 \*******************************************************************/
8 
9 #include "arrays.h"
10 
11 #include <util/arith_tools.h>
12 #include <util/json.h>
13 #include <util/message.h>
14 #include <util/replace_expr.h>
15 #include <util/std_expr.h>
16 
18 #include <solvers/prop/prop.h>
19 
20 #ifdef DEBUG
21 # include <util/format_expr.h>
22 
23 # include <iostream>
24 #endif
25 
26 #include <unordered_set>
27 
29  const namespacet &_ns,
30  propt &_prop,
31  message_handlert &_message_handler,
32  bool _get_array_constraints)
33  : equalityt(_prop, _message_handler),
34  ns(_ns),
35  log(_message_handler),
36  message_handler(_message_handler)
37 {
38  lazy_arrays = false; // will be set to true when --refine is used
39  incremental_cache = false; // for incremental solving
40  // get_array_constraints is true when --show-array-constraints is used
41  get_array_constraints = _get_array_constraints;
42 }
43 
45 {
46  // we are not allowed to put the index directly in the
47  // entry for the root of the equivalence class
48  // because this map is accessed during building the error trace
49  std::size_t number=arrays.number(index.array());
50  if(index_map[number].insert(index.index()).second)
51  update_indices.insert(number);
52 }
53 
55  const equal_exprt &equality)
56 {
57  const exprt &op0=equality.op0();
58  const exprt &op1=equality.op1();
59 
61  op0.type() == op1.type(),
62  "record_array_equality got equality without matching types",
63  irep_pretty_diagnosticst{equality});
64 
66  op0.type().id() == ID_array,
67  "record_array_equality parameter should be array-typed");
68 
69  array_equalities.push_back(array_equalityt());
70 
71  array_equalities.back().f1=op0;
72  array_equalities.back().f2=op1;
73  array_equalities.back().l=SUB::equality(op0, op1);
74 
75  arrays.make_union(op0, op1);
76  collect_arrays(op0);
77  collect_arrays(op1);
78 
79  return array_equalities.back().l;
80 }
81 
83 {
84  for(std::size_t i=0; i<arrays.size(); i++)
85  {
87  }
88 }
89 
91 {
92  if(expr.id()!=ID_index)
93  {
94  if(expr.id() == ID_array_comprehension)
97 
98  forall_operands(op, expr) collect_indices(*op);
99  }
100  else
101  {
102  const index_exprt &e = to_index_expr(expr);
103 
104  if(
105  e.index().id() == ID_symbol &&
107  to_symbol_expr(e.index()).get_identifier()) != 0)
108  {
109  return;
110  }
111 
112  collect_indices(e.index()); // necessary?
113 
114  const typet &array_op_type = e.array().type();
115 
116  if(array_op_type.id()==ID_array)
117  {
118  const array_typet &array_type=
119  to_array_type(array_op_type);
120 
121  if(is_unbounded_array(array_type))
122  {
124  }
125  }
126  }
127 }
128 
130 {
131  const array_typet &array_type = to_array_type(a.type());
132 
133  if(a.id()==ID_with)
134  {
135  const with_exprt &with_expr=to_with_expr(a);
136 
138  array_type == with_expr.old().type(),
139  "collect_arrays got 'with' without matching types",
141 
142  arrays.make_union(a, with_expr.old());
143  collect_arrays(with_expr.old());
144 
145  // make sure this shows as an application
146  for(std::size_t i = 1; i < with_expr.operands().size(); i += 2)
147  {
148  index_exprt index_expr(with_expr.old(), with_expr.operands()[i]);
149  record_array_index(index_expr);
150  }
151  }
152  else if(a.id()==ID_update)
153  {
154  const update_exprt &update_expr=to_update_expr(a);
155 
157  array_type == update_expr.old().type(),
158  "collect_arrays got 'update' without matching types",
160 
161  arrays.make_union(a, update_expr.old());
162  collect_arrays(update_expr.old());
163 
164 #if 0
165  // make sure this shows as an application
166  index_exprt index_expr(update_expr.old(), update_expr.index());
167  record_array_index(index_expr);
168 #endif
169  }
170  else if(a.id()==ID_if)
171  {
172  const if_exprt &if_expr=to_if_expr(a);
173 
175  array_type == if_expr.true_case().type(),
176  "collect_arrays got if without matching types",
178 
180  array_type == if_expr.false_case().type(),
181  "collect_arrays got if without matching types",
183 
184  arrays.make_union(a, if_expr.true_case());
185  arrays.make_union(a, if_expr.false_case());
186  collect_arrays(if_expr.true_case());
187  collect_arrays(if_expr.false_case());
188  }
189  else if(a.id()==ID_symbol)
190  {
191  }
192  else if(a.id()==ID_nondet_symbol)
193  {
194  }
195  else if(a.id()==ID_member)
196  {
197  const auto &struct_op = to_member_expr(a).struct_op();
198 
200  struct_op.id() == ID_symbol || struct_op.id() == ID_nondet_symbol,
201  "unexpected array expression: member with '" + struct_op.id_string() +
202  "'");
203  }
204  else if(a.id()==ID_constant ||
205  a.id()==ID_array ||
206  a.id()==ID_string_constant)
207  {
208  }
209  else if(a.id()==ID_array_of)
210  {
211  }
212  else if(a.id()==ID_byte_update_little_endian ||
213  a.id()==ID_byte_update_big_endian)
214  {
216  false,
217  "byte_update should be removed before collect_arrays");
218  }
219  else if(a.id()==ID_typecast)
220  {
221  const auto &typecast_op = to_typecast_expr(a).op();
222 
223  // cast between array types?
225  typecast_op.type().id() == ID_array,
226  "unexpected array type cast from " + typecast_op.type().id_string());
227 
228  arrays.make_union(a, typecast_op);
229  collect_arrays(typecast_op);
230  }
231  else if(a.id()==ID_index)
232  {
233  // nested unbounded arrays
234  const auto &array_op = to_index_expr(a).array();
235  arrays.make_union(a, array_op);
236  collect_arrays(array_op);
237  }
238  else if(a.id() == ID_array_comprehension)
239  {
240  }
241  else
242  {
244  false,
245  "unexpected array expression (collect_arrays): '" + a.id_string() + "'");
246  }
247 }
248 
251 {
252  if(lazy_arrays && refine)
253  {
254  // lazily add the constraint
256  {
257  if(expr_map.find(lazy.lazy) == expr_map.end())
258  {
259  lazy_array_constraints.push_back(lazy);
260  expr_map[lazy.lazy] = true;
261  }
262  }
263  else
264  {
265  lazy_array_constraints.push_back(lazy);
266  }
267  }
268  else
269  {
270  // add the constraint eagerly
272  }
273 }
274 
276 {
277  collect_indices();
278  // at this point all indices should in the index set
279 
280  // reduce initial index map
281  update_index_map(true);
282 
283  // add constraints for if, with, array_of, lambda
284  std::set<std::size_t> roots_to_process, updated_roots;
285  for(std::size_t i=0; i<arrays.size(); i++)
286  roots_to_process.insert(arrays.find_number(i));
287 
288  while(!roots_to_process.empty())
289  {
290  for(std::size_t i = 0; i < arrays.size(); i++)
291  {
292  if(roots_to_process.count(arrays.find_number(i)) == 0)
293  continue;
294 
295  // take a copy as arrays may get modified by add_array_constraints
296  // in case of nested unbounded arrays
297  exprt a = arrays[i];
298 
300 
301  // we have to update before it gets used in the next add_* call
302  for(const std::size_t u : update_indices)
303  updated_roots.insert(arrays.find_number(u));
304  update_index_map(false);
305  }
306 
307  roots_to_process = std::move(updated_roots);
308  updated_roots.clear();
309  }
310 
311  // add constraints for equalities
312  for(const auto &equality : array_equalities)
313  {
316  equality);
317 
318  // update_index_map should not be necessary here
319  }
320 
321  // add the Ackermann constraints
323 }
324 
326 {
327  // this is quadratic!
328 
329 #ifdef DEBUG
330  std::cout << "arrays.size(): " << arrays.size() << '\n';
331 #endif
332 
333  // iterate over arrays
334  for(std::size_t i=0; i<arrays.size(); i++)
335  {
336  const index_sett &index_set=index_map[arrays.find_number(i)];
337 
338 #ifdef DEBUG
339  std::cout << "index_set.size(): " << index_set.size() << '\n';
340 #endif
341 
342  // iterate over indices, 2x!
343  for(index_sett::const_iterator
344  i1=index_set.begin();
345  i1!=index_set.end();
346  i1++)
347  for(index_sett::const_iterator
348  i2=i1;
349  i2!=index_set.end();
350  i2++)
351  if(i1!=i2)
352  {
353  if(i1->is_constant() && i2->is_constant())
354  continue;
355 
356  // index equality
357  const equal_exprt indices_equal(
358  *i1, typecast_exprt::conditional_cast(*i2, i1->type()));
359 
360  literalt indices_equal_lit=convert(indices_equal);
361 
362  if(indices_equal_lit!=const_literal(false))
363  {
364  const typet &subtype =
365  to_array_type(arrays[i].type()).element_type();
366  index_exprt index_expr1(arrays[i], *i1, subtype);
367 
368  index_exprt index_expr2=index_expr1;
369  index_expr2.index()=*i2;
370 
371  equal_exprt values_equal(index_expr1, index_expr2);
372 
373  // add constraint
375  implies_exprt(literal_exprt(indices_equal_lit), values_equal));
376  add_array_constraint(lazy, true); // added lazily
378 
379 #if 0 // old code for adding, not significantly faster
380  prop.lcnf(!indices_equal_lit, convert(values_equal));
381 #endif
382  }
383  }
384  }
385 }
386 
388 void arrayst::update_index_map(std::size_t i)
389 {
390  if(arrays.is_root_number(i))
391  return;
392 
393  std::size_t root_number=arrays.find_number(i);
394  INVARIANT(root_number!=i, "is_root_number incorrect?");
395 
396  index_sett &root_index_set=index_map[root_number];
397  index_sett &index_set=index_map[i];
398 
399  root_index_set.insert(index_set.begin(), index_set.end());
400 }
401 
402 void arrayst::update_index_map(bool update_all)
403 {
404  // iterate over non-roots
405  // possible reasons why update is needed:
406  // -- there are new equivalence classes in arrays
407  // -- there are new indices for arrays that are not the root
408  // of an equivalence class
409  // (and we cannot do that in record_array_index())
410  // -- equivalence classes have been merged
411  if(update_all)
412  {
413  for(std::size_t i=0; i<arrays.size(); i++)
414  update_index_map(i);
415  }
416  else
417  {
418  for(const auto &index : update_indices)
419  update_index_map(index);
420 
421  update_indices.clear();
422  }
423 
424 #ifdef DEBUG
425  // print index sets
426  for(const auto &index_entry : index_map)
427  for(const auto &index : index_entry.second)
428  std::cout << "Index set (" << index_entry.first << " = "
429  << arrays.find_number(index_entry.first) << " = "
430  << format(arrays[arrays.find_number(index_entry.first)])
431  << "): " << format(index) << '\n';
432  std::cout << "-----\n";
433 #endif
434 }
435 
437  const index_sett &index_set,
438  const array_equalityt &array_equality)
439 {
440  // add constraints x=y => x[i]=y[i]
441 
442  for(const auto &index : index_set)
443  {
444  const typet &element_type1 =
445  to_array_type(array_equality.f1.type()).element_type();
446  index_exprt index_expr1(array_equality.f1, index, element_type1);
447 
448  const typet &element_type2 =
449  to_array_type(array_equality.f2.type()).element_type();
450  index_exprt index_expr2(array_equality.f2, index, element_type2);
451 
453  index_expr1.type()==index_expr2.type(),
454  "array elements should all have same type");
455 
456  array_equalityt equal;
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);
461 
462  // add constraint
463  // equality constraints are not added lazily
464  // convert must be done to guarantee correct update of the index_set
465  prop.lcnf(!array_equality.l, convert(equality_expr));
467  }
468 }
469 
471  const index_sett &index_set,
472  const exprt &expr)
473 {
474  if(expr.id()==ID_with)
475  return add_array_constraints_with(index_set, to_with_expr(expr));
476  else if(expr.id()==ID_update)
477  return add_array_constraints_update(index_set, to_update_expr(expr));
478  else if(expr.id()==ID_if)
479  return add_array_constraints_if(index_set, to_if_expr(expr));
480  else if(expr.id()==ID_array_of)
481  return add_array_constraints_array_of(index_set, to_array_of_expr(expr));
482  else if(expr.id() == ID_array)
483  return add_array_constraints_array_constant(index_set, to_array_expr(expr));
484  else if(expr.id() == ID_array_comprehension)
485  {
487  index_set, to_array_comprehension_expr(expr));
488  }
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)
494  {
495  }
496  else if(
497  expr.id() == ID_member &&
498  (to_member_expr(expr).struct_op().id() == ID_symbol ||
499  to_member_expr(expr).struct_op().id() == ID_nondet_symbol))
500  {
501  }
502  else if(expr.id()==ID_byte_update_little_endian ||
503  expr.id()==ID_byte_update_big_endian)
504  {
505  INVARIANT(false, "byte_update should be removed before arrayst");
506  }
507  else if(expr.id()==ID_typecast)
508  {
509  // we got a=(type[])b
510  const auto &expr_typecast_op = to_typecast_expr(expr).op();
511 
512  // add a[i]=b[i]
513  for(const auto &index : index_set)
514  {
515  const typet &element_type = to_array_type(expr.type()).element_type();
516  index_exprt index_expr1(expr, index, element_type);
517  index_exprt index_expr2(expr_typecast_op, index, element_type);
518 
520  index_expr1.type()==index_expr2.type(),
521  "array elements should all have same type");
522 
523  // add constraint
525  equal_exprt(index_expr1, index_expr2));
526  add_array_constraint(lazy, false); // added immediately
528  }
529  }
530  else if(expr.id()==ID_index)
531  {
532  }
533  else
534  {
536  false,
537  "unexpected array expression (add_array_constraints): '" +
538  expr.id_string() + "'");
539  }
540 }
541 
543  const index_sett &index_set,
544  const with_exprt &expr)
545 {
546  // We got x=(y with [i:=v, j:=w, ...]).
547  // First add constraints x[i]=v, x[j]=w, ...
548  std::unordered_set<exprt, irep_hash> updated_indices;
549 
550  const exprt::operandst &operands = expr.operands();
551  for(std::size_t i = 1; i + 1 < operands.size(); i += 2)
552  {
553  const exprt &index = operands[i];
554  const exprt &value = operands[i + 1];
555 
556  index_exprt index_expr(
557  expr, index, to_array_type(expr.type()).element_type());
558 
560  index_expr.type() == value.type(),
561  "with-expression operand should match array element type",
563 
565  lazy_typet::ARRAY_WITH, equal_exprt(index_expr, value));
566  add_array_constraint(lazy, false); // added immediately
568 
569  updated_indices.insert(index);
570  }
571 
572  // For all other indices use the existing value, i.e., add constraints
573  // x[I]=y[I] for I!=i,j,...
574 
575  for(auto other_index : index_set)
576  {
577  if(updated_indices.find(other_index) == updated_indices.end())
578  {
579  // we first build the guard
580  exprt::operandst disjuncts;
581  disjuncts.reserve(updated_indices.size());
582  for(const auto &index : updated_indices)
583  {
584  disjuncts.push_back(equal_exprt{
585  index, typecast_exprt::conditional_cast(other_index, index.type())});
586  }
587 
588  literalt guard_lit = convert(disjunction(disjuncts));
589 
590  if(guard_lit!=const_literal(true))
591  {
592  const typet &element_type = to_array_type(expr.type()).element_type();
593  index_exprt index_expr1(expr, other_index, element_type);
594  index_exprt index_expr2(expr.old(), other_index, element_type);
595 
596  equal_exprt equality_expr(index_expr1, index_expr2);
597 
598  // add constraint
600  literal_exprt(guard_lit)));
601 
602  add_array_constraint(lazy, false); // added immediately
604 
605 #if 0 // old code for adding, not significantly faster
606  {
607  literalt equality_lit=convert(equality_expr);
608 
609  bvt bv;
610  bv.reserve(2);
611  bv.push_back(equality_lit);
612  bv.push_back(guard_lit);
613  prop.lcnf(bv);
614  }
615 #endif
616  }
617  }
618  }
619 }
620 
622  const index_sett &,
623  const update_exprt &)
624 {
625  // we got x=UPDATE(y, [i], v)
626  // add constaint x[i]=v
627 
628 #if 0
629  const exprt &index=expr.where();
630  const exprt &value=expr.new_value();
631 
632  {
633  index_exprt index_expr(expr, index, expr.type().subtype());
634 
636  index_expr.type()==value.type(),
637  "update operand should match array element type",
639 
640  set_to_true(equal_exprt(index_expr, value));
641  }
642 
643  // use other array index applications for "else" case
644  // add constraint x[I]=y[I] for I!=i
645 
646  for(auto other_index : index_set)
647  {
648  if(other_index!=index)
649  {
650  // we first build the guard
651 
652  other_index = typecast_exprt::conditional_cast(other_index, index.type());
653 
654  literalt guard_lit=convert(equal_exprt(index, other_index));
655 
656  if(guard_lit!=const_literal(true))
657  {
658  const typet &subtype=expr.type().subtype();
659  index_exprt index_expr1(expr, other_index, subtype);
660  index_exprt index_expr2(expr.op0(), other_index, subtype);
661 
662  equal_exprt equality_expr(index_expr1, index_expr2);
663 
664  literalt equality_lit=convert(equality_expr);
665 
666  // add constraint
667  bvt bv;
668  bv.reserve(2);
669  bv.push_back(equality_lit);
670  bv.push_back(guard_lit);
671  prop.lcnf(bv);
672  }
673  }
674  }
675 #endif
676 }
677 
679  const index_sett &index_set,
680  const array_of_exprt &expr)
681 {
682  // we got x=array_of[v]
683  // get other array index applications
684  // and add constraint x[i]=v
685 
686  for(const auto &index : index_set)
687  {
688  const typet &element_type = expr.type().element_type();
689  index_exprt index_expr(expr, index, element_type);
690 
692  index_expr.type() == expr.what().type(),
693  "array_of operand type should match array element type");
694 
695  // add constraint
697  lazy_typet::ARRAY_OF, equal_exprt(index_expr, expr.what()));
698  add_array_constraint(lazy, false); // added immediately
700  }
701 }
702 
704  const index_sett &index_set,
705  const array_exprt &expr)
706 {
707  // we got x = { v, ... } - add constraint x[i] = v
708  const exprt::operandst &operands = expr.operands();
709 
710  for(const auto &index : index_set)
711  {
712  const typet &element_type = expr.type().element_type();
713  const index_exprt index_expr{expr, index, element_type};
714 
715  if(index.is_constant())
716  {
717  // We have a constant index - just pick the element at that index from the
718  // array constant.
719 
720  const optionalt<std::size_t> i =
721  numeric_cast<std::size_t>(to_constant_expr(index));
722  // if the access is out of bounds, we leave it unconstrained
723  if(!i.has_value() || *i >= operands.size())
724  continue;
725 
726  const exprt v = operands[*i];
728  index_expr.type() == v.type(),
729  "array operand type should match array element type");
730 
731  // add constraint
733  equal_exprt{index_expr, v}};
734  add_array_constraint(lazy, false); // added immediately
736  }
737  else
738  {
739  // We have a non-constant index into an array constant. We need to build a
740  // case statement testing the index against all possible values. Whenever
741  // neighbouring array elements are the same, we can test the index against
742  // the range rather than individual elements. This should be particularly
743  // helpful when we have arrays of zeros, as is the case for initializers.
744 
745  std::vector<std::pair<std::size_t, std::size_t>> ranges;
746 
747  for(std::size_t i = 0; i < operands.size(); ++i)
748  {
749  if(ranges.empty() || operands[i] != operands[ranges.back().first])
750  ranges.emplace_back(i, i);
751  else
752  ranges.back().second = i;
753  }
754 
755  for(const auto &range : ranges)
756  {
757  exprt index_constraint;
758 
759  if(range.first == range.second)
760  {
761  index_constraint =
762  equal_exprt{index, from_integer(range.first, index.type())};
763  }
764  else
765  {
766  index_constraint = and_exprt{
768  from_integer(range.first, index.type()), ID_le, index},
770  index, ID_le, from_integer(range.second, index.type())}};
771  }
772 
775  implies_exprt{index_constraint,
776  equal_exprt{index_expr, operands[range.first]}}};
777  add_array_constraint(lazy, true); // added lazily
779  }
780  }
781  }
782 }
783 
785  const index_sett &index_set,
786  const array_comprehension_exprt &expr)
787 {
788  // we got x=lambda(i: e)
789  // get all other array index applications
790  // and add constraints x[j]=e[i/j]
791 
792  for(const auto &index : index_set)
793  {
794  index_exprt index_expr{expr, index};
795  exprt comprehension_body = expr.body();
796  replace_expr(expr.arg(), index, comprehension_body);
797 
798  // add constraint
801  equal_exprt(index_expr, comprehension_body));
802 
803  add_array_constraint(lazy, false); // added immediately
805  }
806 }
807 
809  const index_sett &index_set,
810  const if_exprt &expr)
811 {
812  // we got x=(c?a:b)
813  literalt cond_lit=convert(expr.cond());
814 
815  // get other array index applications
816  // and add c => x[i]=a[i]
817  // !c => x[i]=b[i]
818 
819  // first do true case
820 
821  for(const auto &index : index_set)
822  {
823  const typet &element_type = to_array_type(expr.type()).element_type();
824  index_exprt index_expr1(expr, index, element_type);
825  index_exprt index_expr2(expr.true_case(), index, element_type);
826 
827  // add implication
829  or_exprt(literal_exprt(!cond_lit),
830  equal_exprt(index_expr1, index_expr2)));
831  add_array_constraint(lazy, false); // added immediately
833 
834 #if 0 // old code for adding, not significantly faster
835  prop.lcnf(!cond_lit, convert(equal_exprt(index_expr1, index_expr2)));
836 #endif
837  }
838 
839  // now the false case
840  for(const auto &index : index_set)
841  {
842  const typet &element_type = to_array_type(expr.type()).element_type();
843  index_exprt index_expr1(expr, index, element_type);
844  index_exprt index_expr2(expr.false_case(), index, element_type);
845 
846  // add implication
849  or_exprt(literal_exprt(cond_lit),
850  equal_exprt(index_expr1, index_expr2)));
851  add_array_constraint(lazy, false); // added immediately
853 
854 #if 0 // old code for adding, not significantly faster
855  prop.lcnf(cond_lit, convert(equal_exprt(index_expr1, index_expr2)));
856 #endif
857  }
858 }
859 
861 {
862  switch(type)
863  {
865  return "arrayAckermann";
867  return "arrayWith";
869  return "arrayIf";
871  return "arrayOf";
873  return "arrayTypecast";
875  return "arrayConstant";
877  return "arrayComprehension";
879  return "arrayEquality";
880  default:
881  UNREACHABLE;
882  }
883 }
884 
886 {
887  json_objectt json_result;
888  json_objectt &json_array_theory =
889  json_result["arrayConstraints"].make_object();
890 
891  size_t num_constraints = 0;
892 
893  array_constraint_countt::iterator it = array_constraint_count.begin();
894  while(it != array_constraint_count.end())
895  {
896  std::string contraint_type_string = enum_to_string(it->first);
897  json_array_theory[contraint_type_string] =
898  json_numbert(std::to_string(it->second));
899 
900  num_constraints += it->second;
901  it++;
902  }
903 
904  json_result["numOfConstraints"] =
905  json_numbert(std::to_string(num_constraints));
906  log.status() << ",\n" << json_result;
907 }
with_exprt
Operator to update elements in structs and arrays.
Definition: std_expr.h:2423
UNREACHABLE
#define UNREACHABLE
This should be used to mark dead code.
Definition: invariant.h:503
json_numbert
Definition: json.h:290
to_array_comprehension_expr
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
Definition: std_expr.h:3418
format
static format_containert< T > format(const T &o)
Definition: format.h:37
to_update_expr
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition: std_expr.h:2688
arrayst::constraint_typet::ARRAY_WITH
@ ARRAY_WITH
typecast_exprt::conditional_cast
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition: std_expr.h:2025
arrayst::constraint_typet::ARRAY_COMPREHENSION
@ ARRAY_COMPREHENSION
arrayst::array_equalityt::f1
exprt f1
Definition: arrays.h:68
arrayst::constraint_typet::ARRAY_IF
@ ARRAY_IF
typet::subtype
const typet & subtype() const
Definition: type.h:50
arrayst::constraint_typet
constraint_typet
Definition: arrays.h:118
arrayst::array_comprehension_args
std::unordered_set< irep_idt > array_comprehension_args
Definition: arrays.h:163
arrayst::record_array_equality
literalt record_array_equality(const equal_exprt &expr)
Definition: arrays.cpp:54
arith_tools.h
to_array_expr
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition: std_expr.h:1603
arrayst::log
messaget log
Definition: arrays.h:57
array_of_exprt::what
exprt & what()
Definition: std_expr.h:1515
arrayst::lazy_constraintt
Definition: arrays.h:99
typet
The type of an expression, extends irept.
Definition: type.h:28
update_exprt::old
exprt & old()
Definition: std_expr.h:2620
bvt
std::vector< literalt > bvt
Definition: literal.h:201
arrayst::index_map
index_mapt index_map
Definition: arrays.h:85
messaget::status
mstreamt & status() const
Definition: message.h:414
to_index_expr
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition: std_expr.h:1478
to_if_expr
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition: std_expr.h:2403
if_exprt
The trinary if-then-else operator.
Definition: std_expr.h:2322
arrayst::collect_arrays
void collect_arrays(const exprt &a)
Definition: arrays.cpp:129
and_exprt
Boolean AND.
Definition: std_expr.h:2070
to_array_of_expr
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition: std_expr.h:1543
exprt
Base class for all expressions.
Definition: expr.h:55
decision_proceduret::set_to_true
void set_to_true(const exprt &expr)
For a Boolean expression expr, add the constraint 'expr'.
Definition: decision_procedure.cpp:23
array_of_exprt::type
const array_typet & type() const
Definition: std_expr.h:1505
array_comprehension_exprt::arg
const symbol_exprt & arg() const
Definition: std_expr.h:3375
propt::l_set_to_true
void l_set_to_true(literalt a)
Definition: prop.h:50
arrayst::collect_indices
void collect_indices()
Definition: arrays.cpp:82
to_string
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
Definition: string_constraint.cpp:58
arrayst::array_equalityt::l
literalt l
Definition: arrays.h:67
arrayst::update_indices
std::set< std::size_t > update_indices
Definition: arrays.h:159
jsont::make_object
json_objectt & make_object()
Definition: json.h:438
arrayst::array_constraint_count
array_constraint_countt array_constraint_count
Definition: arrays.h:131
equal_exprt
Equality.
Definition: std_expr.h:1305
arrayst::constraint_typet::ARRAY_ACKERMANN
@ ARRAY_ACKERMANN
arrayst::lazy_typet::ARRAY_IF
@ ARRAY_IF
if_exprt::false_case
exprt & false_case()
Definition: std_expr.h:2360
json_objectt
Definition: json.h:299
arrayst::constraint_typet::ARRAY_OF
@ ARRAY_OF
namespacet
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition: namespace.h:90
union_find::number
size_type number(const T &a)
Definition: union_find.h:235
exprt::type
typet & type()
Return the type of the expression.
Definition: expr.h:84
array_exprt::type
const array_typet & type() const
Definition: std_expr.h:1570
with_exprt::old
exprt & old()
Definition: std_expr.h:2434
arrayst::add_array_constraints_with
void add_array_constraints_with(const index_sett &index_set, const with_exprt &expr)
Definition: arrays.cpp:542
disjunction
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition: std_expr.cpp:50
arrayst::incremental_cache
bool incremental_cache
Definition: arrays.h:112
arrayst::lazy_typet::ARRAY_OF
@ ARRAY_OF
union_find::find_number
size_type find_number(const_iterator it) const
Definition: union_find.h:201
DATA_INVARIANT_WITH_DIAGNOSTICS
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition: invariant.h:511
or_exprt
Boolean OR.
Definition: std_expr.h:2178
union_find::make_union
bool make_union(const T &a, const T &b)
Definition: union_find.h:155
arrayst::add_array_constraints
void add_array_constraints()
Definition: arrays.cpp:275
arrayst::lazy_array_constraints
std::list< lazy_constraintt > lazy_array_constraints
Definition: arrays.h:114
DATA_INVARIANT
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition: invariant.h:510
get_identifier
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)
Definition: smt2_incremental_decision_procedure.cpp:328
forall_operands
#define forall_operands(it, expr)
Definition: expr.h:20
member_exprt::struct_op
const exprt & struct_op() const
Definition: std_expr.h:2832
binary_predicate_exprt
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition: std_expr.h:675
symbol_exprt::get_identifier
const irep_idt & get_identifier() const
Definition: std_expr.h:142
lazy
auto lazy(funt fun) -> lazyt< decltype(fun())>
Delay the computation of fun to the next time the force method is called.
Definition: lazy.h:49
literal_exprt
Definition: literal_expr.h:17
array_of_exprt
Array constructor from single element.
Definition: std_expr.h:1497
arrayst::array_equalities
array_equalitiest array_equalities
Definition: arrays.h:75
irept::id_string
const std::string & id_string() const
Definition: irep.h:399
array_comprehension_exprt::body
const exprt & body() const
Definition: std_expr.h:3389
prop.h
const_literal
literalt const_literal(bool value)
Definition: literal.h:188
arrayst::is_unbounded_array
virtual bool is_unbounded_array(const typet &type) const =0
arrayst::index_sett
std::set< exprt > index_sett
Definition: arrays.h:81
index_exprt::index
exprt & index()
Definition: std_expr.h:1450
arrayst::lazy_typet::ARRAY_WITH
@ ARRAY_WITH
index_exprt::array
exprt & array()
Definition: std_expr.h:1440
arrayst::expr_map
std::map< exprt, bool > expr_map
Definition: arrays.h:116
to_symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition: std_expr.h:222
union_find::is_root_number
bool is_root_number(size_type a) const
Definition: union_find.h:216
irept::id
const irep_idt & id() const
Definition: irep.h:396
message_handlert
Definition: message.h:27
exprt::operandst
std::vector< exprt > operandst
Definition: expr.h:58
arrayst::record_array_index
void record_array_index(const index_exprt &expr)
Definition: arrays.cpp:44
equalityt
Definition: equality.h:19
arrayst::constraint_typet::ARRAY_CONSTANT
@ ARRAY_CONSTANT
unary_exprt::op
const exprt & op() const
Definition: std_expr.h:326
optionalt
nonstd::optional< T > optionalt
Definition: optional.h:35
arrayst::add_array_Ackermann_constraints
void add_array_Ackermann_constraints()
Definition: arrays.cpp:325
arrayst::array_equalityt::f2
exprt f2
Definition: arrays.h:68
prop_conv_solvert::convert
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
Definition: prop_conv_solver.cpp:156
arrayst::lazy_typet::ARRAY_TYPECAST
@ ARRAY_TYPECAST
to_with_expr
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition: std_expr.h:2486
update_exprt
Operator to update elements in structs and arrays.
Definition: std_expr.h:2607
arrayst::display_array_constraint_count
void display_array_constraint_count()
Definition: arrays.cpp:885
irep_pretty_diagnosticst
Definition: irep.h:502
arrayst::add_array_constraints_update
void add_array_constraints_update(const index_sett &index_set, const update_exprt &expr)
Definition: arrays.cpp:621
format_expr.h
arrays.h
propt
TO_BE_DOCUMENTED.
Definition: prop.h:22
union_find::size
size_t size() const
Definition: union_find.h:268
arrayst::array_equalityt
Definition: arrays.h:65
array_typet
Arrays with given size.
Definition: std_types.h:762
if_exprt::true_case
exprt & true_case()
Definition: std_expr.h:2350
replace_expr
bool replace_expr(const exprt &what, const exprt &by, exprt &dest)
Definition: replace_expr.cpp:12
from_integer
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Definition: arith_tools.cpp:100
arrayst::add_array_constraints_comprehension
void add_array_constraints_comprehension(const index_sett &index_set, const array_comprehension_exprt &expr)
Definition: arrays.cpp:784
to_typecast_expr
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition: std_expr.h:2051
arrayst::lazy_typet::ARRAY_CONSTANT
@ ARRAY_CONSTANT
if_exprt::cond
exprt & cond()
Definition: std_expr.h:2340
literalt
Definition: literal.h:25
to_array_type
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition: std_types.h:844
json.h
arrayst::add_array_constraints_array_constant
void add_array_constraints_array_constant(const index_sett &index_set, const array_exprt &exprt)
Definition: arrays.cpp:703
arrayst::add_array_constraints_array_of
void add_array_constraints_array_of(const index_sett &index_set, const array_of_exprt &exprt)
Definition: arrays.cpp:678
to_member_expr
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition: std_expr.h:2886
arrayst::update_index_map
void update_index_map(bool update_all)
Definition: arrays.cpp:402
implies_exprt
Boolean implication.
Definition: std_expr.h:2133
replace_expr.h
exprt::operands
operandst & operands()
Definition: expr.h:94
arrayst::arrays
union_find< exprt, irep_hash > arrays
Definition: arrays.h:78
arrayst::lazy_typet::ARRAY_ACKERMANN
@ ARRAY_ACKERMANN
index_exprt
Array index operator.
Definition: std_expr.h:1409
arrayst::lazy_arrays
bool lazy_arrays
Definition: arrays.h:111
array_comprehension_exprt
Expression to define a mapping from an argument (index) to elements.
Definition: std_expr.h:3350
arrayst::constraint_typet::ARRAY_EQUALITY
@ ARRAY_EQUALITY
message.h
arrayst::add_array_constraint
void add_array_constraint(const lazy_constraintt &lazy, bool refine=true)
adds array constraints (refine=true...lazily for the refinement loop)
Definition: arrays.cpp:250
arrayst::get_array_constraints
bool get_array_constraints
Definition: arrays.h:113
arrayst::lazy_typet::ARRAY_COMPREHENSION
@ ARRAY_COMPREHENSION
std_expr.h
arrayst::constraint_typet::ARRAY_TYPECAST
@ ARRAY_TYPECAST
array_exprt
Array constructor from list of elements.
Definition: std_expr.h:1562
arrayst::add_array_constraints_equality
void add_array_constraints_equality(const index_sett &index_set, const array_equalityt &array_equality)
Definition: arrays.cpp:436
arrayst::arrayst
arrayst(const namespacet &_ns, propt &_prop, message_handlert &message_handler, bool get_array_constraints=false)
Definition: arrays.cpp:28
propt::lcnf
void lcnf(literalt l0, literalt l1)
Definition: prop.h:56
literal_expr.h
equalityt::equality
virtual literalt equality(const exprt &e1, const exprt &e2)
Definition: equality.cpp:17
validation_modet::INVARIANT
@ INVARIANT
arrayst::enum_to_string
std::string enum_to_string(constraint_typet)
Definition: arrays.cpp:860
prop_conv_solvert::prop
propt & prop
Definition: prop_conv_solver.h:130
array_typet::element_type
const typet & element_type() const
The type of the elements of the array.
Definition: std_types.h:785
to_constant_expr
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition: std_expr.h:2992
arrayst::add_array_constraints_if
void add_array_constraints_if(const index_sett &index_set, const if_exprt &exprt)
Definition: arrays.cpp:808