CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
convert_expr_to_smt.cpp
Go to the documentation of this file.
1// Author: Diffblue Ltd.
2#include <util/arith_tools.h>
5#include <util/c_types.h>
6#include <util/config.h>
7#include <util/expr.h>
8#include <util/expr_cast.h>
9#include <util/floatbv_expr.h>
11#include <util/pointer_expr.h>
13#include <util/range.h>
14#include <util/std_expr.h>
16
22
23#include <algorithm>
24#include <functional>
25#include <numeric>
26#include <stack>
27
37using sub_expression_mapt = std::unordered_map<exprt, smt_termt, irep_hash>;
38
51template <typename factoryt>
53 const multi_ary_exprt &expr,
54 const sub_expression_mapt &converted,
55 const factoryt &factory)
56{
57 PRECONDITION(expr.operands().size() >= 2);
58 const auto operand_terms =
59 make_range(expr.operands()).map([&](const exprt &expr) {
60 return converted.at(expr);
61 });
62 return std::accumulate(
63 ++operand_terms.begin(),
64 operand_terms.end(),
65 *operand_terms.begin(),
66 factory);
67}
68
73template <typename target_typet>
74static bool operands_are_of_type(const exprt &expr)
75{
76 return std::all_of(
77 expr.operands().cbegin(), expr.operands().cend(), [](const exprt &operand) {
78 return can_cast_type<target_typet>(operand.type());
79 });
80}
81
83{
84 return smt_bool_sortt{};
85}
86
91
98
100{
101 if(const auto bool_type = type_try_dynamic_cast<bool_typet>(type))
102 {
104 }
106 {
108 }
110 {
112 }
113 UNIMPLEMENTED_FEATURE("Generation of SMT formula for type: " + type.pretty());
114}
115
117{
118 return smt_identifier_termt{symbol_expr.get_identifier(),
119 convert_type_to_smt_sort(symbol_expr.type())};
120}
121
124 const sub_expression_mapt &converted)
125{
126 // A nondet_symbol is a reference to an unconstrained function. This function
127 // will already have been added as a dependency.
129 nondet_symbol.get_identifier(),
131}
132
135{
136 if(input.get_sort().cast<smt_bool_sortt>())
137 return input;
138 if(const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>())
139 {
142 }
144}
145
148 const smt_termt &from_term,
149 const typet &from_type,
150 const bitvector_typet &to_type)
151{
152 const std::size_t c_bool_width = to_type.get_width();
154 make_not_zero(from_term, from_type),
157}
158
159static std::function<std::function<smt_termt(smt_termt)>(std::size_t)>
172
174 const smt_termt &from_term,
176 const bitvector_typet &to_type)
177{
179 {
181 "Generation of SMT formula for type cast to fixed-point bitvector "
182 "type: " +
183 to_type.pretty());
184 }
186 {
188 "Generation of SMT formula for type cast to floating-point bitvector "
189 "type: " +
190 to_type.pretty());
191 }
192 const std::size_t from_width = from_type.get_width();
193 const std::size_t to_width = to_type.get_width();
194 if(to_width == from_width)
195 return from_term;
196 if(to_width < from_width)
197 return smt_bit_vector_theoryt::extract(to_width - 1, 0)(from_term);
198 const std::size_t extension_size = to_width - from_width;
199 return extension_for_type(from_type)(extension_size)(from_term);
200}
201
204{
208 std::optional<smt_termt> result;
209
217
218 void visit(const smt_bool_sortt &) override
219 {
221 from_term, from_type, c_bool_typet{to_type.get_width()});
222 }
223
224 void visit(const smt_bit_vector_sortt &) override
225 {
228 else
230 "Generation of SMT formula for type cast to bit vector from type: " +
231 from_type.pretty());
232 }
233
234 void visit(const smt_array_sortt &) override
235 {
237 "Generation of SMT formula for type cast to bit vector from type: " +
238 from_type.pretty());
239 }
240};
241
243 const smt_termt &from_term,
244 const typet &from_type,
245 const bitvector_typet &to_type)
246{
248 from_term, from_type, to_type};
249 from_term.get_sort().accept(converter);
250 POSTCONDITION(converter.result);
251 return *converter.result;
252}
253
255 const typecast_exprt &cast,
256 const sub_expression_mapt &converted)
257{
258 const auto &from_term = converted.at(cast.op());
259 const typet &from_type = cast.op().type();
260 const typet &to_type = cast.type();
261 if(const auto bool_type = type_try_dynamic_cast<bool_typet>(to_type))
262 return make_not_zero(from_term, cast.op().type());
263 if(const auto c_bool_type = type_try_dynamic_cast<c_bool_typet>(to_type))
264 return convert_c_bool_cast(from_term, from_type, *c_bool_type);
265 if(const auto bit_vector = type_try_dynamic_cast<bitvector_typet>(to_type))
266 return convert_bit_vector_cast(from_term, from_type, *bit_vector);
268 "Generation of SMT formula for type cast expression: " + cast.pretty());
269}
270
273 const sub_expression_mapt &converted)
274{
276 "Generation of SMT formula for floating point type cast expression: " +
277 float_cast.pretty());
278}
279
282 const sub_expression_mapt &converted)
283{
285 "Generation of SMT formula for struct construction expression: " +
286 struct_construction.pretty());
287}
288
291 const sub_expression_mapt &converted)
292{
294 "Generation of SMT formula for union construction expression: " +
295 union_construction.pretty());
296}
297
299{
301 std::optional<smt_termt> result;
302
304 : member_input{input}
305 {
306 }
307
308 void visit(const smt_bool_sortt &) override
309 {
311 }
312
314 {
315 const auto &width = bit_vector_sort.bit_width();
316 // We get the value using a non-signed interpretation, as smt bit vector
317 // terms do not carry signedness.
318 const auto value = bvrep2integer(member_input.get_value(), width, false);
320 }
321
322 void visit(const smt_array_sortt &array_sort) override
323 {
325 "Conversion of array SMT literal " + array_sort.pretty());
326 }
327};
328
330{
331 if(constant_literal.is_null_pointer())
332 {
333 const size_t bit_width =
335 // An address of 0 encodes an object identifier of 0 for the NULL object
336 // and an offset of 0 into the object.
337 const auto address = 0;
338 return smt_bit_vector_constant_termt{address, bit_width};
339 }
340 if(constant_literal.type() == integer_typet{})
341 {
342 // This is converting integer constants into bit vectors for use with
343 // bit vector based smt logics. As bit vector widths are not specified for
344 // non bit vector types, this chooses a width based on the minimum needed
345 // to hold the integer constant value.
347 return smt_bit_vector_constant_termt{value, address_bits(value + 1)};
348 }
349 const auto sort = convert_type_to_smt_sort(constant_literal.type());
351 sort.accept(converter);
352 return *converter.result;
353}
354
357 const sub_expression_mapt &converted)
358{
360 {
363 }
365 "Generation of SMT formula for concatenation expression: " +
366 concatenation.pretty());
367}
368
371 const sub_expression_mapt &converted)
372{
374 {
377 }
378 else
379 {
381 "Generation of SMT formula for bitwise and expression: " +
382 bitwise_and_expr.pretty());
383 }
384}
385
388 const sub_expression_mapt &converted)
389{
391 {
394 }
395 else
396 {
398 "Generation of SMT formula for bitwise or expression: " +
399 bitwise_or_expr.pretty());
400 }
401}
402
405 const sub_expression_mapt &converted)
406{
408 {
411 }
412 else
413 {
415 "Generation of SMT formula for bitwise xor expression: " +
416 bitwise_xor.pretty());
417 }
418}
419
421 const bitnot_exprt &bitwise_not,
422 const sub_expression_mapt &converted)
423{
424 if(can_cast_type<bitvector_typet>(bitwise_not.op().type()))
425 {
426 return smt_bit_vector_theoryt::make_not(converted.at(bitwise_not.op()));
427 }
428 else
429 {
431 "Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty());
432 }
433}
434
436 const unary_minus_exprt &unary_minus,
437 const sub_expression_mapt &converted)
438{
439 if(can_cast_type<integer_bitvector_typet>(unary_minus.op().type()))
440 {
441 return smt_bit_vector_theoryt::negate(converted.at(unary_minus.op()));
442 }
443 else
444 {
446 "Generation of SMT formula for unary minus expression: " +
447 unary_minus.pretty());
448 }
449}
450
452 const unary_plus_exprt &unary_plus,
453 const sub_expression_mapt &converted)
454{
456 "Generation of SMT formula for unary plus expression: " +
457 unary_plus.pretty());
458}
459
461 const sign_exprt &is_negative,
462 const sub_expression_mapt &converted)
463{
465 "Generation of SMT formula for \"is negative\" expression: " +
466 is_negative.pretty());
467}
468
470 const if_exprt &if_expression,
471 const sub_expression_mapt &converted)
472{
474 converted.at(if_expression.cond()),
475 converted.at(if_expression.true_case()),
476 converted.at(if_expression.false_case()));
477}
478
486
494
502
504 const implies_exprt &implies,
505 const sub_expression_mapt &converted)
506{
508 converted.at(implies.op0()), converted.at(implies.op1()));
509}
510
512 const not_exprt &logical_not,
513 const sub_expression_mapt &converted)
514{
515 return smt_core_theoryt::make_not(converted.at(logical_not.op()));
516}
517
519 const equal_exprt &equal,
520 const sub_expression_mapt &converted)
521{
523 converted.at(equal.op0()), converted.at(equal.op1()));
524}
525
527 const notequal_exprt &not_equal,
528 const sub_expression_mapt &converted)
529{
531 converted.at(not_equal.op0()), converted.at(not_equal.op1()));
532}
533
536 const sub_expression_mapt &converted)
537{
539 "Generation of SMT formula for floating point equality expression: " +
540 float_equal.pretty());
541}
542
545 const sub_expression_mapt &converted)
546{
548 "Generation of SMT formula for floating point not equal expression: " +
549 float_not_equal.pretty());
550}
551
552template <typename unsigned_factory_typet, typename signed_factory_typet>
557 const sub_expression_mapt &converted)
558{
559 PRECONDITION(binary_relation.lhs().type() == binary_relation.rhs().type());
560 const auto &lhs = converted.at(binary_relation.lhs());
561 const auto &rhs = converted.at(binary_relation.rhs());
562 const typet operand_type = binary_relation.lhs().type();
564 {
565 // The code here is operating under the assumption that the comparison
566 // operands have types for which the comparison makes sense.
567
568 // We already know this is the case given that we have followed
569 // the if statement branch, but including the same check here
570 // for consistency (it's cheap).
571 const auto lhs_type_is_pointer =
573 const auto rhs_type_is_pointer =
575 INVARIANT(
577 "pointer comparison requires that both operand types are pointers.");
578 return unsigned_factory(lhs, rhs);
579 }
580 else if(lhs.get_sort().cast<smt_bit_vector_sortt>())
581 {
583 return unsigned_factory(lhs, rhs);
585 return signed_factory(lhs, rhs);
586 }
587
589 "Generation of SMT formula for relational expression: " +
590 binary_relation.pretty());
591}
592
593static std::optional<smt_termt> try_relational_conversion(
594 const exprt &expr,
595 const sub_expression_mapt &converted)
596{
598 {
603 converted);
604 }
605 if(
606 const auto greater_than_or_equal =
608 {
610 *greater_than_or_equal,
613 converted);
614 }
616 {
618 *less_than,
621 converted);
622 }
623 if(
624 const auto less_than_or_equal =
626 {
628 *less_than_or_equal,
631 converted);
632 }
633 return {};
634}
635
637 const plus_exprt &plus,
638 const sub_expression_mapt &converted,
640{
641 if(std::all_of(
642 plus.operands().cbegin(), plus.operands().cend(), [](exprt operand) {
643 return can_cast_type<integer_bitvector_typet>(operand.type());
644 }))
645 {
647 plus, converted, smt_bit_vector_theoryt::add);
648 }
649 else if(can_cast_type<pointer_typet>(plus.type()))
650 {
651 INVARIANT(
652 plus.operands().size() == 2,
653 "We are only handling a binary version of plus when it has a pointer "
654 "operand");
655
656 exprt pointer;
658 for(auto &operand : plus.operands())
659 {
661 {
662 pointer = operand;
663 }
664 else
665 {
666 scalar = operand;
667 }
668 }
669
670 // We need to ensure that we follow this code path only if the expression
671 // our assumptions about the structure of the addition expression hold.
672 INVARIANT(
674 "An addition expression with both operands being pointers when they are "
675 "not dereferenced is malformed");
676
679 const auto base_type = pointer_type.base_type();
680 const auto pointer_size = pointer_sizes.at(base_type);
681
683 converted.at(pointer),
685 }
686 else
687 {
689 "Generation of SMT formula for plus expression: " + plus.pretty());
690 }
691}
692
694 const minus_exprt &minus,
695 const sub_expression_mapt &converted,
697{
698 const bool both_operands_bitvector =
701
702 const bool lhs_is_pointer = can_cast_type<pointer_typet>(minus.lhs().type());
703 const bool rhs_is_pointer = can_cast_type<pointer_typet>(minus.rhs().type());
704
706
707 // We don't really handle this - we just compute this to fall
708 // into an if-else branch that gives proper error handling information.
710
712 {
714 converted.at(minus.lhs()), converted.at(minus.rhs()));
715 }
717 {
718 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
719 const auto rhs_base_type = to_pointer_type(minus.rhs().type()).base_type();
720 INVARIANT(
722 "only pointers of the same object type can be subtracted.");
725 converted.at(minus.lhs()), converted.at(minus.rhs())),
727 }
728 else if(one_operand_pointer)
729 {
730 // It's semantically void to have an expression `3 - a` where `a`
731 // is a pointer.
732 INVARIANT(
734 "minus expressions of pointer and integer expect lhs to be the pointer");
735 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
736
738 converted.at(minus.lhs()),
740 converted.at(minus.rhs()), pointer_sizes.at(lhs_base_type)));
741 }
742 else
743 {
745 "Generation of SMT formula for minus expression: " + minus.pretty());
746 }
747}
748
750 const div_exprt &divide,
751 const sub_expression_mapt &converted)
752{
753 const smt_termt &lhs = converted.at(divide.lhs());
754 const smt_termt &rhs = converted.at(divide.rhs());
755
756 const bool both_operands_bitvector =
759
760 const bool both_operands_unsigned =
763
765 {
767 {
769 }
770 else
771 {
773 }
774 }
775 else
776 {
778 "Generation of SMT formula for divide expression: " + divide.pretty());
779 }
780}
781
784 const sub_expression_mapt &converted)
785{
786 // This case includes the floating point plus, minus, division and
787 // multiplication operations.
789 "Generation of SMT formula for floating point operation expression: " +
790 float_operation.pretty());
791}
792
795 const sub_expression_mapt &converted)
796{
797 const smt_termt &lhs = converted.at(truncation_modulo.lhs());
798 const smt_termt &rhs = converted.at(truncation_modulo.rhs());
799
800 const bool both_operands_bitvector =
803
804 const bool both_operands_unsigned =
807
809 {
811 {
813 }
814 else
815 {
817 }
818 }
819 else
820 {
822 "Generation of SMT formula for remainder (modulus) expression: " +
823 truncation_modulo.pretty());
824 }
825}
826
829 const sub_expression_mapt &converted)
830{
832 "Generation of SMT formula for euclidean modulo expression: " +
833 euclidean_modulo.pretty());
834}
835
837 const mult_exprt &multiply,
838 const sub_expression_mapt &converted)
839{
840 if(std::all_of(
841 multiply.operands().cbegin(),
842 multiply.operands().cend(),
843 [](exprt operand) {
844 return can_cast_type<integer_bitvector_typet>(operand.type());
845 }))
846 {
848 multiply, converted, smt_bit_vector_theoryt::multiply);
849 }
850 else
851 {
853 "Generation of SMT formula for multiply expression: " +
854 multiply.pretty());
855 }
856}
857
867 const sub_expression_mapt &converted,
868 const smt_object_mapt &object_map)
869{
870 const auto type = type_try_dynamic_cast<pointer_typet>(address_of.type());
871 INVARIANT(
872 type, "Result of the address_of operator should have pointer type.");
873 const auto base = find_object_base_expression(address_of);
874 const auto object = object_map.find(base);
875 INVARIANT(
876 object != object_map.end(),
877 "Objects should be tracked before converting their address to SMT terms");
878 const std::size_t object_id = object->second.unique_id;
879 const std::size_t object_bits = config.bv_encoding.object_bits;
880 const std::size_t max_objects = std::size_t(1) << object_bits;
882 {
884 "too many addressed objects: maximum number of objects is set to 2^n=" +
885 std::to_string(max_objects) + " (with n=" + std::to_string(object_bits) +
886 "); " +
887 "use the `--object-bits n` option to increase the maximum number"};
888 }
891 INVARIANT(
892 type->get_width() > object_bits,
893 "Pointer should be wider than object_bits in order to allow for offset "
894 "encoding.");
895 const size_t offset_bits = type->get_width() - object_bits;
896 if(
897 const auto symbol =
899 {
902 }
904 "Generation of SMT formula for address of expression: " +
905 address_of.pretty());
906}
907
910 const sub_expression_mapt &converted)
911{
912 // This function is unreachable as the `array_of_exprt` nodes are already
913 // fully converted by the incremental decision procedure functions
914 // (smt2_incremental_decision_proceduret::define_array_function).
916}
917
920 const sub_expression_mapt &converted)
921{
923 "Generation of SMT formula for array comprehension expression: " +
924 array_comprehension.pretty());
925}
926
928 const index_exprt &index_of,
929 const sub_expression_mapt &converted)
930{
931 const smt_termt &array = converted.at(index_of.array());
932 const smt_termt &index = converted.at(index_of.index());
933 return smt_array_theoryt::select(array, index);
934}
935
936template <typename factoryt, typename shiftt>
938 const factoryt &factory,
939 const shiftt &shift,
940 const sub_expression_mapt &converted)
941{
942 const smt_termt &first_operand = converted.at(shift.op0());
943 const smt_termt &second_operand = converted.at(shift.op1());
944 const auto first_bit_vector_sort =
945 first_operand.get_sort().cast<smt_bit_vector_sortt>();
946 const auto second_bit_vector_sort =
947 second_operand.get_sort().cast<smt_bit_vector_sortt>();
948 INVARIANT(
950 "Shift expressions are expected to have bit vector operands.");
951 INVARIANT(
952 shift.type() == shift.op0().type(),
953 "Shift expression type must be equals to first operand type.");
954 const std::size_t first_width = first_bit_vector_sort->bit_width();
955 const std::size_t second_width = second_bit_vector_sort->bit_width();
957 {
958 return factory(
960 extension_for_type(shift.op1().type())(first_width - second_width)(
962 }
963 else if(first_width < second_width)
964 {
965 const auto result = factory(
966 extension_for_type(shift.op0().type())(second_width - first_width)(
969 return smt_bit_vector_theoryt::extract(first_width - 1, 0)(result);
970 }
971 else
972 {
973 return factory(first_operand, second_operand);
974 }
975}
976
978 const shift_exprt &shift,
979 const sub_expression_mapt &converted)
980{
981 // TODO: Dispatch for rotation expressions. A `shift_exprt` can be a rotation.
982 if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
983 {
985 smt_bit_vector_theoryt::shift_left, *left_shift, converted);
986 }
988 {
992 converted);
993 }
995 {
999 converted);
1000 }
1002 "Generation of SMT formula for shift expression: " + shift.pretty());
1003}
1004
1006 const with_exprt &with,
1007 const sub_expression_mapt &converted)
1008{
1009 smt_termt array = converted.at(with.old());
1010 for(auto it = ++with.operands().begin(); it != with.operands().end(); it += 2)
1011 {
1012 const smt_termt &index_term = converted.at(it[0]);
1013 const smt_termt &value_term = converted.at(it[1]);
1015 }
1016 return array;
1017}
1018
1020 const with_exprt &with,
1021 const sub_expression_mapt &converted)
1022{
1024 return convert_array_update_to_smt(with, converted);
1025 // 'with' expression is also used to update struct fields, but for now we do
1026 // not support them, so we fail.
1028 "Generation of SMT formula for with expression: " + with.pretty());
1029}
1030
1032 const update_exprt &update,
1033 const sub_expression_mapt &converted)
1034{
1036 "Generation of SMT formula for update expression: " + update.pretty());
1037}
1038
1041 const sub_expression_mapt &converted)
1042{
1044 "Generation of SMT formula for member extraction expression: " +
1045 member_extraction.pretty());
1046}
1047
1049 const is_dynamic_object_exprt &is_dynamic_object,
1050 const sub_expression_mapt &converted,
1052{
1053 const smt_termt &pointer = converted.at(is_dynamic_object.address());
1054 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1055 INVARIANT(
1056 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1057 const std::size_t pointer_width = pointer_sort->bit_width();
1059 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1060 pointer_width - 1,
1061 pointer_width - config.bv_encoding.object_bits)(pointer)});
1062}
1063
1066 const smt_object_mapt &object_map,
1067 const sub_expression_mapt &converted)
1068{
1069 const exprt &pointer_expr(to_unary_expr(is_invalid_pointer).op());
1072 INVARIANT(pointer_type, "Pointer object should have a bitvector-based type.");
1073 const std::size_t object_bits = config.bv_encoding.object_bits;
1074 const std::size_t width = pointer_type->get_width();
1075 INVARIANT(
1076 width >= object_bits,
1077 "Width should be at least as big as the number of object bits.");
1078
1080 width - 1, width - object_bits)(converted.at(pointer_expr));
1081
1082 const auto &invalid_pointer = object_map.at(make_invalid_pointer_expr());
1083
1085 invalid_pointer.unique_id, config.bv_encoding.object_bits);
1086
1088}
1089
1092 const sub_expression_mapt &converted)
1093{
1095 "Generation of SMT formula for string constant expression: " +
1096 string_constant.pretty());
1097}
1098
1101 const sub_expression_mapt &converted)
1102{
1104 "Generation of SMT formula for extract bit expression: " +
1105 extract_bit.pretty());
1106}
1107
1110 const sub_expression_mapt &converted)
1111{
1112 const smt_termt &from = converted.at(extract_bits.src());
1113 const auto bit_vector_sort =
1115 INVARIANT(
1116 bit_vector_sort, "Extract can only be applied to bit vector terms.");
1118 if(index_value)
1120 *index_value + bit_vector_sort->bit_width() - 1, *index_value)(from);
1122 "Generation of SMT formula for extract bits expression: " +
1123 extract_bits.pretty());
1124}
1125
1128 const sub_expression_mapt &converted)
1129{
1131 "Generation of SMT formula for bit vector replication expression: " +
1132 replication.pretty());
1133}
1134
1137 const sub_expression_mapt &converted)
1138{
1140 "Generation of SMT formula for byte extract expression: " +
1141 byte_extraction.pretty());
1142}
1143
1146 const sub_expression_mapt &converted)
1147{
1149 "Generation of SMT formula for byte update expression: " +
1150 byte_update.pretty());
1151}
1152
1155 const sub_expression_mapt &converted)
1156{
1158 "Generation of SMT formula for absolute value of expression: " +
1159 absolute_value_of.pretty());
1160}
1161
1163 const isnan_exprt &is_nan_expr,
1164 const sub_expression_mapt &converted)
1165{
1167 "Generation of SMT formula for is not a number expression: " +
1168 is_nan_expr.pretty());
1169}
1170
1173 const sub_expression_mapt &converted)
1174{
1176 "Generation of SMT formula for is finite expression: " +
1177 is_finite_expr.pretty());
1178}
1179
1182 const sub_expression_mapt &converted)
1183{
1185 "Generation of SMT formula for is infinite expression: " +
1186 is_infinite_expr.pretty());
1187}
1188
1191 const sub_expression_mapt &converted)
1192{
1194 "Generation of SMT formula for is infinite expression: " +
1195 is_normal_expr.pretty());
1196}
1197
1202{
1203 const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>();
1204 INVARIANT(
1206 "Most significant bit can only be extracted from bit vector terms.");
1207 const size_t most_significant_bit_index = bit_vector_sort->bit_width() - 1;
1212}
1213
1216 const sub_expression_mapt &converted)
1217{
1218 const smt_termt &left = converted.at(plus_overflow.lhs());
1219 const smt_termt &right = converted.at(plus_overflow.rhs());
1221 {
1225 }
1227 {
1228 // Overflow has occurred if the operands have the same sign and adding them
1229 // gives a result of the opposite sign.
1235 msb_left,
1237 }
1239 "Generation of SMT formula for plus overflow expression: " +
1240 plus_overflow.pretty());
1241}
1242
1245 const sub_expression_mapt &converted)
1246{
1247 const smt_termt &left = converted.at(minus_overflow.lhs());
1248 const smt_termt &right = converted.at(minus_overflow.rhs());
1250 {
1252 }
1254 {
1255 // Overflow has occurred if the operands have the opposing signs and
1256 // subtracting them gives a result having the same signedness as the
1257 // right-hand operand. For example the following would be overflow for cases
1258 // for 8 bit wide bit vectors -
1259 // -128 - 1 == 127
1260 // 127 - (-1) == -128
1266 msb_right,
1268 smt_bit_vector_theoryt::subtract(left, right))));
1269 }
1271 "Generation of SMT formula for minus overflow expression: " +
1272 minus_overflow.pretty());
1273}
1274
1277 const sub_expression_mapt &converted)
1278{
1279 PRECONDITION(mult_overflow.lhs().type() == mult_overflow.rhs().type());
1280 const auto &operand_type = mult_overflow.lhs().type();
1281 const smt_termt &left = converted.at(mult_overflow.lhs());
1282 const smt_termt &right = converted.at(mult_overflow.rhs());
1283 if(
1284 const auto unsigned_type =
1286 {
1287 const std::size_t width = unsigned_type->get_width();
1288 const auto extend = smt_bit_vector_theoryt::zero_extend(width);
1291 smt_bit_vector_constant_termt{power(2, width), width * 2});
1292 }
1293 if(
1294 const auto signed_type =
1296 {
1299 const std::size_t width = signed_type->get_width();
1300 const auto extend = smt_bit_vector_theoryt::sign_extend(width);
1301 const auto multiplication =
1305 smt_bit_vector_constant_termt{power(2, width - 1), width * 2});
1309 smt_bit_vector_constant_termt{power(2, width - 1), width * 2}));
1312 }
1314 "Generation of SMT formula for multiply overflow expression: " +
1315 mult_overflow.pretty());
1316}
1317
1320 const sub_expression_mapt &converted)
1321{
1322 const auto type =
1324 INVARIANT(type, "Pointer object should have a bitvector-based type.");
1325 const auto converted_expr = converted.at(pointer_object.pointer());
1326 const std::size_t width = type->get_width();
1327 const std::size_t object_bits = config.bv_encoding.object_bits;
1328 INVARIANT(
1329 width >= object_bits,
1330 "Width should be at least as big as the number of object bits.");
1331 const std::size_t ext = width - object_bits;
1333 width - 1, width - object_bits)(converted_expr);
1334 if(ext > 0)
1335 {
1337 }
1338 return extract_op;
1339}
1340
1343 const sub_expression_mapt &converted)
1344{
1345 const auto type =
1347 INVARIANT(type, "Pointer offset should have a bitvector-based type.");
1348 const auto converted_expr = converted.at(pointer_offset.pointer());
1349 const std::size_t width = type->get_width();
1350 std::size_t offset_bits = width - config.bv_encoding.object_bits;
1351 if(offset_bits > width)
1352 offset_bits = width;
1353 const auto extract_op =
1355 if(width > offset_bits)
1356 {
1358 }
1359 return extract_op;
1360}
1361
1364 const sub_expression_mapt &converted)
1365{
1367 "Generation of SMT formula for shift left overflow expression: " +
1368 shl_overflow.pretty());
1369}
1370
1373 const sub_expression_mapt &converted)
1374{
1375 // This function is unreachable as the `array_exprt` nodes are already fully
1376 // converted by the incremental decision procedure functions
1377 // (smt2_incremental_decision_proceduret::define_array_function).
1379}
1380
1382 const literal_exprt &literal,
1383 const sub_expression_mapt &converted)
1384{
1386 "Generation of SMT formula for literal expression: " + literal.pretty());
1387}
1388
1390 const forall_exprt &for_all,
1391 const sub_expression_mapt &converted)
1392{
1394 "Generation of SMT formula for for all expression: " + for_all.pretty());
1395}
1396
1398 const exists_exprt &exists,
1399 const sub_expression_mapt &converted)
1400{
1402 "Generation of SMT formula for exists expression: " + exists.pretty());
1403}
1404
1406 const vector_exprt &vector,
1407 const sub_expression_mapt &converted)
1408{
1410 "Generation of SMT formula for vector expression: " + vector.pretty());
1411}
1412
1415 const sub_expression_mapt &converted,
1417{
1418 const smt_termt &pointer = converted.at(object_size.pointer());
1419 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1420 INVARIANT(
1421 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1422 const std::size_t pointer_width = pointer_sort->bit_width();
1423 return call_object_size(
1424 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1425 pointer_width - 1,
1426 pointer_width - config.bv_encoding.object_bits)(pointer)});
1427}
1428
1429static smt_termt
1431{
1433 "Generation of SMT formula for let expression: " + let.pretty());
1434}
1435
1437 const bswap_exprt &byte_swap,
1438 const sub_expression_mapt &converted)
1439{
1441 "Generation of SMT formula for byte swap expression: " +
1442 byte_swap.pretty());
1443}
1444
1447 const sub_expression_mapt &converted)
1448{
1450 "Generation of SMT formula for population count expression: " +
1451 population_count.pretty());
1452}
1453
1456 const sub_expression_mapt &converted)
1457{
1459 "Generation of SMT formula for count leading zeros expression: " +
1460 count_leading_zeros.pretty());
1461}
1462
1465 const sub_expression_mapt &converted)
1466{
1468 "Generation of SMT formula for count trailing zeros expression: " +
1469 count_trailing_zeros.pretty());
1470}
1471
1473 const zero_extend_exprt &zero_extend,
1474 const sub_expression_mapt &converted)
1475{
1477 "zero_extend expression should have been lowered by the decision "
1478 "procedure before conversion to smt terms");
1479}
1480
1483 const sub_expression_mapt &converted)
1484{
1486 "prophecy_r_or_w_ok expression should have been lowered by the decision "
1487 "procedure before conversion to smt terms");
1488}
1489
1492 const sub_expression_mapt &converted)
1493{
1495 "prophecy_pointer_in_range expression should have been lowered by the "
1496 "decision procedure before conversion to smt terms");
1497}
1498
1500 const exprt &expr,
1501 const sub_expression_mapt &converted,
1502 const smt_object_mapt &object_map,
1506{
1507 if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
1508 {
1509 return convert_expr_to_smt(*symbol);
1510 }
1512 {
1513 return convert_expr_to_smt(*nondet, converted);
1514 }
1515 if(const auto cast = expr_try_dynamic_cast<typecast_exprt>(expr))
1516 {
1517 return convert_expr_to_smt(*cast, converted);
1518 }
1519 if(
1521 {
1522 return convert_expr_to_smt(*float_cast, converted);
1523 }
1525 {
1526 return convert_expr_to_smt(*struct_construction, converted);
1527 }
1529 {
1530 return convert_expr_to_smt(*union_construction, converted);
1531 }
1533 {
1535 }
1536 if(
1538 {
1539 return convert_expr_to_smt(*concatenation, converted);
1540 }
1542 {
1543 return convert_expr_to_smt(*bitwise_and_expr, converted);
1544 }
1546 {
1547 return convert_expr_to_smt(*bitwise_or_expr, converted);
1548 }
1550 {
1551 return convert_expr_to_smt(*bitwise_xor, converted);
1552 }
1553 if(const auto bitwise_not = expr_try_dynamic_cast<bitnot_exprt>(expr))
1554 {
1555 return convert_expr_to_smt(*bitwise_not, converted);
1556 }
1557 if(const auto unary_minus = expr_try_dynamic_cast<unary_minus_exprt>(expr))
1558 {
1559 return convert_expr_to_smt(*unary_minus, converted);
1560 }
1561 if(const auto unary_plus = expr_try_dynamic_cast<unary_plus_exprt>(expr))
1562 {
1563 return convert_expr_to_smt(*unary_plus, converted);
1564 }
1565 if(const auto is_negative = expr_try_dynamic_cast<sign_exprt>(expr))
1566 {
1567 return convert_expr_to_smt(*is_negative, converted);
1568 }
1569 if(const auto if_expression = expr_try_dynamic_cast<if_exprt>(expr))
1570 {
1571 return convert_expr_to_smt(*if_expression, converted);
1572 }
1574 {
1575 return convert_expr_to_smt(*and_expression, converted);
1576 }
1577 if(const auto or_expression = expr_try_dynamic_cast<or_exprt>(expr))
1578 {
1579 return convert_expr_to_smt(*or_expression, converted);
1580 }
1582 {
1583 return convert_expr_to_smt(*xor_expression, converted);
1584 }
1585 if(const auto implies = expr_try_dynamic_cast<implies_exprt>(expr))
1586 {
1587 return convert_expr_to_smt(*implies, converted);
1588 }
1589 if(const auto logical_not = expr_try_dynamic_cast<not_exprt>(expr))
1590 {
1591 return convert_expr_to_smt(*logical_not, converted);
1592 }
1593 if(const auto equal = expr_try_dynamic_cast<equal_exprt>(expr))
1594 {
1595 return convert_expr_to_smt(*equal, converted);
1596 }
1597 if(const auto not_equal = expr_try_dynamic_cast<notequal_exprt>(expr))
1598 {
1599 return convert_expr_to_smt(*not_equal, converted);
1600 }
1601 if(
1602 const auto float_equal =
1604 {
1605 return convert_expr_to_smt(*float_equal, converted);
1606 }
1607 if(
1608 const auto float_not_equal =
1610 {
1611 return convert_expr_to_smt(*float_not_equal, converted);
1612 }
1613 if(
1614 const auto converted_relational =
1615 try_relational_conversion(expr, converted))
1616 {
1617 return *converted_relational;
1618 }
1619 if(const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
1620 {
1621 return convert_expr_to_smt(*plus, converted, pointer_sizes);
1622 }
1623 if(const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
1624 {
1625 return convert_expr_to_smt(*minus, converted, pointer_sizes);
1626 }
1627 if(const auto divide = expr_try_dynamic_cast<div_exprt>(expr))
1628 {
1629 return convert_expr_to_smt(*divide, converted);
1630 }
1631 if(
1632 const auto float_operation =
1634 {
1635 return convert_expr_to_smt(*float_operation, converted);
1636 }
1638 {
1639 return convert_expr_to_smt(*truncation_modulo, converted);
1640 }
1641 if(
1642 const auto euclidean_modulo =
1644 {
1645 return convert_expr_to_smt(*euclidean_modulo, converted);
1646 }
1647 if(const auto multiply = expr_try_dynamic_cast<mult_exprt>(expr))
1648 {
1649 return convert_expr_to_smt(*multiply, converted);
1650 }
1651#if 0
1652 else if(expr.id() == ID_floatbv_rem)
1653 {
1654 convert_floatbv_rem(to_binary_expr(expr));
1655 }
1656#endif
1658 {
1659 return convert_expr_to_smt(*address_of, converted, object_map);
1660 }
1661 if(const auto array_of = expr_try_dynamic_cast<array_of_exprt>(expr))
1662 {
1663 return convert_expr_to_smt(*array_of, converted);
1664 }
1665 if(
1666 const auto array_comprehension =
1668 {
1669 return convert_expr_to_smt(*array_comprehension, converted);
1670 }
1671 if(const auto index = expr_try_dynamic_cast<index_exprt>(expr))
1672 {
1673 return convert_expr_to_smt(*index, converted);
1674 }
1675 if(const auto shift = expr_try_dynamic_cast<shift_exprt>(expr))
1676 {
1677 return convert_expr_to_smt(*shift, converted);
1678 }
1679 if(const auto with = expr_try_dynamic_cast<with_exprt>(expr))
1680 {
1681 return convert_expr_to_smt(*with, converted);
1682 }
1683 if(const auto update = expr_try_dynamic_cast<update_exprt>(expr))
1684 {
1685 return convert_expr_to_smt(*update, converted);
1686 }
1688 {
1689 return convert_expr_to_smt(*member_extraction, converted);
1690 }
1691 else if(
1692 const auto pointer_offset =
1694 {
1695 return convert_expr_to_smt(*pointer_offset, converted);
1696 }
1697 else if(
1698 const auto pointer_object =
1700 {
1701 return convert_expr_to_smt(*pointer_object, converted);
1702 }
1703 if(
1704 const auto is_dynamic_object =
1706 {
1707 return convert_expr_to_smt(
1708 *is_dynamic_object, converted, apply_is_dynamic_object);
1709 }
1710 if(
1711 const auto is_invalid_pointer =
1713 {
1714 return convert_expr_to_smt(*is_invalid_pointer, object_map, converted);
1715 }
1717 {
1718 return convert_expr_to_smt(*string_constant, converted);
1719 }
1721 {
1722 return convert_expr_to_smt(*extract_bit, converted);
1723 }
1725 {
1726 return convert_expr_to_smt(*extract_bits, converted);
1727 }
1729 {
1730 return convert_expr_to_smt(*replication, converted);
1731 }
1732 if(
1733 const auto byte_extraction =
1735 {
1736 return convert_expr_to_smt(*byte_extraction, converted);
1737 }
1739 {
1740 return convert_expr_to_smt(*byte_update, converted);
1741 }
1743 {
1744 return convert_expr_to_smt(*absolute_value_of, converted);
1745 }
1746 if(const auto is_nan_expr = expr_try_dynamic_cast<isnan_exprt>(expr))
1747 {
1748 return convert_expr_to_smt(*is_nan_expr, converted);
1749 }
1751 {
1752 return convert_expr_to_smt(*is_finite_expr, converted);
1753 }
1755 {
1756 return convert_expr_to_smt(*is_infinite_expr, converted);
1757 }
1759 {
1760 return convert_expr_to_smt(*is_normal_expr, converted);
1761 }
1762 if(
1764 {
1765 return convert_expr_to_smt(*plus_overflow, converted);
1766 }
1767 if(
1768 const auto minus_overflow =
1770 {
1771 return convert_expr_to_smt(*minus_overflow, converted);
1772 }
1773 if(
1775 {
1776 return convert_expr_to_smt(*mult_overflow, converted);
1777 }
1779 {
1780 return convert_expr_to_smt(*shl_overflow, converted);
1781 }
1783 {
1784 return convert_expr_to_smt(*array_construction, converted);
1785 }
1786 if(const auto literal = expr_try_dynamic_cast<literal_exprt>(expr))
1787 {
1788 return convert_expr_to_smt(*literal, converted);
1789 }
1790 if(const auto for_all = expr_try_dynamic_cast<forall_exprt>(expr))
1791 {
1792 return convert_expr_to_smt(*for_all, converted);
1793 }
1794 if(const auto exists = expr_try_dynamic_cast<exists_exprt>(expr))
1795 {
1796 return convert_expr_to_smt(*exists, converted);
1797 }
1798 if(const auto vector = expr_try_dynamic_cast<vector_exprt>(expr))
1799 {
1800 return convert_expr_to_smt(*vector, converted);
1801 }
1803 {
1805 }
1806 if(const auto let = expr_try_dynamic_cast<let_exprt>(expr))
1807 {
1808 return convert_expr_to_smt(*let, converted);
1809 }
1810 INVARIANT(
1811 expr.id() != ID_constraint_select_one,
1812 "constraint_select_one is not expected in smt conversion: " +
1813 expr.pretty());
1814 if(const auto byte_swap = expr_try_dynamic_cast<bswap_exprt>(expr))
1815 {
1816 return convert_expr_to_smt(*byte_swap, converted);
1817 }
1819 {
1820 return convert_expr_to_smt(*population_count, converted);
1821 }
1822 if(
1823 const auto count_leading_zeros =
1825 {
1826 return convert_expr_to_smt(*count_leading_zeros, converted);
1827 }
1828 if(
1829 const auto count_trailing_zeros =
1831 {
1832 return convert_expr_to_smt(*count_trailing_zeros, converted);
1833 }
1834 if(const auto zero_extend = expr_try_dynamic_cast<zero_extend_exprt>(expr))
1835 {
1836 return convert_expr_to_smt(*zero_extend, converted);
1837 }
1838 if(
1839 const auto prophecy_r_or_w_ok =
1841 {
1842 return convert_expr_to_smt(*prophecy_r_or_w_ok, converted);
1843 }
1844 if(
1845 const auto prophecy_pointer_in_range =
1847 {
1849 }
1850
1852 "Generation of SMT formula for unknown kind of expression: " +
1853 expr.pretty());
1854}
1855
1856#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1857template <typename functiont>
1870
1871template <typename functiont>
1873{
1874 return at_scope_exitt<functiont>(exit_function);
1875}
1876#endif
1877
1879{
1880 expr.visit_pre([](exprt &expr) {
1882 if(!address_of_expr)
1883 return;
1884 const auto array_index_expr =
1886 if(!array_index_expr)
1887 return;
1888 expr = plus_exprt{
1890 array_index_expr->array(),
1892 array_index_expr->index()};
1893 });
1894 return expr;
1895}
1896
1901 const exprt &_expr,
1902 std::function<bool(const exprt &)> filter,
1903 std::function<void(const exprt &)> visitor)
1904{
1905 struct stack_entryt
1906 {
1907 const exprt *e;
1908 bool operands_pushed;
1909 explicit stack_entryt(const exprt *_e) : e(_e), operands_pushed(false)
1910 {
1911 }
1912 };
1913
1914 std::stack<stack_entryt> stack;
1915
1916 stack.emplace(&_expr);
1917
1918 while(!stack.empty())
1919 {
1920 auto &top = stack.top();
1921 if(top.operands_pushed)
1922 {
1923 visitor(*top.e);
1924 stack.pop();
1925 }
1926 else
1927 {
1928 // do modification of 'top' before pushing in case 'top' isn't stable
1929 top.operands_pushed = true;
1930 if(filter(*top.e))
1931 for(auto &op : top.e->operands())
1932 stack.emplace(&op);
1933 }
1934 }
1935}
1936
1938 const exprt &expr,
1939 const smt_object_mapt &object_map,
1942 const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
1943{
1944#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1945 static bool in_conversion = false;
1946 INVARIANT(
1948 "Conversion of expr to smt should be non-recursive. "
1949 "Re-entrance found in conversion of " +
1950 expr.pretty(1, 0));
1951 in_conversion = true;
1952 const auto end_conversion = at_scope_exit([&]() { in_conversion = false; });
1953#endif
1955 const auto lowered_expr = lower_address_of_array_index(expr);
1958 [](const exprt &expr) {
1959 // Code values inside "address of" expressions do not need to be converted
1960 // as the "address of" conversion only depends on the object identifier.
1961 // Avoiding the conversion side steps a need to convert arbitrary code to
1962 // SMT terms.
1964 if(!address_of)
1965 return true;
1966 return !can_cast_type<code_typet>(address_of->object().type());
1967 },
1968 [&](const exprt &expr) {
1969 const auto find_result = sub_expression_map.find(expr);
1970 if(find_result != sub_expression_map.cend())
1971 return;
1973 expr,
1975 object_map,
1978 is_dynamic_object);
1979 sub_expression_map.emplace_hint(find_result, expr, std::move(term));
1980 });
1981 return std::move(sub_expression_map.at(lowered_expr));
1982}
configt config
Definition config.cpp:25
mp_integer bvrep2integer(const irep_idt &src, std::size_t width, bool is_signed)
convert a bit-vector representation (possibly signed) to integer
std::size_t address_bits(const mp_integer &size)
ceil(log2(size))
mp_integer power(const mp_integer &base, const mp_integer &exponent)
A multi-precision implementation of the power operator.
API to expression classes for bitvectors.
const fixedbv_typet & to_fixedbv_type(const typet &type)
Cast a typet to a fixedbv_typet.
bool can_cast_type< integer_bitvector_typet >(const typet &type)
Check whether a reference to a typet is an integer_bitvector_typet.
bool can_cast_type< unsignedbv_typet >(const typet &type)
Check whether a reference to a typet is a unsignedbv_typet.
const floatbv_typet & to_floatbv_type(const typet &type)
Cast a typet to a floatbv_typet.
Expression classes for byte-level operators.
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
typet c_bool_type()
Definition c_types.cpp:100
Absolute value.
Definition std_expr.h:442
Operator to return the address of an object.
ait supplies three of the four components needed: an abstract interpreter (in this case handling func...
Definition ai.h:562
ait()
Definition ai.h:565
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
Boolean AND.
Definition std_expr.h:2125
Expression to define a mapping from an argument (index) to elements.
Definition std_expr.h:3543
Array constructor from list of elements.
Definition std_expr.h:1621
Array constructor from single element.
Definition std_expr.h:1558
Arrays with given size.
Definition std_types.h:807
typet index_type() const
The type of the index expressions into any instance of this type.
Definition std_types.cpp:34
const typet & element_type() const
The type of the elements of the array.
Definition std_types.h:827
exprt & lhs()
Definition std_expr.h:668
exprt & rhs()
Definition std_expr.h:678
exprt & op0()
Definition expr.h:133
exprt & op1()
Definition expr.h:136
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:762
Bit-wise AND.
Bit-wise negation of bit-vectors.
Bit-wise OR.
Base class of fixed-width bit-vector types.
Definition std_types.h:909
std::size_t get_width() const
Definition std_types.h:925
Bit-wise XOR.
The Boolean type.
Definition std_types.h:36
The byte swap expression.
Expression of type type extracted from some object op starting at position offset (given in number of...
Expression corresponding to op() where the bytes starting at position offset (given in number of byte...
The C/C++ Booleans.
Definition c_types.h:97
Concatenation of bit-vector operands.
struct configt::bv_encodingt bv_encoding
A constant literal expression.
Definition std_expr.h:3117
The count leading zeros (counting the number of zero bits starting from the most-significant bit) exp...
The count trailing zeros (counting the number of zero bits starting from the least-significant bit) e...
Division.
Definition std_expr.h:1157
Equality.
Definition std_expr.h:1366
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition std_expr.h:1296
An exists expression.
Base class for all expressions.
Definition expr.h:56
void visit_pre(std::function< void(exprt &)>)
Definition expr.cpp:227
typet & type()
Return the type of the expression.
Definition expr.h:84
operandst & operands()
Definition expr.h:94
Extracts a single bit of a bit-vector operand.
Extracts a sub-range of a bit-vector operand.
Semantic type conversion from/to floating-point formats.
A forall expression.
IEEE-floating-point equality.
IEEE floating-point disequality.
IEEE floating-point operations These have two data operands (op0 and op1) and one rounding mode (op2)...
The trinary if-then-else operator.
Definition std_expr.h:2497
Boolean implication.
Definition std_expr.h:2225
Array index operator.
Definition std_expr.h:1470
Unbounded, signed integers (mathematical integers, not bitvectors)
std::string pretty(unsigned indent=0, unsigned max_indent=0) const
Definition irep.cpp:482
const irep_idt & id() const
Definition irep.h:388
Evaluates to true if the operand is a pointer to a dynamic object.
Evaluates to true if the operand is finite.
Evaluates to true if the operand is infinite.
Evaluates to true if the operand is NaN.
Evaluates to true if the operand is a normal number.
A let expression.
Definition std_expr.h:3331
Extract member of struct or union.
Definition std_expr.h:2971
Binary minus.
Definition std_expr.h:1061
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1228
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:912
Expression to hold a nondeterministic choice.
Definition std_expr.h:292
Boolean negation.
Definition std_expr.h:2454
Disequality.
Definition std_expr.h:1425
Expression for finding the size (in bytes) of the object a pointer points to.
Boolean OR.
Definition std_expr.h:2270
The plus expression Associativity is not specified.
Definition std_expr.h:1002
A numerical identifier for the object a pointer points to.
The offset (in bytes) of a pointer relative to the object.
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
const typet & base_type() const
The type of the data what we point to.
The popcount (counting the number of bits set to 1) expression.
pointer_in_range (see pointer_in_range_exprt) with prophecy expressions to encode whether a pointer r...
A base class for a predicate that indicates that an address range is ok to read or write or both.
Bit-vector replication.
A base class for shift and rotate operators.
Sign of an expression Predicate is true if _op is negative, false otherwise.
Definition std_expr.h:596
static const smt_function_application_termt::factoryt< storet > store
static const smt_function_application_termt::factoryt< selectt > select
static const smt_function_application_termt::factoryt< ort > make_or
static const smt_function_application_termt::factoryt< unsigned_less_than_or_equalt > unsigned_less_than_or_equal
static const smt_function_application_termt::factoryt< signed_less_than_or_equalt > signed_less_than_or_equal
static const smt_function_application_termt::factoryt< addt > add
static const smt_function_application_termt::factoryt< arithmetic_shift_rightt > arithmetic_shift_right
static const smt_function_application_termt::factoryt< signed_greater_than_or_equalt > signed_greater_than_or_equal
static const smt_function_application_termt::factoryt< unsigned_greater_thant > unsigned_greater_than
static const smt_function_application_termt::factoryt< unsigned_remaindert > unsigned_remainder
static const smt_function_application_termt::factoryt< unsigned_greater_than_or_equalt > unsigned_greater_than_or_equal
static const smt_function_application_termt::factoryt< xort > make_xor
static const smt_function_application_termt::factoryt< nott > make_not
static const smt_function_application_termt::factoryt< shift_leftt > shift_left
static const smt_function_application_termt::factoryt< multiplyt > multiply
static smt_function_application_termt::factoryt< sign_extendt > sign_extend(std::size_t i)
static const smt_function_application_termt::factoryt< signed_less_thant > signed_less_than
static smt_function_application_termt::factoryt< zero_extendt > zero_extend(std::size_t i)
static smt_function_application_termt::factoryt< extractt > extract(std::size_t i, std::size_t j)
Makes a factory for extract function applications.
static const smt_function_application_termt::factoryt< signed_greater_thant > signed_greater_than
static const smt_function_application_termt::factoryt< logical_shift_rightt > logical_shift_right
static const smt_function_application_termt::factoryt< negatet > negate
Arithmetic negation in two's complement.
static const smt_function_application_termt::factoryt< concatt > concat
static const smt_function_application_termt::factoryt< unsigned_dividet > unsigned_divide
static const smt_function_application_termt::factoryt< unsigned_less_thant > unsigned_less_than
static const smt_function_application_termt::factoryt< signed_dividet > signed_divide
static const smt_function_application_termt::factoryt< signed_remaindert > signed_remainder
static const smt_function_application_termt::factoryt< subtractt > subtract
static const smt_function_application_termt::factoryt< andt > make_and
static const smt_function_application_termt::factoryt< distinctt > distinct
Makes applications of the function which returns true iff its two arguments are not identical.
static const smt_function_application_termt::factoryt< if_then_elset > if_then_else
static const smt_function_application_termt::factoryt< impliest > implies
static const smt_function_application_termt::factoryt< ort > make_or
static const smt_function_application_termt::factoryt< equalt > equal
static const smt_function_application_termt::factoryt< andt > make_and
static const smt_function_application_termt::factoryt< xort > make_xor
static const smt_function_application_termt::factoryt< nott > make_not
Stores identifiers in unescaped and unquoted form.
Definition smt_terms.h:93
const smt_sortt & get_sort() const
Definition smt_terms.cpp:36
Struct constructor from list of elements.
Definition std_expr.h:1877
Expression to hold a symbol (variable)
Definition std_expr.h:131
const irep_idt & get_identifier() const
Definition std_expr.h:160
Semantic type conversion.
Definition std_expr.h:2073
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:391
The unary minus expression.
Definition std_expr.h:484
The unary plus expression.
Definition std_expr.h:531
Union constructor from single element.
Definition std_expr.h:1770
Operator to update elements in structs and arrays.
Definition std_expr.h:2782
Vector constructor from list of elements.
Definition std_expr.h:1734
Operator to update elements in structs and arrays.
Definition std_expr.h:2598
Boolean XOR.
Definition std_expr.h:2370
zero extension The operand is converted to the given type by either a) truncating if the new type is ...
void filtered_visit_post(const exprt &_expr, std::function< bool(const exprt &)> filter, std::function< void(const exprt &)> visitor)
Post order traversal where the children of a node are only visited if applying the filter function to...
exprt lower_address_of_array_index(exprt expr)
Lower the address_of(array[idx]) sub expressions in expr to idx + address_of(array),...
static smt_termt convert_bit_vector_cast(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
static std::optional< smt_termt > try_relational_conversion(const exprt &expr, const sub_expression_mapt &converted)
static smt_termt most_significant_bit_is_set(const smt_termt &input)
Constructs a term which is true if the most significant bit of input is set.
static smt_termt convert_array_update_to_smt(const with_exprt &with, const sub_expression_mapt &converted)
static smt_termt make_bitvector_resize_cast(const smt_termt &from_term, const bitvector_typet &from_type, const bitvector_typet &to_type)
static std::function< std::function< smt_termt(smt_termt)>(std::size_t)> extension_for_type(const typet &type)
static smt_termt convert_multiary_operator_to_terms(const multi_ary_exprt &expr, const sub_expression_mapt &converted, const factoryt &factory)
Converts operator expressions with 2 or more operands to terms expressed as binary operator applicati...
std::unordered_map< exprt, smt_termt, irep_hash > sub_expression_mapt
Post order visitation is used in order to construct the the smt terms bottom upwards without using re...
static smt_termt make_not_zero(const smt_termt &input, const typet &source_type)
Makes a term which is true if input is not 0 / false.
static smt_termt convert_relational_to_smt(const binary_relation_exprt &binary_relation, const unsigned_factory_typet &unsigned_factory, const signed_factory_typet &signed_factory, const sub_expression_mapt &converted)
static smt_termt dispatch_expr_to_smt_conversion(const exprt &expr, const sub_expression_mapt &converted, const smt_object_mapt &object_map, const type_size_mapt &pointer_sizes, const smt_object_sizet::make_applicationt &call_object_size, const smt_is_dynamic_objectt::make_applicationt &apply_is_dynamic_object)
static smt_termt convert_to_smt_shift(const factoryt &factory, const shiftt &shift, const sub_expression_mapt &converted)
static smt_sortt convert_type_to_smt_sort(const bool_typet &type)
static smt_termt convert_c_bool_cast(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
Returns a cast to C bool expressed in smt terms.
at_scope_exitt< functiont > at_scope_exit(functiont exit_function)
static bool operands_are_of_type(const exprt &expr)
Ensures that all operands of the argument expression have related types.
static smt_termt convert_expr_to_smt(const symbol_exprt &symbol_expr)
Templated functions to cast to specific exprt-derived classes.
API to expression classes for floating-point arithmetic.
std::string from_type(const namespacet &ns, const irep_idt &identifier, const typet &type)
API to expression classes for 'mathematical' expressions.
mini_bddt exists(const mini_bddt &u, const unsigned var)
Definition miniBDD.cpp:556
mp_integer bitwise_xor(const mp_integer &a, const mp_integer &b)
bitwise 'xor' of two nonnegative integers
Definition mp_arith.cpp:239
exprt make_invalid_pointer_expr()
Create the invalid pointer constant.
exprt find_object_base_expression(const address_of_exprt &address_of)
The model of addresses we use consists of a unique object identifier and an offset.
std::unordered_map< exprt, decision_procedure_objectt, irep_hash > smt_object_mapt
Mapping from an object's base expression to the set of information about it which we track.
API to expression classes for Pointers.
bool can_cast_type< pointer_typet >(const typet &type)
Check whether a reference to a typet is a pointer_typet.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
exprt pointer_offset(const exprt &pointer)
exprt object_size(const exprt &pointer)
exprt pointer_object(const exprt &p)
Various predicates over pointers in programs.
Ranges: pair of begin and end iterators, which can be initialized from containers,...
ranget< iteratort > make_range(iteratort begin, iteratort end)
Definition range.h:522
#define UNIMPLEMENTED_FEATURE(FEATURE)
Definition invariant.h:549
#define UNREACHABLE
This should be used to mark dead code.
Definition invariant.h:525
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
#define UNHANDLED_CASE
Definition invariant.h:559
#define POSTCONDITION(CONDITION)
Definition invariant.h:479
#define UNREACHABLE_BECAUSE(REASON)
Definition invariant.h:526
API to expression classes.
const binary_exprt & to_binary_expr(const exprt &expr)
Cast an exprt to a binary_exprt.
Definition std_expr.h:715
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:426
bool can_cast_type< code_typet >(const typet &type)
Check whether a reference to a typet is a code_typet.
Definition std_types.h:775
binary_relation_exprt less_than(exprt lhs, exprt rhs)
Definition string_expr.h:49
binary_relation_exprt greater_than(exprt lhs, exprt rhs)
Definition string_expr.h:26
at_scope_exitt(functiont exit_function)
void visit(const smt_array_sortt &) override
sort_based_cast_to_bit_vector_convertert(const smt_termt &from_term, const typet &from_type, const bitvector_typet &to_type)
void visit(const smt_bool_sortt &) override
void visit(const smt_bit_vector_sortt &) override
void visit(const smt_array_sortt &array_sort) override
void visit(const smt_bit_vector_sortt &bit_vector_sort) override
std::optional< smt_termt > result
void visit(const smt_bool_sortt &) override
sort_based_literal_convertert(const constant_exprt &input)
std::unordered_map< typet, smt_termt, irep_hash > type_size_mapt