CBMC
Loading...
Searching...
No Matches
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 // Convert floating-point to bitvector for bit-blasting
102 return smt_bit_vector_sortt{type.get_width()};
103}
104
106{
107 if(const auto bool_type = type_try_dynamic_cast<bool_typet>(type))
108 {
110 }
112 {
114 {
116 }
118 }
120 {
122 }
123 UNIMPLEMENTED_FEATURE("Generation of SMT formula for type: " + type.pretty());
124}
125
127{
129 symbol_expr.identifier(), convert_type_to_smt_sort(symbol_expr.type())};
130}
131
134 const sub_expression_mapt &converted)
135{
136 // A nondet_symbol is a reference to an unconstrained function. This function
137 // will already have been added as a dependency.
139 nondet_symbol.get_identifier(),
141}
142
145{
146 if(input.get_sort().cast<smt_bool_sortt>())
147 return input;
148 if(const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>())
149 {
152 }
154}
155
158 const smt_termt &from_term,
159 const typet &from_type,
160 const bitvector_typet &to_type)
161{
162 const std::size_t c_bool_width = to_type.get_width();
164 make_not_zero(from_term, from_type),
167}
168
169static std::function<std::function<smt_termt(smt_termt)>(std::size_t)>
182
184 const smt_termt &from_term,
186 const bitvector_typet &to_type)
187{
189 {
191 "Generation of SMT formula for type cast to fixed-point bitvector "
192 "type: " +
193 to_type.pretty());
194 }
195 // After float lowering, floatbv types are treated as bitvectors.
196 // Same-width casts (e.g., from float_bvt::pack) are handled below.
197 const std::size_t from_width = from_type.get_width();
198 const std::size_t to_width = to_type.get_width();
199 if(to_width == from_width)
200 return from_term;
201 if(to_width < from_width)
202 return smt_bit_vector_theoryt::extract(to_width - 1, 0)(from_term);
203 const std::size_t extension_size = to_width - from_width;
204 return extension_for_type(from_type)(extension_size)(from_term);
205}
206
209{
213 std::optional<smt_termt> result;
214
222
223 void visit(const smt_bool_sortt &) override
224 {
226 from_term, from_type, c_bool_typet{to_type.get_width()});
227 }
228
229 void visit(const smt_bit_vector_sortt &) override
230 {
233 else
235 "Generation of SMT formula for type cast to bit vector from type: " +
236 from_type.pretty());
237 }
238
239 void visit(const smt_array_sortt &) override
240 {
242 "Generation of SMT formula for type cast to bit vector from type: " +
243 from_type.pretty());
244 }
245};
246
248 const smt_termt &from_term,
249 const typet &from_type,
250 const bitvector_typet &to_type)
251{
253 from_term, from_type, to_type};
254 from_term.get_sort().accept(converter);
255 POSTCONDITION(converter.result);
256 return *converter.result;
257}
258
260 const typecast_exprt &cast,
261 const sub_expression_mapt &converted)
262{
263 const auto &from_term = converted.at(cast.op());
264 const typet &from_type = cast.op().type();
265 const typet &to_type = cast.type();
267 return make_not_zero(from_term, cast.op().type());
268 if(const auto c_bool_type = type_try_dynamic_cast<c_bool_typet>(to_type))
269 return convert_c_bool_cast(from_term, from_type, *c_bool_type);
270 if(const auto bit_vector = type_try_dynamic_cast<bitvector_typet>(to_type))
271 return convert_bit_vector_cast(from_term, from_type, *bit_vector);
273 "Generation of SMT formula for type cast expression: " + cast.pretty());
274}
275
278 const sub_expression_mapt &converted)
279{
280 // Floating-point operations should be lowered to bitvector operations
281 // before reaching this point. If we get here, it means the lowering failed.
283 "Floating point type cast expression should have been lowered to "
284 "bitvector operations: " +
285 float_cast.pretty());
286}
287
290 const sub_expression_mapt &converted)
291{
293 "Generation of SMT formula for struct construction expression: " +
294 struct_construction.pretty());
295}
296
299 const sub_expression_mapt &converted)
300{
302 "Generation of SMT formula for union construction expression: " +
303 union_construction.pretty());
304}
305
307{
309 std::optional<smt_termt> result;
310
312 : member_input{input}
313 {
314 }
315
316 void visit(const smt_bool_sortt &) override
317 {
319 }
320
322 {
323 const auto &width = bit_vector_sort.bit_width();
324 // We get the value using a non-signed interpretation, as smt bit vector
325 // terms do not carry signedness.
326 const auto value = bvrep2integer(member_input.get_value(), width, false);
328 }
329
330 void visit(const smt_array_sortt &array_sort) override
331 {
333 "Conversion of array SMT literal " + array_sort.pretty());
334 }
335};
336
338{
339 if(constant_literal.is_null_pointer())
340 {
341 const size_t bit_width =
343 // An address of 0 encodes an object identifier of 0 for the NULL object
344 // and an offset of 0 into the object.
345 const auto address = 0;
346 return smt_bit_vector_constant_termt{address, bit_width};
347 }
348 if(constant_literal.type() == integer_typet{})
349 {
350 // This is converting integer constants into bit vectors for use with
351 // bit vector based smt logics. As bit vector widths are not specified for
352 // non bit vector types, this chooses a width based on the minimum needed
353 // to hold the integer constant value.
355 return smt_bit_vector_constant_termt{value, address_bits(value + 1)};
356 }
357 const auto sort = convert_type_to_smt_sort(constant_literal.type());
359 sort.accept(converter);
360 return *converter.result;
361}
362
365 const sub_expression_mapt &converted)
366{
368 {
371 }
373 "Generation of SMT formula for concatenation expression: " +
374 concatenation.pretty());
375}
376
379 const sub_expression_mapt &converted)
380{
382 {
385 }
386 else
387 {
389 "Generation of SMT formula for bitwise and expression: " +
390 bitwise_and_expr.pretty());
391 }
392}
393
396 const sub_expression_mapt &converted)
397{
399 {
402 }
403 else
404 {
406 "Generation of SMT formula for bitwise or expression: " +
407 bitwise_or_expr.pretty());
408 }
409}
410
413 const sub_expression_mapt &converted)
414{
416 {
419 }
420 else
421 {
423 "Generation of SMT formula for bitwise xor expression: " +
424 bitwise_xor.pretty());
425 }
426}
427
429 const bitnot_exprt &bitwise_not,
430 const sub_expression_mapt &converted)
431{
432 if(can_cast_type<bitvector_typet>(bitwise_not.op().type()))
433 {
434 return smt_bit_vector_theoryt::make_not(converted.at(bitwise_not.op()));
435 }
436 else
437 {
439 "Generation of SMT formula for bitnot_exprt: " + bitwise_not.pretty());
440 }
441}
442
444 const unary_minus_exprt &unary_minus,
445 const sub_expression_mapt &converted)
446{
447 if(can_cast_type<integer_bitvector_typet>(unary_minus.op().type()))
448 {
449 return smt_bit_vector_theoryt::negate(converted.at(unary_minus.op()));
450 }
451 else
452 {
454 "Generation of SMT formula for unary minus expression: " +
455 unary_minus.pretty());
456 }
457}
458
460 const unary_plus_exprt &unary_plus,
461 const sub_expression_mapt &converted)
462{
464 "Generation of SMT formula for unary plus expression: " +
465 unary_plus.pretty());
466}
467
469 const sign_exprt &is_negative,
470 const sub_expression_mapt &converted)
471{
473 "Generation of SMT formula for \"is negative\" expression: " +
474 is_negative.pretty());
475}
476
478 const if_exprt &if_expression,
479 const sub_expression_mapt &converted)
480{
482 converted.at(if_expression.cond()),
483 converted.at(if_expression.true_case()),
484 converted.at(if_expression.false_case()));
485}
486
494
502
510
512 const implies_exprt &implies,
513 const sub_expression_mapt &converted)
514{
516 converted.at(implies.op0()), converted.at(implies.op1()));
517}
518
520 const not_exprt &logical_not,
521 const sub_expression_mapt &converted)
522{
523 return smt_core_theoryt::make_not(converted.at(logical_not.op()));
524}
525
527 const equal_exprt &equal,
528 const sub_expression_mapt &converted)
529{
531 converted.at(equal.op0()), converted.at(equal.op1()));
532}
533
535 const notequal_exprt &not_equal,
536 const sub_expression_mapt &converted)
537{
539 converted.at(not_equal.op0()), converted.at(not_equal.op1()));
540}
541
544 const sub_expression_mapt &converted)
545{
547 "Floating point equality expression should have been lowered to "
548 "bitvector operations: " +
549 float_equal.pretty());
550}
551
554 const sub_expression_mapt &converted)
555{
557 "Floating point not equal expression should have been lowered to "
558 "bitvector operations: " +
559 float_not_equal.pretty());
560}
561
562template <typename unsigned_factory_typet, typename signed_factory_typet>
567 const sub_expression_mapt &converted)
568{
569 PRECONDITION(binary_relation.lhs().type() == binary_relation.rhs().type());
570 const auto &lhs = converted.at(binary_relation.lhs());
571 const auto &rhs = converted.at(binary_relation.rhs());
572 const typet operand_type = binary_relation.lhs().type();
574 {
575 // The code here is operating under the assumption that the comparison
576 // operands have types for which the comparison makes sense.
577
578 // We already know this is the case given that we have followed
579 // the if statement branch, but including the same check here
580 // for consistency (it's cheap).
581 const auto lhs_type_is_pointer =
583 const auto rhs_type_is_pointer =
585 INVARIANT(
587 "pointer comparison requires that both operand types are pointers.");
588 return unsigned_factory(lhs, rhs);
589 }
590 else if(lhs.get_sort().cast<smt_bit_vector_sortt>())
591 {
593 return unsigned_factory(lhs, rhs);
595 return signed_factory(lhs, rhs);
596 }
597
599 "Generation of SMT formula for relational expression: " +
600 binary_relation.pretty());
601}
602
603static std::optional<smt_termt> try_relational_conversion(
604 const exprt &expr,
605 const sub_expression_mapt &converted)
606{
608 {
613 converted);
614 }
615 if(
616 const auto greater_than_or_equal =
618 {
620 *greater_than_or_equal,
623 converted);
624 }
626 {
628 *less_than,
631 converted);
632 }
633 if(
634 const auto less_than_or_equal =
636 {
638 *less_than_or_equal,
641 converted);
642 }
643 return {};
644}
645
647 const plus_exprt &plus,
648 const sub_expression_mapt &converted,
650{
651 if(std::all_of(
652 plus.operands().cbegin(), plus.operands().cend(), [](exprt operand) {
653 return can_cast_type<integer_bitvector_typet>(operand.type());
654 }))
655 {
657 plus, converted, smt_bit_vector_theoryt::add);
658 }
659 else if(can_cast_type<pointer_typet>(plus.type()))
660 {
661 INVARIANT(
662 plus.operands().size() == 2,
663 "We are only handling a binary version of plus when it has a pointer "
664 "operand");
665
666 exprt pointer;
668 for(auto &operand : plus.operands())
669 {
671 {
672 pointer = operand;
673 }
674 else
675 {
676 scalar = operand;
677 }
678 }
679
680 // We need to ensure that we follow this code path only if the expression
681 // our assumptions about the structure of the addition expression hold.
682 INVARIANT(
684 "An addition expression with both operands being pointers when they are "
685 "not dereferenced is malformed");
686
689 const auto base_type = pointer_type.base_type();
690 const auto pointer_size = pointer_sizes.at(base_type);
691
693 converted.at(pointer),
695 }
696 else
697 {
699 "Generation of SMT formula for plus expression: " + plus.pretty());
700 }
701}
702
704 const minus_exprt &minus,
705 const sub_expression_mapt &converted,
707{
708 const bool both_operands_bitvector =
711
712 const bool lhs_is_pointer = can_cast_type<pointer_typet>(minus.lhs().type());
713 const bool rhs_is_pointer = can_cast_type<pointer_typet>(minus.rhs().type());
714
716
717 // We don't really handle this - we just compute this to fall
718 // into an if-else branch that gives proper error handling information.
720
722 {
724 converted.at(minus.lhs()), converted.at(minus.rhs()));
725 }
727 {
728 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
729 const auto rhs_base_type = to_pointer_type(minus.rhs().type()).base_type();
730 INVARIANT(
732 "only pointers of the same object type can be subtracted.");
735 converted.at(minus.lhs()), converted.at(minus.rhs())),
737 }
738 else if(one_operand_pointer)
739 {
740 // It's semantically void to have an expression `3 - a` where `a`
741 // is a pointer.
742 INVARIANT(
744 "minus expressions of pointer and integer expect lhs to be the pointer");
745 const auto lhs_base_type = to_pointer_type(minus.lhs().type()).base_type();
746
748 converted.at(minus.lhs()),
750 converted.at(minus.rhs()), pointer_sizes.at(lhs_base_type)));
751 }
752 else
753 {
755 "Generation of SMT formula for minus expression: " + minus.pretty());
756 }
757}
758
760 const div_exprt &divide,
761 const sub_expression_mapt &converted)
762{
763 const smt_termt &lhs = converted.at(divide.lhs());
764 const smt_termt &rhs = converted.at(divide.rhs());
765
766 const bool both_operands_bitvector =
769
770 const bool both_operands_unsigned =
773
775 {
777 {
779 }
780 else
781 {
783 }
784 }
785 else
786 {
788 "Generation of SMT formula for divide expression: " + divide.pretty());
789 }
790}
791
794 const sub_expression_mapt &converted)
795{
796 // This case includes the floating point plus, minus, division and
797 // multiplication operations.
799 "Floating point operation expression should have been lowered to "
800 "bitvector operations: " +
801 float_operation.pretty());
802}
803
806 const sub_expression_mapt &converted)
807{
808 const smt_termt &lhs = converted.at(truncation_modulo.lhs());
809 const smt_termt &rhs = converted.at(truncation_modulo.rhs());
810
811 const bool both_operands_bitvector =
814
815 const bool both_operands_unsigned =
818
820 {
822 {
824 }
825 else
826 {
828 }
829 }
830 else
831 {
833 "Generation of SMT formula for remainder (modulus) expression: " +
834 truncation_modulo.pretty());
835 }
836}
837
840 const sub_expression_mapt &converted)
841{
843 "Generation of SMT formula for euclidean modulo expression: " +
844 euclidean_modulo.pretty());
845}
846
848 const mult_exprt &multiply,
849 const sub_expression_mapt &converted)
850{
851 if(std::all_of(
852 multiply.operands().cbegin(),
853 multiply.operands().cend(),
854 [](exprt operand) {
855 return can_cast_type<integer_bitvector_typet>(operand.type());
856 }))
857 {
859 multiply, converted, smt_bit_vector_theoryt::multiply);
860 }
861 else
862 {
864 "Generation of SMT formula for multiply expression: " +
865 multiply.pretty());
866 }
867}
868
878 const sub_expression_mapt &converted,
879 const smt_object_mapt &object_map)
880{
881 const auto type = type_try_dynamic_cast<pointer_typet>(address_of.type());
882 INVARIANT(
883 type, "Result of the address_of operator should have pointer type.");
884 const auto base = find_object_base_expression(address_of);
885 const auto object = object_map.find(base);
886 INVARIANT(
887 object != object_map.end(),
888 "Objects should be tracked before converting their address to SMT terms");
889 const std::size_t object_id = object->second.unique_id;
890 const std::size_t object_bits = config.bv_encoding.object_bits;
891 const std::size_t max_objects = std::size_t(1) << object_bits;
893 {
895 "too many addressed objects: maximum number of objects is set to 2^n=" +
896 std::to_string(max_objects) + " (with n=" + std::to_string(object_bits) +
897 "); " +
898 "use the `--object-bits n` option to increase the maximum number"};
899 }
902 INVARIANT(
903 type->get_width() > object_bits,
904 "Pointer should be wider than object_bits in order to allow for offset "
905 "encoding.");
906 const size_t offset_bits = type->get_width() - object_bits;
908 {
911 }
913 "Generation of SMT formula for address of expression: " +
914 address_of.pretty());
915}
916
919 const sub_expression_mapt &converted)
920{
921 // This function is unreachable as the `array_of_exprt` nodes are already
922 // fully converted by the incremental decision procedure functions
923 // (smt2_incremental_decision_proceduret::define_array_function).
925}
926
929 const sub_expression_mapt &converted)
930{
932 "Generation of SMT formula for array comprehension expression: " +
933 array_comprehension.pretty());
934}
935
937 const index_exprt &index_of,
938 const sub_expression_mapt &converted)
939{
940 const smt_termt &array = converted.at(index_of.array());
941 const smt_termt &index = converted.at(index_of.index());
942 return smt_array_theoryt::select(array, index);
943}
944
945template <typename factoryt, typename shiftt>
947 const factoryt &factory,
948 const shiftt &shift,
949 const sub_expression_mapt &converted)
950{
951 const smt_termt &first_operand = converted.at(shift.op0());
952 const smt_termt &second_operand = converted.at(shift.op1());
953 const auto first_bit_vector_sort =
954 first_operand.get_sort().cast<smt_bit_vector_sortt>();
955 const auto second_bit_vector_sort =
956 second_operand.get_sort().cast<smt_bit_vector_sortt>();
957 INVARIANT(
959 "Shift expressions are expected to have bit vector operands.");
960 INVARIANT(
961 shift.type() == shift.op0().type(),
962 "Shift expression type must be equals to first operand type.");
963 const std::size_t first_width = first_bit_vector_sort->bit_width();
964 const std::size_t second_width = second_bit_vector_sort->bit_width();
966 {
967 return factory(
969 extension_for_type(shift.op1().type())(first_width - second_width)(
971 }
972 else if(first_width < second_width)
973 {
974 const auto result = factory(
975 extension_for_type(shift.op0().type())(second_width - first_width)(
978 return smt_bit_vector_theoryt::extract(first_width - 1, 0)(result);
979 }
980 else
981 {
982 return factory(first_operand, second_operand);
983 }
984}
985
987 const shift_exprt &shift,
988 const sub_expression_mapt &converted)
989{
990 // TODO: Dispatch for rotation expressions. A `shift_exprt` can be a rotation.
991 if(const auto left_shift = expr_try_dynamic_cast<shl_exprt>(shift))
992 {
994 smt_bit_vector_theoryt::shift_left, *left_shift, converted);
995 }
997 {
1001 converted);
1002 }
1004 {
1005 return convert_to_smt_shift(
1008 converted);
1009 }
1011 "Generation of SMT formula for shift expression: " + shift.pretty());
1012}
1013
1015 const with_exprt &with,
1016 const sub_expression_mapt &converted)
1017{
1018 smt_termt array = converted.at(with.old());
1019 const smt_termt &index_term = converted.at(with.where());
1020 const smt_termt &value_term = converted.at(with.new_value());
1022 return array;
1023}
1024
1026 const with_exprt &with,
1027 const sub_expression_mapt &converted)
1028{
1030 return convert_array_update_to_smt(with, converted);
1031 // 'with' expression is also used to update struct fields, but for now we do
1032 // not support them, so we fail.
1034 "Generation of SMT formula for with expression: " + with.pretty());
1035}
1036
1038 const update_exprt &update,
1039 const sub_expression_mapt &converted)
1040{
1042 "Generation of SMT formula for update expression: " + update.pretty());
1043}
1044
1047 const sub_expression_mapt &converted)
1048{
1050 "Generation of SMT formula for member extraction expression: " +
1051 member_extraction.pretty());
1052}
1053
1055 const is_dynamic_object_exprt &is_dynamic_object,
1056 const sub_expression_mapt &converted,
1058{
1059 const smt_termt &pointer = converted.at(is_dynamic_object.address());
1060 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1061 INVARIANT(
1062 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1063 const std::size_t pointer_width = pointer_sort->bit_width();
1065 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1066 pointer_width - 1,
1067 pointer_width - config.bv_encoding.object_bits)(pointer)});
1068}
1069
1072 const smt_object_mapt &object_map,
1073 const sub_expression_mapt &converted)
1074{
1075 const exprt &pointer_expr(to_unary_expr(is_invalid_pointer).op());
1078 INVARIANT(pointer_type, "Pointer object should have a bitvector-based type.");
1079 const std::size_t object_bits = config.bv_encoding.object_bits;
1080 const std::size_t width = pointer_type->get_width();
1081 INVARIANT(
1082 width >= object_bits,
1083 "Width should be at least as big as the number of object bits.");
1084
1086 width - 1, width - object_bits)(converted.at(pointer_expr));
1087
1088 const auto &invalid_pointer = object_map.at(make_invalid_pointer_expr());
1089
1091 invalid_pointer.unique_id, config.bv_encoding.object_bits);
1092
1094}
1095
1098 const sub_expression_mapt &converted)
1099{
1101 "Generation of SMT formula for string constant expression: " +
1102 string_constant.pretty());
1103}
1104
1107 const sub_expression_mapt &converted)
1108{
1110 "Generation of SMT formula for extract bit expression: " +
1111 extract_bit.pretty());
1112}
1113
1116 const sub_expression_mapt &converted)
1117{
1118 const smt_termt &from = converted.at(extract_bits.src());
1119 const auto bit_vector_sort =
1121 INVARIANT(
1122 bit_vector_sort, "Extract can only be applied to bit vector terms.");
1124 if(index_value)
1126 *index_value + bit_vector_sort->bit_width() - 1, *index_value)(from);
1128 "Generation of SMT formula for extract bits expression: " +
1129 extract_bits.pretty());
1130}
1131
1134 const sub_expression_mapt &converted)
1135{
1137 "Generation of SMT formula for bit vector replication expression: " +
1138 replication.pretty());
1139}
1140
1143 const sub_expression_mapt &converted)
1144{
1146 "Generation of SMT formula for byte extract expression: " +
1147 byte_extraction.pretty());
1148}
1149
1152 const sub_expression_mapt &converted)
1153{
1155 "Generation of SMT formula for byte update expression: " +
1156 byte_update.pretty());
1157}
1158
1161 const sub_expression_mapt &converted)
1162{
1164 "Generation of SMT formula for absolute value of expression: " +
1165 absolute_value_of.pretty());
1166}
1167
1169 const isnan_exprt &is_nan_expr,
1170 const sub_expression_mapt &converted)
1171{
1173 "Is not a number expression should have been lowered to "
1174 "bitvector operations: " +
1175 is_nan_expr.pretty());
1176}
1177
1180 const sub_expression_mapt &converted)
1181{
1183 "Is finite expression should have been lowered to "
1184 "bitvector operations: " +
1185 is_finite_expr.pretty());
1186}
1187
1190 const sub_expression_mapt &converted)
1191{
1193 "Is infinite expression should have been lowered to "
1194 "bitvector operations: " +
1195 is_infinite_expr.pretty());
1196}
1197
1200 const sub_expression_mapt &converted)
1201{
1203 "Is normal expression should have been lowered to "
1204 "bitvector operations: " +
1205 is_normal_expr.pretty());
1206}
1207
1212{
1213 const auto bit_vector_sort = input.get_sort().cast<smt_bit_vector_sortt>();
1214 INVARIANT(
1216 "Most significant bit can only be extracted from bit vector terms.");
1217 const size_t most_significant_bit_index = bit_vector_sort->bit_width() - 1;
1222}
1223
1226 const sub_expression_mapt &converted)
1227{
1228 const smt_termt &left = converted.at(plus_overflow.lhs());
1229 const smt_termt &right = converted.at(plus_overflow.rhs());
1231 {
1235 }
1237 {
1238 // Overflow has occurred if the operands have the same sign and adding them
1239 // gives a result of the opposite sign.
1245 msb_left,
1247 }
1249 "Generation of SMT formula for plus overflow expression: " +
1250 plus_overflow.pretty());
1251}
1252
1255 const sub_expression_mapt &converted)
1256{
1257 const smt_termt &left = converted.at(minus_overflow.lhs());
1258 const smt_termt &right = converted.at(minus_overflow.rhs());
1260 {
1262 }
1264 {
1265 // Overflow has occurred if the operands have the opposing signs and
1266 // subtracting them gives a result having the same signedness as the
1267 // right-hand operand. For example the following would be overflow for cases
1268 // for 8 bit wide bit vectors -
1269 // -128 - 1 == 127
1270 // 127 - (-1) == -128
1276 msb_right,
1278 smt_bit_vector_theoryt::subtract(left, right))));
1279 }
1281 "Generation of SMT formula for minus overflow expression: " +
1282 minus_overflow.pretty());
1283}
1284
1287 const sub_expression_mapt &converted)
1288{
1289 PRECONDITION(mult_overflow.lhs().type() == mult_overflow.rhs().type());
1290 const auto &operand_type = mult_overflow.lhs().type();
1291 const smt_termt &left = converted.at(mult_overflow.lhs());
1292 const smt_termt &right = converted.at(mult_overflow.rhs());
1293 if(
1294 const auto unsigned_type =
1296 {
1297 const std::size_t width = unsigned_type->get_width();
1298 const auto extend = smt_bit_vector_theoryt::zero_extend(width);
1301 smt_bit_vector_constant_termt{power(2, width), width * 2});
1302 }
1303 if(
1304 const auto signed_type =
1306 {
1309 const std::size_t width = signed_type->get_width();
1310 const auto extend = smt_bit_vector_theoryt::sign_extend(width);
1311 const auto multiplication =
1315 smt_bit_vector_constant_termt{power(2, width - 1), width * 2});
1319 smt_bit_vector_constant_termt{power(2, width - 1), width * 2}));
1322 }
1324 "Generation of SMT formula for multiply overflow expression: " +
1325 mult_overflow.pretty());
1326}
1327
1330 const sub_expression_mapt &converted)
1331{
1332 const auto type =
1334 INVARIANT(type, "Pointer object should have a bitvector-based type.");
1335 const auto converted_expr = converted.at(pointer_object.pointer());
1336 const std::size_t width = type->get_width();
1337 const std::size_t object_bits = config.bv_encoding.object_bits;
1338 INVARIANT(
1339 width >= object_bits,
1340 "Width should be at least as big as the number of object bits.");
1341 const std::size_t ext = width - object_bits;
1343 width - 1, width - object_bits)(converted_expr);
1344 if(ext > 0)
1345 {
1347 }
1348 return extract_op;
1349}
1350
1353 const sub_expression_mapt &converted)
1354{
1355 const auto type =
1357 INVARIANT(type, "Pointer offset should have a bitvector-based type.");
1358 const auto converted_expr = converted.at(pointer_offset.pointer());
1359 const std::size_t width = type->get_width();
1360 std::size_t offset_bits = width - config.bv_encoding.object_bits;
1361 if(offset_bits > width)
1362 offset_bits = width;
1363 const auto extract_op =
1365 if(width > offset_bits)
1366 {
1368 }
1369 return extract_op;
1370}
1371
1374 const sub_expression_mapt &converted)
1375{
1377 "Generation of SMT formula for shift left overflow expression: " +
1378 shl_overflow.pretty());
1379}
1380
1383 const sub_expression_mapt &converted)
1384{
1385 // This function is unreachable as the `array_exprt` nodes are already fully
1386 // converted by the incremental decision procedure functions
1387 // (smt2_incremental_decision_proceduret::define_array_function).
1389}
1390
1392 const literal_exprt &literal,
1393 const sub_expression_mapt &converted)
1394{
1396 "Generation of SMT formula for literal expression: " + literal.pretty());
1397}
1398
1400 const forall_exprt &for_all,
1401 const sub_expression_mapt &converted)
1402{
1404 "Generation of SMT formula for for all expression: " + for_all.pretty());
1405}
1406
1408 const exists_exprt &exists,
1409 const sub_expression_mapt &converted)
1410{
1412 "Generation of SMT formula for exists expression: " + exists.pretty());
1413}
1414
1416 const vector_exprt &vector,
1417 const sub_expression_mapt &converted)
1418{
1420 "Generation of SMT formula for vector expression: " + vector.pretty());
1421}
1422
1425 const sub_expression_mapt &converted,
1427{
1428 const smt_termt &pointer = converted.at(object_size.pointer());
1429 const auto pointer_sort = pointer.get_sort().cast<smt_bit_vector_sortt>();
1430 INVARIANT(
1431 pointer_sort, "Pointers should be encoded as bit vector sorted terms.");
1432 const std::size_t pointer_width = pointer_sort->bit_width();
1433 return call_object_size(
1434 std::vector<smt_termt>{smt_bit_vector_theoryt::extract(
1435 pointer_width - 1,
1436 pointer_width - config.bv_encoding.object_bits)(pointer)});
1437}
1438
1439static smt_termt
1441{
1443 "Generation of SMT formula for let expression: " + let.pretty());
1444}
1445
1447 const bswap_exprt &byte_swap,
1448 const sub_expression_mapt &converted)
1449{
1451 "Generation of SMT formula for byte swap expression: " +
1452 byte_swap.pretty());
1453}
1454
1457 const sub_expression_mapt &converted)
1458{
1460 "Generation of SMT formula for population count expression: " +
1461 population_count.pretty());
1462}
1463
1466 const sub_expression_mapt &converted)
1467{
1469 "Generation of SMT formula for count leading zeros expression: " +
1470 count_leading_zeros.pretty());
1471}
1472
1475 const sub_expression_mapt &converted)
1476{
1478 "Generation of SMT formula for count trailing zeros expression: " +
1479 count_trailing_zeros.pretty());
1480}
1481
1483 const zero_extend_exprt &zero_extend,
1484 const sub_expression_mapt &converted)
1485{
1487 "zero_extend expression should have been lowered by the decision "
1488 "procedure before conversion to smt terms");
1489}
1490
1493 const sub_expression_mapt &converted)
1494{
1496 "prophecy_r_or_w_ok expression should have been lowered by the decision "
1497 "procedure before conversion to smt terms");
1498}
1499
1502 const sub_expression_mapt &converted)
1503{
1505 "prophecy_pointer_in_range expression should have been lowered by the "
1506 "decision procedure before conversion to smt terms");
1507}
1508
1510 const exprt &expr,
1511 const sub_expression_mapt &converted,
1512 const smt_object_mapt &object_map,
1516{
1517 if(const auto symbol = expr_try_dynamic_cast<symbol_exprt>(expr))
1518 {
1519 return convert_expr_to_smt(*symbol);
1520 }
1522 {
1523 return convert_expr_to_smt(*nondet, converted);
1524 }
1525 if(const auto cast = expr_try_dynamic_cast<typecast_exprt>(expr))
1526 {
1527 return convert_expr_to_smt(*cast, converted);
1528 }
1529 if(
1531 {
1532 return convert_expr_to_smt(*float_cast, converted);
1533 }
1535 {
1536 return convert_expr_to_smt(*struct_construction, converted);
1537 }
1539 {
1540 return convert_expr_to_smt(*union_construction, converted);
1541 }
1543 {
1545 }
1546 if(
1548 {
1549 return convert_expr_to_smt(*concatenation, converted);
1550 }
1552 {
1553 return convert_expr_to_smt(*bitwise_and_expr, converted);
1554 }
1556 {
1557 return convert_expr_to_smt(*bitwise_or_expr, converted);
1558 }
1560 {
1561 return convert_expr_to_smt(*bitwise_xor, converted);
1562 }
1563 if(const auto bitwise_not = expr_try_dynamic_cast<bitnot_exprt>(expr))
1564 {
1565 return convert_expr_to_smt(*bitwise_not, converted);
1566 }
1567 if(const auto unary_minus = expr_try_dynamic_cast<unary_minus_exprt>(expr))
1568 {
1569 return convert_expr_to_smt(*unary_minus, converted);
1570 }
1571 if(const auto unary_plus = expr_try_dynamic_cast<unary_plus_exprt>(expr))
1572 {
1573 return convert_expr_to_smt(*unary_plus, converted);
1574 }
1575 if(const auto is_negative = expr_try_dynamic_cast<sign_exprt>(expr))
1576 {
1577 return convert_expr_to_smt(*is_negative, converted);
1578 }
1579 if(const auto if_expression = expr_try_dynamic_cast<if_exprt>(expr))
1580 {
1581 return convert_expr_to_smt(*if_expression, converted);
1582 }
1584 {
1585 return convert_expr_to_smt(*and_expression, converted);
1586 }
1587 if(const auto or_expression = expr_try_dynamic_cast<or_exprt>(expr))
1588 {
1589 return convert_expr_to_smt(*or_expression, converted);
1590 }
1592 {
1593 return convert_expr_to_smt(*xor_expression, converted);
1594 }
1595 if(const auto implies = expr_try_dynamic_cast<implies_exprt>(expr))
1596 {
1597 return convert_expr_to_smt(*implies, converted);
1598 }
1599 if(const auto logical_not = expr_try_dynamic_cast<not_exprt>(expr))
1600 {
1601 return convert_expr_to_smt(*logical_not, converted);
1602 }
1603 if(const auto equal = expr_try_dynamic_cast<equal_exprt>(expr))
1604 {
1605 return convert_expr_to_smt(*equal, converted);
1606 }
1607 if(const auto not_equal = expr_try_dynamic_cast<notequal_exprt>(expr))
1608 {
1609 return convert_expr_to_smt(*not_equal, converted);
1610 }
1611 if(
1612 const auto float_equal =
1614 {
1615 return convert_expr_to_smt(*float_equal, converted);
1616 }
1617 if(
1618 const auto float_not_equal =
1620 {
1621 return convert_expr_to_smt(*float_not_equal, converted);
1622 }
1623 if(
1624 const auto converted_relational =
1625 try_relational_conversion(expr, converted))
1626 {
1627 return *converted_relational;
1628 }
1629 if(const auto plus = expr_try_dynamic_cast<plus_exprt>(expr))
1630 {
1631 return convert_expr_to_smt(*plus, converted, pointer_sizes);
1632 }
1633 if(const auto minus = expr_try_dynamic_cast<minus_exprt>(expr))
1634 {
1635 return convert_expr_to_smt(*minus, converted, pointer_sizes);
1636 }
1637 if(const auto divide = expr_try_dynamic_cast<div_exprt>(expr))
1638 {
1639 return convert_expr_to_smt(*divide, converted);
1640 }
1641 if(
1642 const auto float_operation =
1644 {
1645 return convert_expr_to_smt(*float_operation, converted);
1646 }
1648 {
1649 return convert_expr_to_smt(*truncation_modulo, converted);
1650 }
1651 if(
1652 const auto euclidean_modulo =
1654 {
1655 return convert_expr_to_smt(*euclidean_modulo, converted);
1656 }
1657 if(const auto multiply = expr_try_dynamic_cast<mult_exprt>(expr))
1658 {
1659 return convert_expr_to_smt(*multiply, converted);
1660 }
1661#if 0
1662 else if(expr.id() == ID_floatbv_rem)
1663 {
1664 convert_floatbv_rem(to_binary_expr(expr));
1665 }
1666#endif
1668 {
1669 return convert_expr_to_smt(*address_of, converted, object_map);
1670 }
1671 if(const auto array_of = expr_try_dynamic_cast<array_of_exprt>(expr))
1672 {
1673 return convert_expr_to_smt(*array_of, converted);
1674 }
1675 if(
1676 const auto array_comprehension =
1678 {
1679 return convert_expr_to_smt(*array_comprehension, converted);
1680 }
1681 if(const auto index = expr_try_dynamic_cast<index_exprt>(expr))
1682 {
1683 return convert_expr_to_smt(*index, converted);
1684 }
1685 if(const auto shift = expr_try_dynamic_cast<shift_exprt>(expr))
1686 {
1687 return convert_expr_to_smt(*shift, converted);
1688 }
1689 if(const auto with = expr_try_dynamic_cast<with_exprt>(expr))
1690 {
1691 return convert_expr_to_smt(*with, converted);
1692 }
1693 if(const auto update = expr_try_dynamic_cast<update_exprt>(expr))
1694 {
1695 return convert_expr_to_smt(*update, converted);
1696 }
1698 {
1699 return convert_expr_to_smt(*member_extraction, converted);
1700 }
1701 else if(
1702 const auto pointer_offset =
1704 {
1705 return convert_expr_to_smt(*pointer_offset, converted);
1706 }
1707 else if(
1708 const auto pointer_object =
1710 {
1711 return convert_expr_to_smt(*pointer_object, converted);
1712 }
1713 if(
1714 const auto is_dynamic_object =
1716 {
1717 return convert_expr_to_smt(
1718 *is_dynamic_object, converted, apply_is_dynamic_object);
1719 }
1720 if(
1721 const auto is_invalid_pointer =
1723 {
1724 return convert_expr_to_smt(*is_invalid_pointer, object_map, converted);
1725 }
1727 {
1728 return convert_expr_to_smt(*string_constant, converted);
1729 }
1731 {
1732 return convert_expr_to_smt(*extract_bit, converted);
1733 }
1735 {
1736 return convert_expr_to_smt(*extract_bits, converted);
1737 }
1739 {
1740 return convert_expr_to_smt(*replication, converted);
1741 }
1742 if(
1743 const auto byte_extraction =
1745 {
1746 return convert_expr_to_smt(*byte_extraction, converted);
1747 }
1749 {
1750 return convert_expr_to_smt(*byte_update, converted);
1751 }
1753 {
1754 return convert_expr_to_smt(*absolute_value_of, converted);
1755 }
1756 if(const auto is_nan_expr = expr_try_dynamic_cast<isnan_exprt>(expr))
1757 {
1758 return convert_expr_to_smt(*is_nan_expr, converted);
1759 }
1761 {
1762 return convert_expr_to_smt(*is_finite_expr, converted);
1763 }
1765 {
1766 return convert_expr_to_smt(*is_infinite_expr, converted);
1767 }
1769 {
1770 return convert_expr_to_smt(*is_normal_expr, converted);
1771 }
1772 if(
1774 {
1775 return convert_expr_to_smt(*plus_overflow, converted);
1776 }
1777 if(
1778 const auto minus_overflow =
1780 {
1781 return convert_expr_to_smt(*minus_overflow, converted);
1782 }
1783 if(
1785 {
1786 return convert_expr_to_smt(*mult_overflow, converted);
1787 }
1789 {
1790 return convert_expr_to_smt(*shl_overflow, converted);
1791 }
1793 {
1794 return convert_expr_to_smt(*array_construction, converted);
1795 }
1796 if(const auto literal = expr_try_dynamic_cast<literal_exprt>(expr))
1797 {
1798 return convert_expr_to_smt(*literal, converted);
1799 }
1800 if(const auto for_all = expr_try_dynamic_cast<forall_exprt>(expr))
1801 {
1802 return convert_expr_to_smt(*for_all, converted);
1803 }
1804 if(const auto exists = expr_try_dynamic_cast<exists_exprt>(expr))
1805 {
1806 return convert_expr_to_smt(*exists, converted);
1807 }
1808 if(const auto vector = expr_try_dynamic_cast<vector_exprt>(expr))
1809 {
1810 return convert_expr_to_smt(*vector, converted);
1811 }
1813 {
1815 }
1816 if(const auto let = expr_try_dynamic_cast<let_exprt>(expr))
1817 {
1818 return convert_expr_to_smt(*let, converted);
1819 }
1820 INVARIANT(
1821 expr.id() != ID_constraint_select_one,
1822 "constraint_select_one is not expected in smt conversion: " +
1823 expr.pretty());
1824 if(const auto byte_swap = expr_try_dynamic_cast<bswap_exprt>(expr))
1825 {
1826 return convert_expr_to_smt(*byte_swap, converted);
1827 }
1829 {
1830 return convert_expr_to_smt(*population_count, converted);
1831 }
1832 if(
1833 const auto count_leading_zeros =
1835 {
1836 return convert_expr_to_smt(*count_leading_zeros, converted);
1837 }
1838 if(
1839 const auto count_trailing_zeros =
1841 {
1842 return convert_expr_to_smt(*count_trailing_zeros, converted);
1843 }
1844 if(const auto zero_extend = expr_try_dynamic_cast<zero_extend_exprt>(expr))
1845 {
1846 return convert_expr_to_smt(*zero_extend, converted);
1847 }
1848 if(
1849 const auto prophecy_r_or_w_ok =
1851 {
1852 return convert_expr_to_smt(*prophecy_r_or_w_ok, converted);
1853 }
1854 if(
1855 const auto prophecy_pointer_in_range =
1857 {
1859 }
1860
1862 "Generation of SMT formula for unknown kind of expression: " +
1863 expr.pretty());
1864}
1865
1866#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1867template <typename functiont>
1880
1881template <typename functiont>
1883{
1884 return at_scope_exitt<functiont>(exit_function);
1885}
1886#endif
1887
1889{
1890 expr.visit_pre([](exprt &expr) {
1892 if(!address_of_expr)
1893 return;
1894 const auto array_index_expr =
1896 if(!array_index_expr)
1897 return;
1898 expr = plus_exprt{
1900 array_index_expr->array(),
1902 array_index_expr->index()};
1903 });
1904 return expr;
1905}
1906
1911 const exprt &_expr,
1912 std::function<bool(const exprt &)> filter,
1913 std::function<void(const exprt &)> visitor)
1914{
1915 struct stack_entryt
1916 {
1917 const exprt *e;
1918 bool operands_pushed;
1919 explicit stack_entryt(const exprt *_e) : e(_e), operands_pushed(false)
1920 {
1921 }
1922 };
1923
1924 std::stack<stack_entryt> stack;
1925
1926 stack.emplace(&_expr);
1927
1928 while(!stack.empty())
1929 {
1930 auto &top = stack.top();
1931 if(top.operands_pushed)
1932 {
1933 visitor(*top.e);
1934 stack.pop();
1935 }
1936 else
1937 {
1938 // do modification of 'top' before pushing in case 'top' isn't stable
1939 top.operands_pushed = true;
1940 if(filter(*top.e))
1941 for(auto &op : top.e->operands())
1942 stack.emplace(&op);
1943 }
1944 }
1945}
1946
1948 const exprt &expr,
1949 const smt_object_mapt &object_map,
1952 const smt_is_dynamic_objectt::make_applicationt &is_dynamic_object)
1953{
1954#ifndef CPROVER_INVARIANT_DO_NOT_CHECK
1955 static bool in_conversion = false;
1956 INVARIANT(
1958 "Conversion of expr to smt should be non-recursive. "
1959 "Re-entrance found in conversion of " +
1960 expr.pretty(1, 0));
1961 in_conversion = true;
1962 const auto end_conversion = at_scope_exit([&]() { in_conversion = false; });
1963#endif
1965 const auto lowered_expr = lower_address_of_array_index(expr);
1968 [](const exprt &expr) {
1969 // Code values inside "address of" expressions do not need to be converted
1970 // as the "address of" conversion only depends on the object identifier.
1971 // Avoiding the conversion side steps a need to convert arbitrary code to
1972 // SMT terms.
1974 if(!address_of)
1975 return true;
1976 return !can_cast_type<code_typet>(address_of->object().type());
1977 },
1978 [&](const exprt &expr) {
1979 const auto find_result = sub_expression_map.find(expr);
1980 if(find_result != sub_expression_map.cend())
1981 return;
1983 expr,
1985 object_map,
1988 is_dynamic_object);
1989 sub_expression_map.emplace_hint(find_result, expr, std::move(term));
1990 });
1991 return std::move(sub_expression_map.at(lowered_expr));
1992}
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.
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.
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:440
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:566
ait()
Definition ai.h:569
Thrown when an unexpected error occurs during the analysis (e.g., when the SAT solver returns an erro...
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
Array constructor from list of elements.
Definition std_expr.h:1570
Array constructor from single element.
Definition std_expr.h:1512
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:679
exprt & rhs()
Definition std_expr.h:689
exprt & op0()
Definition expr.h:134
exprt & op1()
Definition expr.h:137
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:784
Bit-wise AND Any number of operands that is greater or equal one.
Bit-wise negation of bit-vectors.
Bit-wise OR Any number of operands that is greater or equal one.
Base class of fixed-width bit-vector types.
std::size_t get_width() const
Bit-wise XOR Any number of operands that is greater or equal one.
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:3007
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:1152
Equality.
Definition std_expr.h:1339
Boute's Euclidean definition of Modulo – to match SMT-LIB2.
Definition std_expr.h:1277
An exists expression.
Base class for all expressions.
Definition expr.h:57
void visit_pre(std::function< void(exprt &)>)
Definition expr.cpp:148
typet & type()
Return the type of the expression.
Definition expr.h:85
operandst & operands()
Definition expr.h:95
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.
Fixed-width bit-vector with IEEE floating-point interpretation.
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:2426
Boolean implication.
Definition std_expr.h:2154
Array index operator.
Definition std_expr.h:1431
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:3259
Extract member of struct or union.
Definition std_expr.h:2866
Binary minus.
Definition std_expr.h:1065
Modulo defined as lhs-(rhs * truncate(lhs/rhs)).
Definition std_expr.h:1216
Binary multiplication Associativity is not specified.
Definition std_expr.h:1104
A base class for multi-ary expressions Associativity is not specified.
Definition std_expr.h:908
Expression to hold a nondeterministic choice.
Definition std_expr.h:295
Boolean negation.
Definition std_expr.h:2388
Disequality.
Definition std_expr.h:1393
Expression for finding the size (in bytes) of the object a pointer points to.
Boolean OR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2193
The plus expression Associativity is not specified.
Definition std_expr.h:1006
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:612
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:1820
Expression to hold a symbol (variable)
Definition std_expr.h:132
void identifier(const irep_idt &identifier)
Definition std_expr.h:160
Semantic type conversion.
Definition std_expr.h:1995
The type of an expression, extends irept.
Definition type.h:29
const exprt & op() const
Definition std_expr.h:394
The unary minus expression.
Definition std_expr.h:477
The unary plus expression.
Definition std_expr.h:519
Union constructor from single element.
Definition std_expr.h:1724
Operator to update elements in structs and arrays.
Definition std_expr.h:2679
Vector constructor from list of elements.
Definition std_expr.h:1686
Operator to update elements in structs and arrays.
Definition std_expr.h:2520
Boolean XOR All operands must be boolean, and the result is always boolean.
Definition std_expr.h:2300
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:721
const unary_exprt & to_unary_expr(const exprt &expr)
Cast an exprt to a unary_exprt.
Definition std_expr.h:424
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