CBMC
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
recursive_initialization.cpp
Go to the documentation of this file.
1/******************************************************************\
2
3Module: recursive_initialization
4
5Author: Diffblue Ltd.
6
7\******************************************************************/
8
10
12
13#include <util/arith_tools.h>
14#include <util/c_types.h>
15#include <util/fresh_symbol.h>
16#include <util/irep.h>
17#include <util/optional_utils.h>
18#include <util/pointer_expr.h>
20#include <util/rename.h>
21#include <util/std_code.h>
22#include <util/string2int.h>
23#include <util/string_utils.h>
24
25#include <iterator>
26
29
31 const std::string &option,
32 const std::list<std::string> &values)
33{
35 {
36 auto const value =
38 auto const user_min_null_tree_depth =
40 if(user_min_null_tree_depth.has_value())
41 {
43 }
44 else
45 {
47 "failed to convert '" + value + "' to integer",
49 }
50 return true;
51 }
53 {
54 auto const value =
58 if(user_max_nondet_tree_depth.has_value())
59 {
61 }
62 else
63 {
65 "failed to convert '" + value + "' to integer",
67 }
68 return true;
69 }
71 {
74 return true;
75 }
77 {
80 return true;
81 }
83 {
84 std::transform(
85 values.begin(),
86 values.end(),
87 std::inserter(
90 [](const std::string &opt) -> irep_idt { return irep_idt{opt}; });
91 return true;
92 }
94 {
95 const auto list_of_members_string =
99 for(const auto &member : list_of_members)
100 {
101 const auto selection_spec_strings = split_string(member, '.');
102
103 selection_specs.push_back({});
104 auto &selection_spec = selection_specs.back();
105 std::transform(
108 std::back_inserter(selection_spec),
109 [](const std::string &member_name_string) {
110 return irep_idt{member_name_string};
111 });
112 }
113 return true;
114 }
115 return false;
116}
117
119 recursive_initialization_configt initialization_config,
120 goto_modelt &goto_model)
121 : initialization_config(std::move(initialization_config)),
122 goto_model(goto_model),
123 max_depth_var_name(get_fresh_global_name(
124 "max_depth",
126 initialization_config.max_nondet_tree_depth,
127 signed_int_type()))),
128 min_depth_var_name(get_fresh_global_name(
129 "min_depth",
131 initialization_config.min_null_tree_depth,
132 signed_int_type())))
133{
135 this->initialization_config.pointers_to_treat_equal.size());
136}
137
139 const exprt &lhs,
140 const exprt &depth,
141 code_blockt &body)
142{
143 if(lhs.id() == ID_symbol && !initialization_config.selection_specs.empty())
144 {
145 auto lhs_id = to_symbol_expr(lhs).get_identifier();
146 for(const auto &selection_spec : initialization_config.selection_specs)
147 {
148 if(selection_spec.front() == lhs_id)
149 {
151 return;
152 }
153 }
154 }
155 // special handling for the case that pointer arguments should be treated
156 // equal: if the equality is enforced (rather than the pointers may be equal),
157 // then we don't even build the constructor functions
158 if(lhs.id() == ID_symbol)
159 {
160 const auto maybe_cluster_index =
161 find_equal_cluster(to_symbol_expr(lhs).get_identifier());
162 if(maybe_cluster_index.has_value())
163 {
165 {
166 const auto set_equal_case =
168 if(initialization_config.arguments_may_be_equal)
169 {
170 const irep_idt &fun_name = build_constructor(lhs);
171 const symbolt &fun_symbol =
174 fun_symbol.symbol_expr(), {depth, address_of_exprt{lhs}}};
175 const auto should_make_equal =
176 get_fresh_local_typed_symexpr("should_make_equal", bool_typet{});
180 }
181 else
182 {
183 body.add(set_equal_case);
184 }
185 return;
186 }
187 else
188 {
190 }
191 }
192 }
193
194 const irep_idt &fun_name = build_constructor(lhs);
196
197 if(lhs.id() == ID_symbol)
198 {
199 const irep_idt &lhs_name = to_symbol_expr(lhs).get_identifier();
201 {
203 if(size_var.has_value())
204 {
206 goto_model.symbol_table.lookup_ref(size_var.value()).symbol_expr();
208 fun_symbol.symbol_expr(),
210 }
211 else
212 {
213 const auto &fun_type_params =
214 to_code_type(fun_symbol.type).parameters();
217 INVARIANT(size_var_type, "Size parameter must have pointer type.");
219 fun_symbol.symbol_expr(),
221 }
222 return;
223 }
224 for(const auto &irep_pair :
225 initialization_config.array_name_to_associated_array_size_variable)
226 {
227 // skip initialisation of array-size variables
228 if(irep_pair.second == lhs_name)
229 return;
230 }
231 }
232 body.add(code_function_callt{fun_symbol.symbol_expr(),
233 {depth, address_of_exprt{lhs}}});
234}
235
245
247 const exprt &depth_symbol,
249 const std::optional<exprt> &size_symbol,
250 const std::optional<irep_idt> &lhs_name,
251 const bool is_nullable)
252{
253 PRECONDITION(result_symbol.type().id() == ID_pointer);
254 const typet &type = to_pointer_type(result_symbol.type()).base_type();
255 if(type.id() == ID_struct_tag)
256 {
258 }
259 else if(type.id() == ID_pointer)
260 {
261 if(to_pointer_type(type).base_type().id() == ID_code)
262 {
264 }
265 if(to_pointer_type(type).base_type().id() == ID_empty)
266 {
267 // always initalize void* pointers as NULL
269 }
270 if(lhs_name.has_value())
271 {
273 {
274 CHECK_RETURN(size_symbol.has_value());
277 }
278 }
280 }
281 else if(type.id() == ID_array)
282 {
284 }
285 else
286 {
288 }
289}
290
292{
293 // for `expr` of type T builds a declaration of a function:
294 //
295 // void type_constructor_T(int depth_T, T *result);
296 //
297 // or in case a `size` is associated with the `expr`
298 //
299 // void type_constructor_T(int depth_T, T *result_T, int *size);
300 std::optional<irep_idt> size_var;
301 std::optional<irep_idt> expr_name;
302 bool is_nullable = false;
303 bool has_size_param = false;
304 if(expr.id() == ID_symbol)
305 {
306 expr_name = to_symbol_expr(expr).get_identifier();
307 is_nullable = initialization_config.potential_null_function_pointers.count(
308 expr_name.value());
310 {
312 has_size_param = true;
313 }
314 }
315 const typet &type = expr.type();
316 const constructor_keyt key{type, is_nullable, has_size_param};
319
320 const std::string &pretty_type = type2id(type);
324
327 depth_parameter.set_identifier(depth_symbol.name);
328 fun_params.push_back(depth_parameter);
329
330 const typet &result_type = pointer_type(type);
331 const symbolt &result_symbol =
332 get_fresh_param_symbol("result_" + pretty_type, result_type);
334 result_parameter.set_identifier(result_symbol.name);
335 fun_params.push_back(result_parameter);
336
337 auto &symbol_table = goto_model.symbol_table;
338 std::optional<exprt> size_symbol_expr;
340 {
342 if(size_var.has_value())
343 {
345 symbol_table.lookup_ref(*size_var).symbol_expr();
347 }
348 else
350
351 const symbolt &size_symbol =
354 fun_params.back().set_identifier(size_symbol.name);
355 size_symbol_expr = size_symbol.symbol_expr();
356 }
358 "type_constructor_" + pretty_type, code_typet{fun_params, empty_typet{}});
360 symbolt *mutable_symbol = symbol_table.get_writeable(function_symbol.name);
361
362 // the body is specific for each type of expression
364 depth_symbol.symbol_expr(),
365 result_symbol.symbol_expr(),
367 // the expression name may be needed to decide if expr should be treated as
368 // a string
369 expr_name,
370 is_nullable);
371
372 return type_constructor_names.at(key);
373}
374
376{
377 auto malloc_sym = goto_model.symbol_table.lookup("malloc");
378 if(malloc_sym == nullptr)
379 {
381 "malloc",
385 new_malloc_sym.pretty_name = "malloc";
386 new_malloc_sym.base_name = "malloc";
388 return new_malloc_sym.symbol_expr();
389 }
390 return malloc_sym->symbol_expr();
391}
392
394 const irep_idt &array_name) const
395{
396 return initialization_config.pointers_to_treat_as_arrays.find(array_name) !=
397 initialization_config.pointers_to_treat_as_arrays.end();
398}
399
400std::optional<recursive_initializationt::equal_cluster_idt>
402{
403 for(equal_cluster_idt index = 0;
404 index != initialization_config.pointers_to_treat_equal.size();
405 ++index)
406 {
407 if(initialization_config.pointers_to_treat_equal[index].count(name) != 0)
408 return index;
409 }
410 return {};
411}
412
414 const irep_idt &cmdline_arg) const
415{
416 return initialization_config.variables_that_hold_array_sizes.find(
417 cmdline_arg) !=
418 initialization_config.variables_that_hold_array_sizes.end();
419}
420
422 const irep_idt &array_name) const
423{
424 return optional_lookup(
425 initialization_config.array_name_to_associated_array_size_variable,
426 array_name);
427}
428
430 const irep_idt &pointer_name) const
431{
432 return initialization_config.pointers_to_treat_as_cstrings.count(
433 pointer_name) != 0;
434}
435
437{
438 std::ostringstream out{};
439 out << "recursive_initialization_config {"
440 << "\n min_null_tree_depth = " << min_null_tree_depth
441 << "\n max_nondet_tree_depth = " << max_nondet_tree_depth
442 << "\n mode = " << mode
443 << "\n max_dynamic_array_size = " << max_dynamic_array_size
444 << "\n min_dynamic_array_size = " << min_dynamic_array_size
445 << "\n pointers_to_treat_as_arrays = [";
446 for(auto const &pointer : pointers_to_treat_as_arrays)
447 {
448 out << "\n " << pointer;
449 }
450 out << "\n ]"
451 << "\n variables_that_hold_array_sizes = [";
453 {
454 out << "\n " << array_size;
455 }
456 out << "\n ]";
457 out << "\n array_name_to_associated_size_variable = [";
458 for(auto const &associated_array_size :
460 {
461 out << "\n " << associated_array_size.first << " -> "
462 << associated_array_size.second;
463 }
464 out << "\n ]";
465 out << "\n pointers_to_treat_as_cstrings = [";
466 for(const auto &pointer_to_treat_as_string_name :
468 {
469 out << "\n " << pointer_to_treat_as_string_name << std::endl;
470 }
471 out << "\n ]";
472 out << "\n}";
473 return out.str();
474}
475
477 symbol_tablet &symbol_table,
478 const std::string &symbol_base_name,
480 irep_idt mode)
481{
482 source_locationt source_location{};
483 source_location.set_file(GOTO_HARNESS_PREFIX "harness.c");
484 symbolt &fresh_symbol = get_fresh_aux_symbol(
485 std::move(symbol_type),
489 mode,
490 symbol_table);
491 fresh_symbol.base_name = fresh_symbol.pretty_name = symbol_base_name;
492 fresh_symbol.is_static_lifetime = true;
493 fresh_symbol.is_lvalue = true;
494 fresh_symbol.is_auxiliary = false;
495 fresh_symbol.is_file_local = false;
496 fresh_symbol.is_thread_local = false;
497 fresh_symbol.is_state_var = false;
498 fresh_symbol.module = GOTO_HARNESS_PREFIX "harness";
499 fresh_symbol.location = std::move(source_location);
500 return fresh_symbol;
501}
502
504 const std::string &symbol_name,
505 const exprt &initial_value) const
506{
507 auto &fresh_symbol = get_fresh_global_symbol(
510 signed_int_type(), // FIXME why always signed_int_type???
512 fresh_symbol.value = initial_value;
513 return fresh_symbol.name;
514}
515
517 const std::string &symbol_name) const
518{
519 auto &fresh_symbol = get_fresh_global_symbol(
524 fresh_symbol.value = from_integer(0, signed_int_type());
525 return fresh_symbol.symbol_expr();
526}
527
529 const std::string &symbol_name) const
530{
531 symbolt &fresh_symbol = get_fresh_aux_symbol(
538 fresh_symbol.is_lvalue = true;
539 fresh_symbol.value = from_integer(0, signed_int_type());
540 return fresh_symbol.symbol_expr();
541}
542
544 const std::string &symbol_name,
545 const typet &type) const
546{
547 symbolt &fresh_symbol = get_fresh_aux_symbol(
548 type,
554 fresh_symbol.is_lvalue = true;
555 fresh_symbol.mode = initialization_config.mode;
556 return fresh_symbol.symbol_expr();
557}
558
560 const std::string &fun_name,
561 const typet &fun_type)
562{
565
566 // create the function symbol
568 function_symbol.name = function_symbol.base_name =
569 function_symbol.pretty_name = fresh_name;
570
571 function_symbol.is_lvalue = true;
574
576 CHECK_RETURN(r.second);
578}
579
597
605
606std::string recursive_initializationt::type2id(const typet &type) const
607{
608 if(type.id() == ID_struct_tag)
609 {
610 auto st_tag = id2string(to_struct_tag_type(type).get_identifier());
611 std::replace(st_tag.begin(), st_tag.end(), '-', '_');
612 return st_tag;
613 }
614 else if(type.id() == ID_pointer)
615 return "ptr_" + type2id(to_pointer_type(type).base_type());
616 else if(type.id() == ID_array)
617 {
618 const auto array_size =
620 return "arr_" + type2id(to_array_type(type).element_type()) + "_" +
621 std::to_string(array_size);
622 }
623 else if(type == char_type())
624 return "char";
625 else if(type.id() == ID_signedbv)
626 return "int";
627 else if(type.id() == ID_unsignedbv)
628 return "uint";
629 else
630 return "";
631}
632
634{
635 auto free_sym = goto_model.symbol_table.lookup("free");
636 if(free_sym == nullptr)
637 {
639 "free",
643 new_free_sym.pretty_name = "free";
644 new_free_sym.base_name = "free";
646 return new_free_sym.symbol_expr();
647 }
648 return free_sym->symbol_expr();
649}
650
652 const exprt &depth,
653 const symbol_exprt &result)
654{
655 PRECONDITION(result.type().id() == ID_pointer);
656 const typet &type = to_pointer_type(result.type()).base_type();
657 PRECONDITION(type.id() == ID_pointer);
658 PRECONDITION(to_pointer_type(type).base_type().id() != ID_empty);
659
660 code_blockt body{};
661 // build:
662 // void type_constructor_ptr_T(int depth, T** result)
663 // {
664 // if(has_seen && depth >= max_depth)
665 // *result=NULL;
666 // return
667 // if(nondet()) {
668 // size_t has_seen_prev;
669 // has_seen_prev = T_has_seen;
670 // T_has_seen = 1;
671 // *result = malloc(sizeof(T));
672 // type_constructor_T(depth+1, *result);
673 // T_has_seen=has_seen_prev;
674 // }
675 // else
676 // *result=NULL;
677 // }
678
682
683 std::optional<symbol_exprt> has_seen;
686 "has_seen_" + type2id(to_pointer_type(type).base_type()));
687
688 if(has_seen.has_value())
689 {
692 }
693
695 pointer_type(to_pointer_type(type).base_type())};
699
700 const auto should_recurse_nondet =
701 get_fresh_local_typed_symexpr("should_recurse_nondet", bool_typet{});
706 code_blockt then_case{};
707
709 if(has_seen.has_value())
710 {
712 "has_seen_prev_" + type2id(to_pointer_type(type).base_type()));
713 then_case.add(code_declt{has_seen_prev});
714 then_case.add(code_assignt{has_seen_prev, *has_seen});
715 then_case.add(code_assignt{*has_seen, from_integer(1, has_seen->type())});
717 }
718
719 // we want to initialize the pointee as non-const even for pointer to const
721 pointer_type(remove_const(to_pointer_type(type).base_type()));
724
725 then_case.add(code_declt{local_result});
727 then_case.add(code_function_callt{
730 {*size_of_expr(non_const_pointer_type.base_type(), ns)}});
733 plus_exprt{depth, from_integer(1, depth.type())},
734 then_case);
735 then_case.add(code_assignt{dereference_exprt{result}, local_result});
736
737 if(has_seen.has_value())
738 {
739 then_case.add(seen_assign_prev);
740 }
741
742 body.add(
744 return body;
745}
746
748 const exprt &depth,
749 const symbol_exprt &result)
750{
751 PRECONDITION(result.type().id() == ID_pointer);
752 const typet &type = to_pointer_type(result.type()).base_type();
753 PRECONDITION(type.id() == ID_array);
754 const array_typet &array_type = to_array_type(type);
755 const auto array_size =
757 code_blockt body{};
758
759 for(std::size_t index = 0; index < array_size; index++)
760 {
763 depth,
764 body);
765 }
766 return body;
767}
768
770 const exprt &depth,
771 const symbol_exprt &result)
772{
773 PRECONDITION(result.type().id() == ID_pointer);
774 const typet &struct_type = to_pointer_type(result.type()).base_type();
776 code_blockt body{};
778 for(const auto &component :
779 ns.follow_tag(to_struct_tag_type(struct_type)).components())
780 {
781 if(component.get_is_padding())
782 {
783 continue;
784 }
785 // if the struct component is const we need to cast away the const
786 // for initialisation purposes.
787 // As far as I'm aware that's the closest thing to a 'correct' way
788 // to initialize dynamically allocated structs with const components
791 if(component.type().get_bool(ID_C_constant))
792 {
793 return dereference_exprt{
796 }
797 else
798 {
799 return std::move(member_expr);
800 }
801 }();
803 }
804 return body;
805}
806
808 const symbol_exprt &result) const
809{
810 PRECONDITION(result.type().id() == ID_pointer);
811 code_blockt body{};
813 "nondet", to_pointer_type(result.type()).base_type());
814 body.add(code_declt{nondet_symbol});
815 body.add(code_assignt{dereference_exprt{result}, nondet_symbol});
816 return body;
817}
818
820 const exprt &depth,
821 const symbol_exprt &result,
822 const exprt &size,
823 const std::optional<irep_idt> &lhs_name)
824{
825 PRECONDITION(result.type().id() == ID_pointer);
826 const typet &dynamic_array_type = to_pointer_type(result.type()).base_type();
828 const typet &element_type = to_pointer_type(dynamic_array_type).base_type();
829 PRECONDITION(element_type.id() != ID_empty);
830
831 // builds:
832 // void type_constructor_ptr_T(int depth, T** result, int* size)
833 // {
834 // int nondet_size;
835 // assume(nondet_size >= min_array_size && nondet_size <= max_array_size);
836 // T* local_result = malloc(nondet_size * sizeof(T));
837 // for (int i = 0; i < nondet_size; ++i)
838 // {
839 // type_construct_T(depth+1, local_result+i);
840 // }
841 // *result = local_result;
842 // if (size!=NULL)
843 // *size = nondet_size;
844 // }
845
846 const auto min_array_size = initialization_config.min_dynamic_array_size;
847 const auto max_array_size = initialization_config.max_dynamic_array_size;
849
850 code_blockt body{};
851 const symbol_exprt &nondet_size = get_fresh_local_symexpr("nondet_size");
852 body.add(code_declt{nondet_size});
853
854 body.add(code_assumet{and_exprt{
859
860 // we want the local result to be mutable so we can initialise it
862 pointer_type(remove_const(element_type));
865 body.add(code_declt{local_result});
868 ++array_size)
869 {
875 *size_of_expr(element_type, ns)}}}});
876 }
877
879 body.add(code_declt{index_iter});
886 {
887 code_blockt else_case{};
890 plus_exprt{depth, from_integer(1, depth.type())},
891 else_case);
892 else_case.add(code_assumet{
894 from_integer(0, char_type())}});
895
901 from_integer(0, char_type())},
902 else_case});
903 }
904 else
905 {
908 plus_exprt{depth, from_integer(1, depth.type())},
909 for_body);
910 }
911
913 body.add(code_assignt{dereference_exprt{result}, local_result});
914
915 CHECK_RETURN(size.type().id() == ID_pointer);
916 body.add(code_ifthenelset{
919 dereference_exprt{size},
921 nondet_size, to_pointer_type(size.type()).base_type())}});
922
923 return body;
924}
925
927{
928 if(
929 expr.type().id() != ID_pointer ||
930 to_pointer_type(expr.type()).base_type().id() == ID_code)
931 return false;
933 {
934 if(common_arguments_origin.has_value() && expr.id() == ID_symbol)
935 {
936 auto origin_name =
937 to_symbol_expr(*common_arguments_origin).get_identifier();
938 auto expr_name = to_symbol_expr(expr).get_identifier();
939 return origin_name == expr_name;
940 }
941 }
942 return true;
943}
944
946 const exprt &expr,
947 code_blockt &body)
948{
949 PRECONDITION(expr.id() == ID_symbol);
950 const auto expr_id = to_symbol_expr(expr).get_identifier();
952 const auto call_free = code_function_callt{get_free_function(), {expr}};
953 if(!maybe_cluster_index.has_value())
954 {
955 // not in any equality cluster -> just free
956 body.add(call_free);
957 return;
958 }
959
960 if(
962 .get_identifier() != expr_id &&
963 initialization_config.arguments_may_be_equal)
964 {
965 // in equality cluster but not common origin -> free if not equal to origin
966 const auto condition =
968 body.add(code_ifthenelset{condition, call_free});
969 }
970 else
971 {
972 // expr is common origin, leave freeing until the rest of the cluster is
973 // freed
974 return;
975 }
976}
977
985
987 const symbol_exprt &result,
988 bool is_nullable)
989{
991 const auto &result_type = to_pointer_type(result.type());
992 PRECONDITION(can_cast_type<pointer_typet>(result_type.base_type()));
993 const auto &function_pointer_type = to_pointer_type(result_type.base_type());
995 const auto &function_type = to_code_type(function_pointer_type.base_type());
996
997 std::vector<exprt> targets;
998
999 for(const auto &sym : goto_model.get_symbol_table())
1000 {
1001 if(sym.second.type == function_type)
1002 {
1003 targets.push_back(address_of_exprt{sym.second.symbol_expr()});
1004 }
1005 }
1006
1007 if(is_nullable)
1008 targets.push_back(null_pointer_exprt{function_pointer_type});
1009
1010 code_blockt body{};
1011
1012 const auto function_pointer_selector =
1013 get_fresh_local_symexpr("function_pointer_selector");
1015 auto function_pointer_index = std::size_t{0};
1016
1017 for(const auto &target : targets)
1018 {
1019 auto const assign = code_assignt{dereference_exprt{result}, target};
1020 auto const sym_to_lookup =
1021 target.id() == ID_address_of
1022 ?
1023 // This is either address of or pointer; in pointer case, we don't
1024 // need to do anything. In the address of case, the operand is
1025 // a symbol representing a target function.
1026 to_symbol_expr(to_address_of_expr(target).object()).get_identifier()
1027 : "";
1028 // skip referencing globals because the corresponding symbols in the symbol
1029 // table are no longer marked as file local.
1030 if(sym_to_lookup.starts_with(FILE_LOCAL_PREFIX))
1031 {
1032 continue;
1033 }
1034 else if(
1036 goto_model.get_symbol_table().lookup(sym_to_lookup)->is_file_local)
1037 {
1038 continue;
1039 }
1040
1041 if(function_pointer_index != targets.size() - 1)
1042 {
1043 auto const condition = equal_exprt{
1046 auto const then = code_blockt{{assign, code_frontend_returnt{}}};
1047 body.add(code_ifthenelset{condition, then});
1048 }
1049 else
1050 {
1051 body.add(assign);
1052 }
1054 }
1055
1056 return body;
1057}
1058
1060 const exprt &lhs,
1061 const exprt &depth,
1062 code_blockt &body,
1063 const std::vector<irep_idt> &selection_spec)
1064{
1065 PRECONDITION(lhs.id() == ID_symbol);
1066 PRECONDITION(lhs.type().id() == ID_struct_tag);
1067 PRECONDITION(!selection_spec.empty());
1068
1069 auto component_member = lhs;
1071
1072 for(auto it = selection_spec.begin() + 1; it != selection_spec.end(); it++)
1073 {
1074 if(component_member.type().id() != ID_struct_tag)
1075 {
1077 "'" + id2string(*it) + "' is not a component name",
1079 }
1081 const auto &struct_type = to_struct_type(ns.follow_tag(struct_tag_type));
1082
1083 bool found = false;
1084 for(auto const &component : struct_type.components())
1085 {
1086 const auto &component_type = component.type();
1087 const auto component_name = component.get_name();
1088
1089 if(*it == component_name)
1090 {
1092 member_exprt{component_member, component_name, component_type};
1093 found = true;
1094 break;
1095 }
1096 }
1097 if(!found)
1098 {
1100 "'" + id2string(*it) + "' is not a component name",
1102 }
1103 }
1104 initialize(component_member, depth, body);
1105}
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
std::string array_name(const namespacet &ns, const exprt &expr)
static code_frontend_assignt assign_null(const exprt &expr)
One of the base cases of the recursive algorithm.
static symbolt result_symbol(const irep_idt &identifier, const typet &type, const source_locationt &source_location, symbol_table_baset &symbol_table)
signedbv_typet signed_int_type()
Definition c_types.cpp:22
pointer_typet pointer_type(const typet &subtype)
Definition c_types.cpp:235
bitvector_typet char_type()
Definition c_types.cpp:106
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
Boolean AND.
Definition std_expr.h:2125
Arrays with given size.
Definition std_types.h:807
A base class for expressions that are predicates, i.e., Boolean-typed, and that take exactly two argu...
Definition std_expr.h:731
A base class for relations, i.e., binary predicates whose two operands have the same type.
Definition std_expr.h:762
The Boolean type.
Definition std_types.h:36
A goto_instruction_codet representing an assignment in the program.
An assumption, which must hold in subsequent code.
Definition std_code.h:217
A codet representing sequential composition of program statements.
Definition std_code.h:130
void add(const codet &code)
Definition std_code.h:168
A goto_instruction_codet representing the declaration of a local variable.
codet representation of a for statement.
Definition std_code.h:734
codet representation of a "return from a function" statement.
Definition std_code.h:893
goto_instruction_codet representation of a function call statement.
codet representation of an if-then-else statement.
Definition std_code.h:460
Base type of functions.
Definition std_types.h:583
std::vector< parametert > parameterst
Definition std_types.h:586
Operator to dereference a pointer.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition dstring.h:38
The empty type.
Definition std_types.h:51
Equality.
Definition std_expr.h:1366
Base class for all expressions.
Definition expr.h:56
std::vector< exprt > operandst
Definition expr.h:58
typet & type()
Return the type of the expression.
Definition expr.h:84
const symbol_tablet & get_symbol_table() const override
Accessor to get the symbol table.
Definition goto_model.h:84
symbol_tablet symbol_table
Symbol table.
Definition goto_model.h:31
Array index operator.
Definition std_expr.h:1470
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
const irep_idt & id() const
Definition irep.h:388
irept & add(const irep_idt &name)
Definition irep.cpp:103
Extract member of struct or union.
Definition std_expr.h:2971
Binary minus.
Definition std_expr.h:1061
Binary multiplication Associativity is not specified.
Definition std_expr.h:1107
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
Definition namespace.h:91
Disequality.
Definition std_expr.h:1425
The null pointer constant.
The plus expression Associativity is not specified.
Definition std_expr.h:1002
The pointer type These are both 'bitvector_typet' (they have a width) and 'type_with_subtypet' (they ...
void initialize_selected_member(const exprt &lhs, const exprt &depth, code_blockt &body, const std::vector< irep_idt > &selection_spec)
Select the specified struct-member to be non-deterministically initialized.
std::string type2id(const typet &type) const
Simple pretty-printer for typet.
void free_if_possible(const exprt &expr, code_blockt &body)
type_constructor_namest type_constructor_names
code_blockt build_dynamic_array_constructor(const exprt &depth, const symbol_exprt &result, const exprt &size, const std::optional< irep_idt > &lhs_name)
Constructor for dynamic arrays: allocate memory for n elements (n is random but bounded) and initiali...
code_blockt build_constructor_body(const exprt &depth_symbol, const symbol_exprt &result_symbol, const std::optional< exprt > &size_symbol, const std::optional< irep_idt > &lhs_name, const bool is_nullable)
Case analysis for which constructor should be used.
std::vector< std::optional< exprt > > common_arguments_origins
code_blockt build_nondet_constructor(const symbol_exprt &result) const
Default constructor: assigns non-deterministic value of the right type.
symbol_exprt get_malloc_function()
Get the malloc function as symbol exprt, and inserts it into the goto-model if it doesn't exist alrea...
std::optional< equal_cluster_idt > find_equal_cluster(const irep_idt &name) const
code_blockt build_struct_constructor(const exprt &depth, const symbol_exprt &result)
Constructor for structures: simply iterates over members and initialise each one.
irep_idt build_constructor(const exprt &expr)
Check if a constructor for the type of expr already exists and create it if not.
irep_idt get_fresh_global_name(const std::string &symbol_name, const exprt &initial_value) const
Construct a new global symbol of type int and set it's value to initial_value.
code_blockt build_function_pointer_constructor(const symbol_exprt &result, bool is_nullable)
Constructor for function pointers.
const recursive_initialization_configt initialization_config
symbol_exprt get_fresh_local_typed_symexpr(const std::string &symbol_name, const typet &type) const
Construct a new local symbol of type type initialised to init_value.
std::optional< irep_idt > get_associated_size_variable(const irep_idt &array_name) const
code_blockt build_array_constructor(const exprt &depth, const symbol_exprt &result)
Constructor for arrays: simply iterates over elements and initialise each one.
recursive_initializationt(recursive_initialization_configt initialization_config, goto_modelt &goto_model)
void free_cluster_origins(code_blockt &body)
bool should_be_treated_as_array(const irep_idt &pointer_name) const
void initialize(const exprt &lhs, const exprt &depth, code_blockt &body)
Generate initialisation code for lhs into body.
symbol_exprt get_free_function()
Get the free function as symbol expression, and inserts it into the goto-model if it doesn't exist al...
bool needs_freeing(const exprt &expr) const
const symbolt & get_fresh_fun_symbol(const std::string &fun_name, const typet &fun_type)
Construct a new function symbol of type fun_type.
bool should_be_treated_as_cstring(const irep_idt &pointer_name) const
symbol_exprt get_fresh_local_symexpr(const std::string &symbol_name) const
Construct a new local symbol of type int initialised to 0.
bool is_array_size_parameter(const irep_idt &cmdline_arg) const
symbol_exprt get_symbol_expr(const irep_idt &symbol_name) const
Recover the symbol expression from symbol table.
symbol_exprt get_fresh_global_symexpr(const std::string &symbol_name) const
Construct a new global symbol of type int initialised to 0.
code_blockt build_pointer_constructor(const exprt &depth, const symbol_exprt &result)
Generic constructor for all pointers: only builds one pointee (not an array) but may recourse in case...
symbolt & get_fresh_param_symbol(const std::string &param_name, const typet &param_type)
Construct a new parameter symbol of type param_type.
An expression containing a side effect.
Definition std_code.h:1450
void set_file(const irep_idt &file)
Expression to hold a symbol (variable)
Definition std_expr.h:131
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The symbol table.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition symbol.h:28
bool is_auxiliary
Definition symbol.h:77
bool is_file_local
Definition symbol.h:73
bool is_static_lifetime
Definition symbol.h:70
bool is_thread_local
Definition symbol.h:71
source_locationt location
Source code location of definition of symbol.
Definition symbol.h:37
bool is_state_var
Definition symbol.h:66
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition symbol.cpp:121
irep_idt pretty_name
Language-specific display name.
Definition symbol.h:52
irep_idt irep_idt base_name
Name of module the symbol belongs to.
Definition symbol.h:46
bool is_lvalue
Definition symbol.h:72
exprt value
Initial value of symbol.
Definition symbol.h:34
irep_idt mode
Language mode.
Definition symbol.h:49
Semantic type conversion.
Definition std_expr.h:2073
static exprt conditional_cast(const exprt &expr, const typet &type)
Definition std_expr.h:2081
The type of an expression, extends irept.
Definition type.h:29
#define COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT
#define COMMON_HARNESS_GENERATOR_MIN_ARRAY_SIZE_OPT
#define COMMON_HARNESS_GENERATOR_MIN_NULL_TREE_DEPTH_OPT
#define COMMON_HARNESS_GENERATOR_MAX_ARRAY_SIZE_OPT
#define COMMON_HARNESS_GENERATOR_MAX_NONDET_TREE_DEPTH_OPT
#define COMMON_HARNESS_GENERATOR_HAVOC_MEMBER_OPT
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
const std::string & id2string(const irep_idt &d)
Definition irep.h:44
static int8_t r
Definition irep_hash.h:60
Mangle names of file-local functions to make them unique.
#define FILE_LOCAL_PREFIX
std::string require_exactly_one_value(const std::string &option, const std::list< std::string > &values)
Returns the only value of a single element list, throws an exception if not passed a single element l...
std::size_t require_one_size_value(const std::string &option, const std::list< std::string > &values)
Returns the only Nat value of a single element list, throws an exception if not passed a single eleme...
STL namespace.
auto optional_lookup(const map_like_collectiont &map, const keyt &key) -> std::optional< decltype(map.find(key) ->second)>
Lookup a key in a map, if found return the associated value, nullopt otherwise.
API to expression classes for Pointers.
const address_of_exprt & to_address_of_expr(const exprt &expr)
Cast an exprt to an address_of_exprt.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
std::optional< exprt > size_of_expr(const typet &type, const namespacet &ns)
Pointer Logic.
static symbolt & get_fresh_global_symbol(symbol_tablet &symbol_table, const std::string &symbol_base_name, typet symbol_type, irep_idt mode)
code_blockt build_null_pointer(const symbol_exprt &result_symbol)
#define GOTO_HARNESS_PREFIX
irep_idt get_new_name(const irep_idt &name, const namespacet &ns, char delimiter)
Build and identifier not yet present in the namespace ns based on name.
Definition rename.cpp:16
#define CHECK_RETURN(CONDITION)
Definition invariant.h:495
#define PRECONDITION(CONDITION)
Definition invariant.h:463
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Definition invariant.h:423
exprt conjunction(const exprt::operandst &op)
1) generates a conjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition std_expr.cpp:83
exprt disjunction(const exprt::operandst &op)
1) generates a disjunction for two or more operands 2) for one operand, returns the operand 3) return...
Definition std_expr.cpp:71
auto component(T &struct_expr, const irep_idt &name, const namespacet &ns) -> decltype(struct_expr.op0())
Definition std_expr.cpp:97
const constant_exprt & to_constant_expr(const exprt &expr)
Cast an exprt to a constant_exprt.
Definition std_expr.h:3172
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
Definition std_expr.h:272
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition std_types.h:788
const struct_typet & to_struct_type(const typet &type)
Cast a typet to a struct_typet.
Definition std_types.h:308
const struct_tag_typet & to_struct_tag_type(const typet &type)
Cast a typet to a struct_tag_typet.
Definition std_types.h:518
const array_typet & to_array_type(const typet &type)
Cast a typet to an array_typet.
Definition std_types.h:888
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
std::vector< std::set< irep_idt > > pointers_to_treat_equal
std::map< irep_idt, irep_idt > array_name_to_associated_array_size_variable
bool handle_option(const std::string &option, const std::list< std::string > &values)
Parse the options specific for recursive initialisation.
std::set< irep_idt > variables_that_hold_array_sizes
std::unordered_set< irep_idt > potential_null_function_pointers
typet remove_const(typet type)
Remove const qualifier from type (if any).
Definition type.cpp:32
#define size_type
Definition unistd.c:186