CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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{
85 for(std::size_t i=0; i<arrays.size(); i++)
86 {
88 }
89}
90
92{
93 if(expr.id()!=ID_index)
94 {
95 if(expr.id() == ID_array_comprehension)
97 to_array_comprehension_expr(expr).arg().get_identifier());
98
99 for(const auto &op : expr.operands())
100 collect_indices(op);
101 }
102 else
103 {
104 const index_exprt &e = to_index_expr(expr);
105
106 if(
107 e.index().id() == ID_symbol &&
109 to_symbol_expr(e.index()).get_identifier()) != 0)
110 {
111 return;
112 }
113
114 collect_indices(e.index()); // necessary?
115
116 const typet &array_op_type = e.array().type();
117
118 if(array_op_type.id()==ID_array)
119 {
120 const array_typet &array_type=
122
124 {
126 }
127 }
128 }
129}
130
132{
133 const array_typet &array_type = to_array_type(a.type());
134
135 if(a.id()==ID_with)
136 {
138
140 array_type == with_expr.old().type(),
141 "collect_arrays got 'with' without matching types",
143
146
147 // make sure this shows as an application
148 for(std::size_t i = 1; i < with_expr.operands().size(); i += 2)
149 {
150 index_exprt index_expr(with_expr.old(), with_expr.operands()[i]);
152 }
153 }
154 else if(a.id()==ID_update)
155 {
157
159 array_type == update_expr.old().type(),
160 "collect_arrays got 'update' without matching types",
162
165
166#if 0
167 // make sure this shows as an application
170#endif
171 }
172 else if(a.id()==ID_if)
173 {
175
177 array_type == if_expr.true_case().type(),
178 "collect_arrays got if without matching types",
180
182 array_type == if_expr.false_case().type(),
183 "collect_arrays got if without matching types",
185
186 arrays.make_union(a, if_expr.true_case());
187 arrays.make_union(a, if_expr.false_case());
188 collect_arrays(if_expr.true_case());
189 collect_arrays(if_expr.false_case());
190 }
191 else if(a.id()==ID_symbol)
192 {
193 }
194 else if(a.id()==ID_nondet_symbol)
195 {
196 }
197 else if(a.id()==ID_member)
198 {
199 const auto &struct_op = to_member_expr(a).struct_op();
200
202 struct_op.id() == ID_symbol || struct_op.id() == ID_nondet_symbol,
203 "unexpected array expression: member with '" + struct_op.id_string() +
204 "'");
205 }
206 else if(a.is_constant() || a.id() == ID_array || 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 ||
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
230 }
231 else if(a.id()==ID_index)
232 {
233 // nested unbounded arrays
234 const auto &array_op = to_index_expr(a).array();
237 }
238 else if(a.id() == ID_array_comprehension)
239 {
240 }
242 {
243 arrays.make_union(a, let_expr->where());
244 collect_arrays(let_expr->where());
245 }
246 else
247 {
249 false,
250 "unexpected array expression (collect_arrays): '" + a.id_string() + "'");
251 }
252}
253
256{
257 if(lazy_arrays && refine)
258 {
259 // lazily add the constraint
261 {
262 if(expr_map.find(lazy.lazy) == expr_map.end())
263 {
264 lazy_array_constraints.push_back(lazy);
265 expr_map[lazy.lazy] = true;
266 }
267 }
268 else
269 {
270 lazy_array_constraints.push_back(lazy);
271 }
272 }
273 else
274 {
275 // add the constraint eagerly
277 }
278}
279
281{
283 // at this point all indices should in the index set
284
285 // reduce initial index map
286 update_index_map(true);
287
288 // add constraints for if, with, array_of, lambda
289 std::set<std::size_t> roots_to_process, updated_roots;
290 for(std::size_t i=0; i<arrays.size(); i++)
292
293 while(!roots_to_process.empty())
294 {
295 for(std::size_t i = 0; i < arrays.size(); i++)
296 {
297 if(roots_to_process.count(arrays.find_number(i)) == 0)
298 continue;
299
300 // take a copy as arrays may get modified by add_array_constraints
301 // in case of nested unbounded arrays
302 exprt a = arrays[i];
303
305
306 // we have to update before it gets used in the next add_* call
307 for(const std::size_t u : update_indices)
309 update_index_map(false);
310 }
311
312 roots_to_process = std::move(updated_roots);
314 }
315
316 // add constraints for equalities
317 for(const auto &equality : array_equalities)
318 {
321 equality);
322
323 // update_index_map should not be necessary here
324 }
325
326 // add the Ackermann constraints
328}
329
331{
332 // this is quadratic!
333
334#ifdef DEBUG
335 std::cout << "arrays.size(): " << arrays.size() << '\n';
336#endif
337
338 // iterate over arrays
339 for(std::size_t i=0; i<arrays.size(); i++)
340 {
342
343#ifdef DEBUG
344 std::cout << "index_set.size(): " << index_set.size() << '\n';
345#endif
346
347 // iterate over indices, 2x!
348 for(index_sett::const_iterator
349 i1=index_set.begin();
350 i1!=index_set.end();
351 i1++)
352 for(index_sett::const_iterator
353 i2=i1;
354 i2!=index_set.end();
355 i2++)
356 if(i1!=i2)
357 {
358 if(i1->is_constant() && i2->is_constant())
359 continue;
360
361 // index equality
364
366
368 {
369 const typet &subtype =
370 to_array_type(arrays[i].type()).element_type();
371 index_exprt index_expr1(arrays[i], *i1, subtype);
372
374 index_expr2.index()=*i2;
375
377
378 // add constraint
381 add_array_constraint(lazy, true); // added lazily
383
384#if 0 // old code for adding, not significantly faster
386#endif
387 }
388 }
389 }
390}
391
393void arrayst::update_index_map(std::size_t i)
394{
396 return;
397
398 std::size_t root_number=arrays.find_number(i);
399 INVARIANT(root_number!=i, "is_root_number incorrect?");
400
403
404 root_index_set.insert(index_set.begin(), index_set.end());
405}
406
408{
409 // iterate over non-roots
410 // possible reasons why update is needed:
411 // -- there are new equivalence classes in arrays
412 // -- there are new indices for arrays that are not the root
413 // of an equivalence class
414 // (and we cannot do that in record_array_index())
415 // -- equivalence classes have been merged
416 if(update_all)
417 {
418 for(std::size_t i=0; i<arrays.size(); i++)
420 }
421 else
422 {
423 for(const auto &index : update_indices)
424 update_index_map(index);
425
427 }
428
429#ifdef DEBUG
430 // print index sets
431 for(const auto &index_entry : index_map)
432 for(const auto &index : index_entry.second)
433 std::cout << "Index set (" << index_entry.first << " = "
434 << arrays.find_number(index_entry.first) << " = "
436 << "): " << format(index) << '\n';
437 std::cout << "-----\n";
438#endif
439}
440
442 const index_sett &index_set,
444{
445 // add constraints x=y => x[i]=y[i]
446
447 for(const auto &index : index_set)
448 {
449 const typet &element_type1 =
450 to_array_type(array_equality.f1.type()).element_type();
452
453 const typet &element_type2 =
454 to_array_type(array_equality.f2.type()).element_type();
456
458 index_expr1.type()==index_expr2.type(),
459 "array elements should all have same type");
460
461 array_equalityt equal;
462 equal.f1 = index_expr1;
463 equal.f2 = index_expr2;
464 equal.l = array_equality.l;
466
467 // add constraint
468 // equality constraints are not added lazily
469 // convert must be done to guarantee correct update of the index_set
472 }
473}
474
476 const index_sett &index_set,
477 const exprt &expr)
478{
479 if(expr.id()==ID_with)
481 else if(expr.id()==ID_update)
483 else if(expr.id()==ID_if)
485 else if(expr.id()==ID_array_of)
487 else if(expr.id() == ID_array)
489 else if(expr.id() == ID_array_comprehension)
490 {
493 }
494 else if(
495 expr.id() == ID_symbol || expr.id() == ID_nondet_symbol ||
496 expr.is_constant() || expr.id() == "zero_string" ||
497 expr.id() == ID_string_constant)
498 {
499 }
500 else if(
501 expr.id() == ID_member &&
502 (to_member_expr(expr).struct_op().id() == ID_symbol ||
503 to_member_expr(expr).struct_op().id() == ID_nondet_symbol))
504 {
505 }
506 else if(expr.id()==ID_byte_update_little_endian ||
508 {
509 INVARIANT(false, "byte_update should be removed before arrayst");
510 }
511 else if(expr.id()==ID_typecast)
512 {
513 // we got a=(type[])b
514 const auto &expr_typecast_op = to_typecast_expr(expr).op();
515
516 // add a[i]=b[i]
517 for(const auto &index : index_set)
518 {
519 const typet &element_type = to_array_type(expr.type()).element_type();
520 index_exprt index_expr1(expr, index, element_type);
521 index_exprt index_expr2(expr_typecast_op, index, element_type);
522
524 index_expr1.type()==index_expr2.type(),
525 "array elements should all have same type");
526
527 // add constraint
530 add_array_constraint(lazy, false); // added immediately
532 }
533 }
534 else if(expr.id()==ID_index)
535 {
536 }
537 else if(auto let_expr = expr_try_dynamic_cast<let_exprt>(expr))
538 {
539 // we got x=let(a=e, A)
540 // add x[i]=A[a/e][i]
541
542 exprt where = let_expr->where();
543 replace_symbolt replace_symbol;
544 for(const auto &binding :
545 make_range(let_expr->variables()).zip(let_expr->values()))
546 {
547 replace_symbol.insert(binding.first, binding.second);
548 }
549 replace_symbol(where);
550
551 for(const auto &index : index_set)
552 {
553 index_exprt index_expr{expr, index};
554 index_exprt where_indexed{where, index};
555
556 // add constraint
559
560 add_array_constraint(lazy, false); // added immediately
562 }
563 }
564 else
565 {
567 false,
568 "unexpected array expression (add_array_constraints): '" +
569 expr.id_string() + "'");
570 }
571}
572
574 const index_sett &index_set,
575 const with_exprt &expr)
576{
577 // We got x=(y with [i:=v, j:=w, ...]).
578 // First add constraints x[i]=v, x[j]=w, ...
579 std::unordered_set<exprt, irep_hash> updated_indices;
580
581 const exprt::operandst &operands = expr.operands();
582 for(std::size_t i = 1; i + 1 < operands.size(); i += 2)
583 {
584 const exprt &index = operands[i];
585 const exprt &value = operands[i + 1];
586
588 expr, index, to_array_type(expr.type()).element_type());
589
591 index_expr.type() == value.type(),
592 "with-expression operand should match array element type",
594
597 add_array_constraint(lazy, false); // added immediately
599
600 updated_indices.insert(index);
601 }
602
603 // For all other indices use the existing value, i.e., add constraints
604 // x[I]=y[I] for I!=i,j,...
605
606 for(auto other_index : index_set)
607 {
609 {
610 // we first build the guard
612 disjuncts.reserve(updated_indices.size());
613 for(const auto &index : updated_indices)
614 {
615 disjuncts.push_back(equal_exprt{
616 index, typecast_exprt::conditional_cast(other_index, index.type())});
617 }
618
620
621 if(guard_lit!=const_literal(true))
622 {
623 const typet &element_type = to_array_type(expr.type()).element_type();
624 index_exprt index_expr1(expr, other_index, element_type);
625 index_exprt index_expr2(expr.old(), other_index, element_type);
626
628
629 // add constraint
632
633 add_array_constraint(lazy, false); // added immediately
635
636#if 0 // old code for adding, not significantly faster
637 {
639
640 bvt bv;
641 bv.reserve(2);
642 bv.push_back(equality_lit);
643 bv.push_back(guard_lit);
644 prop.lcnf(bv);
645 }
646#endif
647 }
648 }
649 }
650}
651
653 const index_sett &,
654 const update_exprt &)
655{
656 // we got x=UPDATE(y, [i], v)
657 // add constaint x[i]=v
658
659#if 0
660 const exprt &index=expr.where();
661 const exprt &value=expr.new_value();
662
663 {
664 index_exprt index_expr(expr, index, expr.type().subtype());
665
667 index_expr.type()==value.type(),
668 "update operand should match array element type",
670
672 }
673
674 // use other array index applications for "else" case
675 // add constraint x[I]=y[I] for I!=i
676
677 for(auto other_index : index_set)
678 {
679 if(other_index!=index)
680 {
681 // we first build the guard
682
684
686
687 if(guard_lit!=const_literal(true))
688 {
689 const typet &subtype=expr.type().subtype();
690 index_exprt index_expr1(expr, other_index, subtype);
691 index_exprt index_expr2(expr.op0(), other_index, subtype);
692
694
696
697 // add constraint
698 bvt bv;
699 bv.reserve(2);
700 bv.push_back(equality_lit);
701 bv.push_back(guard_lit);
702 prop.lcnf(bv);
703 }
704 }
705 }
706#endif
707}
708
710 const index_sett &index_set,
711 const array_of_exprt &expr)
712{
713 // we got x=array_of[v]
714 // get other array index applications
715 // and add constraint x[i]=v
716
717 for(const auto &index : index_set)
718 {
719 const typet &element_type = expr.type().element_type();
720 index_exprt index_expr(expr, index, element_type);
721
723 index_expr.type() == expr.what().type(),
724 "array_of operand type should match array element type");
725
726 // add constraint
729 add_array_constraint(lazy, false); // added immediately
731 }
732}
733
735 const index_sett &index_set,
736 const array_exprt &expr)
737{
738 // we got x = { v, ... } - add constraint x[i] = v
739 const exprt::operandst &operands = expr.operands();
740
741 for(const auto &index : index_set)
742 {
743 const typet &element_type = expr.type().element_type();
744 const index_exprt index_expr{expr, index, element_type};
745
746 if(index.is_constant())
747 {
748 // We have a constant index - just pick the element at that index from the
749 // array constant.
750
751 const std::optional<std::size_t> i =
753 // if the access is out of bounds, we leave it unconstrained
754 if(!i.has_value() || *i >= operands.size())
755 continue;
756
757 const exprt v = operands[*i];
759 index_expr.type() == v.type(),
760 "array operand type should match array element type");
761
762 // add constraint
765 add_array_constraint(lazy, false); // added immediately
767 }
768 else
769 {
770 // We have a non-constant index into an array constant. We need to build a
771 // case statement testing the index against all possible values. Whenever
772 // neighbouring array elements are the same, we can test the index against
773 // the range rather than individual elements. This should be particularly
774 // helpful when we have arrays of zeros, as is the case for initializers.
775
776 std::vector<std::pair<std::size_t, std::size_t>> ranges;
777
778 for(std::size_t i = 0; i < operands.size(); ++i)
779 {
780 if(ranges.empty() || operands[i] != operands[ranges.back().first])
781 ranges.emplace_back(i, i);
782 else
783 ranges.back().second = i;
784 }
785
786 for(const auto &range : ranges)
787 {
789
790 if(range.first == range.second)
791 {
793 equal_exprt{index, from_integer(range.first, index.type())};
794 }
795 else
796 {
799 from_integer(range.first, index.type()), ID_le, index},
801 index, ID_le, from_integer(range.second, index.type())}};
802 }
803
807 equal_exprt{index_expr, operands[range.first]}}};
808 add_array_constraint(lazy, true); // added lazily
810 }
811 }
812 }
813}
814
816 const index_sett &index_set,
817 const array_comprehension_exprt &expr)
818{
819 // we got x=lambda(i: e)
820 // get all other array index applications
821 // and add constraints x[j]=e[i/j]
822
823 for(const auto &index : index_set)
824 {
825 index_exprt index_expr{expr, index};
827 replace_expr(expr.arg(), index, comprehension_body);
828
829 // add constraint
833
834 add_array_constraint(lazy, false); // added immediately
836 }
837}
838
840 const index_sett &index_set,
841 const if_exprt &expr)
842{
843 // we got x=(c?a:b)
845
846 // get other array index applications
847 // and add c => x[i]=a[i]
848 // !c => x[i]=b[i]
849
850 // first do true case
851
852 for(const auto &index : index_set)
853 {
854 const typet &element_type = to_array_type(expr.type()).element_type();
855 index_exprt index_expr1(expr, index, element_type);
856 index_exprt index_expr2(expr.true_case(), index, element_type);
857
858 // add implication
862 add_array_constraint(lazy, false); // added immediately
864
865#if 0 // old code for adding, not significantly faster
867#endif
868 }
869
870 // now the false case
871 for(const auto &index : index_set)
872 {
873 const typet &element_type = to_array_type(expr.type()).element_type();
874 index_exprt index_expr1(expr, index, element_type);
875 index_exprt index_expr2(expr.false_case(), index, element_type);
876
877 // add implication
882 add_array_constraint(lazy, false); // added immediately
884
885#if 0 // old code for adding, not significantly faster
887#endif
888 }
889}
890
892{
893 switch(type)
894 {
896 return "arrayAckermann";
898 return "arrayWith";
900 return "arrayIf";
902 return "arrayOf";
904 return "arrayTypecast";
906 return "arrayConstant";
908 return "arrayComprehension";
910 return "arrayEquality";
912 return "arrayLet";
913 default:
915 }
916}
917
919{
922 json_result["arrayConstraints"].make_object();
923
924 size_t num_constraints = 0;
925
926 array_constraint_countt::iterator it = array_constraint_count.begin();
927 while(it != array_constraint_count.end())
928 {
929 std::string contraint_type_string = enum_to_string(it->first);
931 json_numbert(std::to_string(it->second));
932
933 num_constraints += it->second;
934 it++;
935 }
936
937 json_result["numOfConstraints"] =
938 json_numbert(std::to_string(num_constraints));
939 log.status() << ",\n" << json_result;
940}
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:265
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
Boolean AND.
Definition std_expr.h:2125
Expression to define a mapping from an argument (index) to elements.
Definition std_expr.h:3543
const symbol_exprt & arg() const
Definition std_expr.h:3567
const exprt & body() const
Definition std_expr.h:3581
Array constructor from list of elements.
Definition std_expr.h:1621
const array_typet & type() const
Definition std_expr.h:1628
Array constructor from single element.
Definition std_expr.h:1558
const array_typet & type() const
Definition std_expr.h:1565
exprt & what()
Definition std_expr.h:1575
Arrays with given size.
Definition std_types.h:807
std::list< lazy_constraintt > lazy_array_constraints
Definition arrays.h:115
std::unordered_set< irep_idt > array_comprehension_args
Definition arrays.h:165
index_mapt index_map
Definition arrays.h:85
void add_array_constraints_equality(const index_sett &index_set, const array_equalityt &array_equality)
Definition arrays.cpp:441
std::set< std::size_t > update_indices
Definition arrays.h:161
void add_array_constraints_array_of(const index_sett &index_set, const array_of_exprt &exprt)
Definition arrays.cpp:709
void add_array_Ackermann_constraints()
Definition arrays.cpp:330
bool lazy_arrays
Definition arrays.h:112
void collect_indices()
Definition arrays.cpp:83
void add_array_constraints_update(const index_sett &index_set, const update_exprt &expr)
Definition arrays.cpp:652
void collect_arrays(const exprt &a)
Definition arrays.cpp:131
union_find< exprt, irep_hash > arrays
Definition arrays.h:78
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:734
arrayst(const namespacet &_ns, propt &_prop, message_handlert &message_handler, bool get_array_constraints=false)
Definition arrays.cpp:29
constraint_typet
Definition arrays.h:120
std::map< exprt, bool > expr_map
Definition arrays.h:117
void add_array_constraints_if(const index_sett &index_set, const if_exprt &exprt)
Definition arrays.cpp:839
std::string enum_to_string(constraint_typet)
Definition arrays.cpp:891
bool get_array_constraints
Definition arrays.h:114
void add_array_constraints()
Definition arrays.cpp:280
void add_array_constraints_comprehension(const index_sett &index_set, const array_comprehension_exprt &expr)
Definition arrays.cpp:815
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:75
std::set< exprt > index_sett
Definition arrays.h:81
void add_array_constraint(const lazy_constraintt &lazy, bool refine=true)
adds array constraints (refine=true...lazily for the refinement loop)
Definition arrays.cpp:255
array_constraint_countt array_constraint_count
Definition arrays.h:133
void add_array_constraints_with(const index_sett &index_set, const with_exprt &expr)
Definition arrays.cpp:573
bool incremental_cache
Definition arrays.h:113
void display_array_constraint_count()
Definition arrays.cpp:918
void update_index_map(bool update_all)
Definition arrays.cpp:407
messaget log
Definition arrays.h:57
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition std_expr.h:731
void set_to_true(const exprt &)
For a Boolean expression expr, add the constraint 'expr'.
Equality.
Definition std_expr.h:1366
virtual literalt equality(const exprt &e1, const exprt &e2)
Definition equality.cpp:17
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
bool is_constant() const
Return whether the expression is a constant.
Definition expr.h:212
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
The trinary if-then-else operator.
Definition std_expr.h:2497
exprt & cond()
Definition std_expr.h:2514
exprt & false_case()
Definition std_expr.h:2534
exprt & true_case()
Definition std_expr.h:2524
Boolean implication.
Definition std_expr.h:2225
Array index operator.
Definition std_expr.h:1470
exprt & index()
Definition std_expr.h:1510
exprt & array()
Definition std_expr.h:1500
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.
Definition std_expr.h:2270
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...
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
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:2782
Operator to update elements in structs and arrays.
Definition std_expr.h:2598
exprt & old()
Definition std_expr.h:2608
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:2449
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:71
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:1603
const index_exprt & to_index_expr(const exprt &expr)
Cast an exprt to an index_exprt.
Definition std_expr.h:1538
const array_comprehension_exprt & to_array_comprehension_expr(const exprt &expr)
Cast an exprt to a array_comprehension_exprt.
Definition std_expr.h:3610
const array_exprt & to_array_expr(const exprt &expr)
Cast an exprt to an array_exprt.
Definition std_expr.h:1665
const typecast_exprt & to_typecast_expr(const exprt &expr)
Cast an exprt to a typecast_exprt.
Definition std_expr.h:2107
const if_exprt & to_if_expr(const exprt &expr)
Cast an exprt to an if_exprt.
Definition std_expr.h:2577
const member_exprt & to_member_expr(const exprt &expr)
Cast an exprt to a member_exprt.
Definition std_expr.h:3063
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const with_exprt & to_with_expr(const exprt &expr)
Cast an exprt to a with_exprt.
Definition std_expr.h:2660
const update_exprt & to_update_expr(const exprt &expr)
Cast an exprt to an update_exprt.
Definition std_expr.h:2865
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888