CBMC
Loading...
Searching...
No Matches
arrays.cpp
Go to the documentation of this file.
1/*******************************************************************\
2
3Module:
4
5Author: 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/replace_symbol.h>
16#include <util/std_expr.h>
17
19#include <solvers/prop/prop.h>
20
21#ifdef DEBUG
22# include <util/format_expr.h>
23
24# include <iostream>
25#endif
26
27#include <unordered_set>
28
30 const namespacet &_ns,
31 propt &_prop,
35 ns(_ns),
37 message_handler(_message_handler)
38{
39 lazy_arrays = false; // will be set to true when --refine is used
40 incremental_cache = false; // for incremental solving
41 // get_array_constraints is true when --show-array-constraints is used
43}
44
46{
47 // we are not allowed to put the index directly in the
48 // entry for the root of the equivalence class
49 // because this map is accessed during building the error trace
50 std::size_t number=arrays.number(index.array());
51 if(index_map[number].insert(index.index()).second)
52 update_indices.insert(number);
53}
54
56 const equal_exprt &equality)
57{
58 const exprt &op0=equality.op0();
59 const exprt &op1=equality.op1();
60
62 op0.type() == op1.type(),
63 "record_array_equality got equality without matching types",
64 irep_pretty_diagnosticst{equality});
65
67 op0.type().id() == ID_array,
68 "record_array_equality parameter should be array-typed");
69
71
72 array_equalities.back().f1=op0;
73 array_equalities.back().f2=op1;
74 array_equalities.back().l=SUB::equality(op0, op1);
75
76 arrays.make_union(op0, op1);
77 collect_arrays(op0);
78 collect_arrays(op1);
79
80 return array_equalities.back().l;
81}
82
84 const symbol_exprt &symbol,
85 const exprt &value)
86{
88 symbol.type().id() == ID_array,
89 "record_array_let_binding parameter should be array-typed");
90
91 const equal_exprt eq{symbol, value};
94}
95
97{
98 for(std::size_t i=0; i<arrays.size(); i++)
99 {
101 }
102}
103
105{
106 if(expr.id()!=ID_index)
107 {
108 if(expr.id() == ID_array_comprehension)
110 to_array_comprehension_expr(expr).arg().identifier());
111
112 for(const auto &op : expr.operands())
113 collect_indices(op);
114 }
115 else
116 {
117 const index_exprt &e = to_index_expr(expr);
118
119 if(
120 e.index().id() == ID_symbol &&
121 array_comprehension_args.count(to_symbol_expr(e.index()).identifier()) !=
122 0)
123 {
124 return;
125 }
126
127 collect_indices(e.index()); // necessary?
128
129 const typet &array_op_type = e.array().type();
130
131 if(array_op_type.id()==ID_array)
132 {
133 const array_typet &array_type=
135
137 {
139 }
140 }
141 }
142}
143
145{
146 const array_typet &array_type = to_array_type(a.type());
147
148 if(a.id()==ID_with)
149 {
151
153 array_type == with_expr.old().type(),
154 "collect_arrays got 'with' without matching types",
156
159
160 // make sure this shows as an application
163 }
164 else if(a.id()==ID_update)
165 {
167
169 array_type == update_expr.old().type(),
170 "collect_arrays got 'update' without matching types",
172
175
176#if 0
177 // make sure this shows as an application
180#endif
181 }
182 else if(a.id()==ID_if)
183 {
185
187 array_type == if_expr.true_case().type(),
188 "collect_arrays got if without matching types",
190
192 array_type == if_expr.false_case().type(),
193 "collect_arrays got if without matching types",
195
196 arrays.make_union(a, if_expr.true_case());
197 arrays.make_union(a, if_expr.false_case());
198 collect_arrays(if_expr.true_case());
199 collect_arrays(if_expr.false_case());
200 }
201 else if(a.id()==ID_symbol)
202 {
203 }
204 else if(a.id()==ID_nondet_symbol)
205 {
206 }
207 else if(a.id()==ID_member)
208 {
209 const auto &struct_op = to_member_expr(a).struct_op();
210
212 struct_op.id() == ID_symbol || struct_op.id() == ID_nondet_symbol,
213 "unexpected array expression: member with '" + struct_op.id_string() +
214 "'");
215 }
216 else if(a.is_constant() || a.id() == ID_array || a.id() == ID_string_constant)
217 {
218 }
219 else if(a.id()==ID_array_of)
220 {
221 }
222 else if(a.id()==ID_byte_update_little_endian ||
224 {
226 false,
227 "byte_update should be removed before collect_arrays");
228 }
229 else if(a.id()==ID_typecast)
230 {
231 const auto &typecast_op = to_typecast_expr(a).op();
232
233 // cast between array types?
235 typecast_op.type().id() == ID_array,
236 "unexpected array type cast from " + typecast_op.type().id_string());
237
240 }
241 else if(a.id()==ID_index)
242 {
243 // nested unbounded arrays
244 const auto &array_op = to_index_expr(a).array();
247 }
248 else if(a.id() == ID_array_comprehension)
249 {
250 }
252 {
253 arrays.make_union(a, let_expr->where());
254 collect_arrays(let_expr->where());
255 }
256 else
257 {
259 false,
260 "unexpected array expression (collect_arrays): '" + a.id_string() + "'");
261 }
262}
263
266{
267 if(lazy_arrays && refine)
268 {
269 // lazily add the constraint
271 {
272 if(expr_map.find(lazy.lazy) == expr_map.end())
273 {
274 lazy_array_constraints.push_back(lazy);
275 expr_map[lazy.lazy] = true;
276 }
277 }
278 else
279 {
280 lazy_array_constraints.push_back(lazy);
281 }
282 }
283 else
284 {
285 // add the constraint eagerly
287 }
288}
289
291{
293 // at this point all indices should in the index set
294
295 // reduce initial index map
296 update_index_map(true);
297
298 // add constraints for if, with, array_of, lambda
299 std::set<std::size_t> roots_to_process, updated_roots;
300 for(std::size_t i=0; i<arrays.size(); i++)
302
303 while(!roots_to_process.empty())
304 {
305 for(std::size_t i = 0; i < arrays.size(); i++)
306 {
307 if(roots_to_process.count(arrays.find_number(i)) == 0)
308 continue;
309
310 // take a copy as arrays may get modified by add_array_constraints
311 // in case of nested unbounded arrays
312 exprt a = arrays[i];
313
315
316 // we have to update before it gets used in the next add_* call
317 for(const std::size_t u : update_indices)
319 update_index_map(false);
320 }
321
322 roots_to_process = std::move(updated_roots);
324 }
325
326 // add constraints for equalities
327 for(const auto &equality : array_equalities)
328 {
331 equality);
332
333 // update_index_map should not be necessary here
334 }
335
336 // add the Ackermann constraints
338}
339
341{
342 // this is quadratic!
343
344#ifdef DEBUG
345 std::cout << "arrays.size(): " << arrays.size() << '\n';
346#endif
347
348 // iterate over arrays
349 for(std::size_t i=0; i<arrays.size(); i++)
350 {
352
353#ifdef DEBUG
354 std::cout << "index_set.size(): " << index_set.size() << '\n';
355#endif
356
357 // iterate over indices, 2x!
358 for(index_sett::const_iterator
359 i1=index_set.begin();
360 i1!=index_set.end();
361 i1++)
362 for(index_sett::const_iterator
363 i2=i1;
364 i2!=index_set.end();
365 i2++)
366 if(i1!=i2)
367 {
368 if(i1->is_constant() && i2->is_constant())
369 continue;
370
371 // index equality
374
376
378 {
379 const typet &subtype =
380 to_array_type(arrays[i].type()).element_type();
381 index_exprt index_expr1(arrays[i], *i1, subtype);
382
384 index_expr2.index()=*i2;
385
387
388 // add constraint
391 add_array_constraint(lazy, true); // added lazily
393
394#if 0 // old code for adding, not significantly faster
396#endif
397 }
398 }
399 }
400}
401
403void arrayst::update_index_map(std::size_t i)
404{
406 return;
407
408 std::size_t root_number=arrays.find_number(i);
409 INVARIANT(root_number!=i, "is_root_number incorrect?");
410
413
414 root_index_set.insert(index_set.begin(), index_set.end());
415}
416
418{
419 // iterate over non-roots
420 // possible reasons why update is needed:
421 // -- there are new equivalence classes in arrays
422 // -- there are new indices for arrays that are not the root
423 // of an equivalence class
424 // (and we cannot do that in record_array_index())
425 // -- equivalence classes have been merged
426 if(update_all)
427 {
428 for(std::size_t i=0; i<arrays.size(); i++)
430 }
431 else
432 {
433 for(const auto &index : update_indices)
434 update_index_map(index);
435
437 }
438
439#ifdef DEBUG
440 // print index sets
441 for(const auto &index_entry : index_map)
442 for(const auto &index : index_entry.second)
443 std::cout << "Index set (" << index_entry.first << " = "
444 << arrays.find_number(index_entry.first) << " = "
446 << "): " << format(index) << '\n';
447 std::cout << "-----\n";
448#endif
449}
450
452 const index_sett &index_set,
454{
455 // add constraints x=y => x[i]=y[i]
456
457 for(const auto &index : index_set)
458 {
459 const typet &element_type1 =
460 to_array_type(array_equality.f1.type()).element_type();
462
463 const typet &element_type2 =
464 to_array_type(array_equality.f2.type()).element_type();
466
468 index_expr1.type()==index_expr2.type(),
469 "array elements should all have same type");
470
471 array_equalityt equal;
472 equal.f1 = index_expr1;
473 equal.f2 = index_expr2;
474 equal.l = array_equality.l;
476
477 // add constraint
478 // equality constraints are not added lazily
479 // convert must be done to guarantee correct update of the index_set
482 }
483}
484
486 const index_sett &index_set,
487 const exprt &expr)
488{
489 if(expr.id()==ID_with)
491 else if(expr.id()==ID_update)
493 else if(expr.id()==ID_if)
495 else if(expr.id()==ID_array_of)
497 else if(expr.id() == ID_array)
499 else if(expr.id() == ID_array_comprehension)
500 {
503 }
504 else if(
505 expr.id() == ID_symbol || expr.id() == ID_nondet_symbol ||
506 expr.is_constant() || expr.id() == "zero_string" ||
507 expr.id() == ID_string_constant)
508 {
509 }
510 else if(
511 expr.id() == ID_member &&
512 (to_member_expr(expr).struct_op().id() == ID_symbol ||
513 to_member_expr(expr).struct_op().id() == ID_nondet_symbol))
514 {
515 }
516 else if(expr.id()==ID_byte_update_little_endian ||
518 {
519 INVARIANT(false, "byte_update should be removed before arrayst");
520 }
521 else if(expr.id()==ID_typecast)
522 {
523 // we got a=(type[])b
524 const auto &expr_typecast_op = to_typecast_expr(expr).op();
525
526 // add a[i]=b[i]
527 for(const auto &index : index_set)
528 {
529 const typet &element_type = to_array_type(expr.type()).element_type();
530 index_exprt index_expr1(expr, index, element_type);
531 index_exprt index_expr2(expr_typecast_op, index, element_type);
532
534 index_expr1.type()==index_expr2.type(),
535 "array elements should all have same type");
536
537 // add constraint
540 add_array_constraint(lazy, false); // added immediately
542 }
543 }
544 else if(expr.id()==ID_index)
545 {
546 }
547 else if(auto let_expr = expr_try_dynamic_cast<let_exprt>(expr))
548 {
549 // we got x=let(a=e, A)
550 // add x[i]=A[a/e][i]
551
552 exprt where = let_expr->where();
553 replace_symbolt replace_symbol;
554 for(const auto &binding :
555 make_range(let_expr->variables()).zip(let_expr->values()))
556 {
557 replace_symbol.insert(binding.first, binding.second);
558 }
559 replace_symbol(where);
560
561 for(const auto &index : index_set)
562 {
563 index_exprt index_expr{expr, index};
564 index_exprt where_indexed{where, index};
565
566 // add constraint
569
570 add_array_constraint(lazy, false); // added immediately
572 }
573 }
574 else
575 {
577 false,
578 "unexpected array expression (add_array_constraints): '" +
579 expr.id_string() + "'");
580 }
581}
582
584 const index_sett &index_set,
585 const with_exprt &expr)
586{
587 // We got x=(y with [i:=v]).
588 // First add constraint x[i]=v
589 std::unordered_set<exprt, irep_hash> updated_indices;
590
592 expr, expr.where(), to_array_type(expr.type()).element_type());
593
595 index_expr.type() == expr.new_value().type(),
596 "with-expression operand should match array element type",
598
601 add_array_constraint(lazy, false); // added immediately
603
604 updated_indices.insert(expr.where());
605
606 // For all other indices use the existing value, i.e., add constraints
607 // x[I]=y[I] for I!=i,j,...
608
609 for(auto other_index : index_set)
610 {
612 {
613 // we first build the guard
615 disjuncts.reserve(updated_indices.size());
616 for(const auto &index : updated_indices)
617 {
618 disjuncts.push_back(equal_exprt{
619 index, typecast_exprt::conditional_cast(other_index, index.type())});
620 }
621
623
624 if(guard_lit!=const_literal(true))
625 {
626 const typet &element_type = to_array_type(expr.type()).element_type();
627 index_exprt index_expr1(expr, other_index, element_type);
628 index_exprt index_expr2(expr.old(), other_index, element_type);
629
631
632 // add constraint
635
636 add_array_constraint(lazy, false); // added immediately
638
639#if 0 // old code for adding, not significantly faster
640 {
642
643 bvt bv;
644 bv.reserve(2);
645 bv.push_back(equality_lit);
646 bv.push_back(guard_lit);
647 prop.lcnf(bv);
648 }
649#endif
650 }
651 }
652 }
653}
654
656 const index_sett &,
657 const update_exprt &)
658{
659 // we got x=UPDATE(y, [i], v)
660 // add constaint x[i]=v
661
662#if 0
663 const exprt &index=expr.where();
664 const exprt &value=expr.new_value();
665
666 {
667 index_exprt index_expr(expr, index, expr.type().subtype());
668
670 index_expr.type()==value.type(),
671 "update operand should match array element type",
673
675 }
676
677 // use other array index applications for "else" case
678 // add constraint x[I]=y[I] for I!=i
679
680 for(auto other_index : index_set)
681 {
682 if(other_index!=index)
683 {
684 // we first build the guard
685
687
689
690 if(guard_lit!=const_literal(true))
691 {
692 const typet &subtype=expr.type().subtype();
693 index_exprt index_expr1(expr, other_index, subtype);
694 index_exprt index_expr2(expr.op0(), other_index, subtype);
695
697
699
700 // add constraint
701 bvt bv;
702 bv.reserve(2);
703 bv.push_back(equality_lit);
704 bv.push_back(guard_lit);
705 prop.lcnf(bv);
706 }
707 }
708 }
709#endif
710}
711
713 const index_sett &index_set,
714 const array_of_exprt &expr)
715{
716 // we got x=array_of[v]
717 // get other array index applications
718 // and add constraint x[i]=v
719
720 for(const auto &index : index_set)
721 {
722 const typet &element_type = expr.type().element_type();
723 index_exprt index_expr(expr, index, element_type);
724
726 index_expr.type() == expr.what().type(),
727 "array_of operand type should match array element type");
728
729 // add constraint
732 add_array_constraint(lazy, false); // added immediately
734 }
735}
736
738 const index_sett &index_set,
739 const array_exprt &expr)
740{
741 // we got x = { v, ... } - add constraint x[i] = v
742 const exprt::operandst &operands = expr.operands();
743
744 for(const auto &index : index_set)
745 {
746 const typet &element_type = expr.type().element_type();
747 const index_exprt index_expr{expr, index, element_type};
748
749 if(index.is_constant())
750 {
751 // We have a constant index - just pick the element at that index from the
752 // array constant.
753
754 const std::optional<std::size_t> i =
756 // if the access is out of bounds, we leave it unconstrained
757 if(!i.has_value() || *i >= operands.size())
758 continue;
759
760 const exprt v = operands[*i];
762 index_expr.type() == v.type(),
763 "array operand type should match array element type");
764
765 // add constraint
768 add_array_constraint(lazy, false); // added immediately
770 }
771 else
772 {
773 // We have a non-constant index into an array constant. We need to build a
774 // case statement testing the index against all possible values. Whenever
775 // neighbouring array elements are the same, we can test the index against
776 // the range rather than individual elements. This should be particularly
777 // helpful when we have arrays of zeros, as is the case for initializers.
778
779 std::vector<std::pair<std::size_t, std::size_t>> ranges;
780
781 for(std::size_t i = 0; i < operands.size(); ++i)
782 {
783 if(ranges.empty() || operands[i] != operands[ranges.back().first])
784 ranges.emplace_back(i, i);
785 else
786 ranges.back().second = i;
787 }
788
789 for(const auto &range : ranges)
790 {
792
793 if(range.first == range.second)
794 {
796 equal_exprt{index, from_integer(range.first, index.type())};
797 }
798 else
799 {
802 from_integer(range.first, index.type()), ID_le, index},
804 index, ID_le, from_integer(range.second, index.type())}};
805 }
806
810 equal_exprt{index_expr, operands[range.first]}}};
811 add_array_constraint(lazy, true); // added lazily
813 }
814 }
815 }
816}
817
819 const index_sett &index_set,
820 const array_comprehension_exprt &expr)
821{
822 // we got x=lambda(i: e)
823 // get all other array index applications
824 // and add constraints x[j]=e[i/j]
825
826 for(const auto &index : index_set)
827 {
828 index_exprt index_expr{expr, index};
830 replace_expr(expr.arg(), index, comprehension_body);
831
832 // add constraint
836
837 add_array_constraint(lazy, false); // added immediately
839 }
840}
841
843 const index_sett &index_set,
844 const if_exprt &expr)
845{
846 // we got x=(c?a:b)
848
849 // get other array index applications
850 // and add c => x[i]=a[i]
851 // !c => x[i]=b[i]
852
853 // first do true case
854
855 for(const auto &index : index_set)
856 {
857 const typet &element_type = to_array_type(expr.type()).element_type();
858 index_exprt index_expr1(expr, index, element_type);
859 index_exprt index_expr2(expr.true_case(), index, element_type);
860
861 // add implication
865 add_array_constraint(lazy, false); // added immediately
867
868#if 0 // old code for adding, not significantly faster
870#endif
871 }
872
873 // now the false case
874 for(const auto &index : index_set)
875 {
876 const typet &element_type = to_array_type(expr.type()).element_type();
877 index_exprt index_expr1(expr, index, element_type);
878 index_exprt index_expr2(expr.false_case(), index, element_type);
879
880 // add implication
885 add_array_constraint(lazy, false); // added immediately
887
888#if 0 // old code for adding, not significantly faster
890#endif
891 }
892}
893
895{
896 switch(type)
897 {
899 return "arrayAckermann";
901 return "arrayWith";
903 return "arrayIf";
905 return "arrayOf";
907 return "arrayTypecast";
909 return "arrayConstant";
911 return "arrayComprehension";
913 return "arrayEquality";
915 return "arrayLet";
916 default:
918 }
919}
920
922{
925 json_result["arrayConstraints"].make_object();
926
927 size_t num_constraints = 0;
928
929 array_constraint_countt::iterator it = array_constraint_count.begin();
930 while(it != array_constraint_count.end())
931 {
932 std::string contraint_type_string = enum_to_string(it->first);
934 json_numbert(std::to_string(it->second));
935
936 num_constraints += it->second;
937 it++;
938 }
939
940 json_result["numOfConstraints"] =
941 json_numbert(std::to_string(num_constraints));
942 log.status() << ",\n" << json_result;
943}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
Theory of Arrays with Extensionality.
virtual void clear()
Reset the abstract state.
Definition ai.h:269
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:566
Boolean AND All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2043
Expression to define a mapping from an argument (index) to elements.
Definition std_expr.h:3586
const symbol_exprt & arg() const
Definition std_expr.h:3610
const exprt & body() const
Definition std_expr.h:3624
Array constructor from list of elements.
Definition std_expr.h:1570
const array_typet & type() const
Definition std_expr.h:1577
Array constructor from single element.
Definition std_expr.h:1512
const array_typet & type() const
Definition std_expr.h:1519
exprt & what()
Definition std_expr.h:1529
Arrays with given size.
Definition std_types.h:807
std::list< lazy_constraintt > lazy_array_constraints
Definition arrays.h:122
std::unordered_set< irep_idt > array_comprehension_args
Definition arrays.h:172
index_mapt index_map
Definition arrays.h:92
void add_array_constraints_equality(const index_sett &index_set, const array_equalityt &array_equality)
Definition arrays.cpp:451
std::set< std::size_t > update_indices
Definition arrays.h:168
void add_array_constraints_array_of(const index_sett &index_set, const array_of_exprt &exprt)
Definition arrays.cpp:712
void add_array_Ackermann_constraints()
Definition arrays.cpp:340
bool lazy_arrays
Definition arrays.h:119
void collect_indices()
Definition arrays.cpp:96
void add_array_constraints_update(const index_sett &index_set, const update_exprt &expr)
Definition arrays.cpp:655
void collect_arrays(const exprt &a)
Definition arrays.cpp:144
void record_array_let_binding(const symbol_exprt &symbol, const exprt &value)
Record that symbol is equal to value for the purposes of the array theory.
Definition arrays.cpp:83
union_find< exprt, irep_hash > arrays
Definition arrays.h:85
literalt record_array_equality(const equal_exprt &expr)
Definition arrays.cpp:55
void add_array_constraints_array_constant(const index_sett &index_set, const array_exprt &exprt)
Definition arrays.cpp:737
arrayst(const namespacet &_ns, propt &_prop, message_handlert &message_handler, bool get_array_constraints=false)
Definition arrays.cpp:29
constraint_typet
Definition arrays.h:127
std::map< exprt, bool > expr_map
Definition arrays.h:124
void add_array_constraints_if(const index_sett &index_set, const if_exprt &exprt)
Definition arrays.cpp:842
std::string enum_to_string(constraint_typet)
Definition arrays.cpp:894
bool get_array_constraints
Definition arrays.h:121
void add_array_constraints()
Definition arrays.cpp:290
void add_array_constraints_comprehension(const index_sett &index_set, const array_comprehension_exprt &expr)
Definition arrays.cpp:818
virtual bool is_unbounded_array(const typet &type) const =0
void record_array_index(const index_exprt &expr)
Definition arrays.cpp:45
array_equalitiest array_equalities
Definition arrays.h:82
std::set< exprt > index_sett
Definition arrays.h:88
void add_array_constraint(const lazy_constraintt &lazy, bool refine=true)
adds array constraints (refine=true...lazily for the refinement loop)
Definition arrays.cpp:265
array_constraint_countt array_constraint_count
Definition arrays.h:140
void add_array_constraints_with(const index_sett &index_set, const with_exprt &expr)
Definition arrays.cpp:583
bool incremental_cache
Definition arrays.h:120
void display_array_constraint_count()
Definition arrays.cpp:921
void update_index_map(bool update_all)
Definition arrays.cpp:417
messaget log
Definition arrays.h:64
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition std_expr.h:737
void set_to_true(const exprt &)
For a Boolean expression expr, add the constraint 'expr'.
Equality.
Definition std_expr.h:1339
virtual literalt equality(const exprt &e1, const exprt &e2)
Definition equality.cpp:17
Base class for all expressions.
Definition expr.h:57
std::vector< exprt > operandst
Definition expr.h:59
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:213
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
The trinary if-then-else operator.
Definition std_expr.h:2426
exprt & cond()
Definition std_expr.h:2443
exprt & false_case()
Definition std_expr.h:2463
exprt & true_case()
Definition std_expr.h:2453
Boolean implication.
Definition std_expr.h:2154
Array index operator.
Definition std_expr.h:1431
exprt & index()
Definition std_expr.h:1471
exprt & array()
Definition std_expr.h:1461
const std::string & id_string() const
Definition irep.h:391
const irep_idt & id() const
Definition irep.h:388
mstreamt & status() const
Definition message.h:406
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Boolean OR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2193
literalt convert(const exprt &expr) override
Convert a Boolean expression and return the corresponding literal.
TO_BE_DOCUMENTED.
Definition prop.h:25
void l_set_to_true(literalt a)
Definition prop.h:52
void lcnf(literalt l0, literalt l1)
Definition prop.h:58
Replace a symbol expression by a given expression.
void insert(const class symbol_exprt &old_expr, const exprt &new_expr)
Sets old_expr to be replaced by new_expr if we don't already have a replacement; otherwise does nothi...
Expression to hold a symbol (variable)
Definition std_expr.h:132
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2003
The type of an expression, extends irept.
Definition type.h:29
size_type number(const T &a)
Definition union_find.h:235
bool make_union(const T &a, const T &b)
Definition union_find.h:155
size_t size() const
Definition union_find.h:268
size_type find_number(const_iterator it) const
Definition union_find.h:201
bool is_root_number(size_type a) const
Definition union_find.h:216
Operator to update elements in structs and arrays.
Definition std_expr.h:2679
Operator to update elements in structs and arrays.
Definition std_expr.h:2520
exprt & new_value()
Definition std_expr.h:2550
exprt & where()
Definition std_expr.h:2540
exprt & old()
Definition std_expr.h:2530
static format_containert< T > format(const T &o)
Definition format.h:37
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
std::vector< literalt > bvt
Definition literal.h:201
literalt const_literal(bool value)
Definition literal.h:188
double log(double x)
Definition math.c:2416
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
bool replace_expr(const exprt &what, const exprt &by, exprt &dest)
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define DATA_INVARIANT(CONDITION, REASON)
This condition should be used to document that assumptions that are made on goto_functions,...
Definition invariant.h:534
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define DATA_INVARIANT_WITH_DIAGNOSTICS(CONDITION, REASON,...)
Definition invariant.h:535
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:240
API to expression classes.
const array_of_exprt & to_array_of_expr(const exprt &expr)
Cast an exprt to an array_of_exprt.
Definition std_expr.h:1552
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1494
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
Definition std_expr.h:3648
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition std_expr.h:1614
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2024
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2501
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:2953
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3078
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:221
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2573
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition std_expr.h:2762
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888