@@ -690,12 +690,17 @@ code_blockt recursive_initializationt::build_pointer_constructor(
690690 seen_assign_prev = code_assignt{*has_seen, has_seen_prev};
691691 }
692692
693- const symbol_exprt &local_result =
694- get_fresh_local_typed_symexpr (" local_result" , type, nullptr_expr);
693+ // we want to initialize the pointee as non-const even for pointer to const
694+ const typet non_const_pointer_type =
695+ pointer_type (remove_const (type.subtype ()));
696+ const symbol_exprt &local_result = get_fresh_local_typed_symexpr (
697+ " local_result" , non_const_pointer_type, nullptr_expr);
695698 then_case.add (code_declt{local_result});
696699 const namespacet ns{goto_model.symbol_table };
697- then_case.add (code_function_callt{
698- local_result, get_malloc_function (), {*size_of_expr (type.subtype (), ns)}});
700+ then_case.add (
701+ code_function_callt{local_result,
702+ get_malloc_function (),
703+ {*size_of_expr (non_const_pointer_type.subtype (), ns)}});
699704 initialize (
700705 dereference_exprt{local_result},
701706 plus_exprt{depth, from_integer (1 , depth.type ())},
@@ -774,7 +779,28 @@ code_blockt recursive_initializationt::build_struct_constructor(
774779 for (const auto &component :
775780 ns.follow_tag (to_struct_tag_type (struct_type)).components ())
776781 {
777- initialize (member_exprt{dereference_exprt{result}, component}, depth, body);
782+ if (component.get_is_padding ())
783+ {
784+ continue ;
785+ }
786+ // if the struct component is const we need to cast away the const
787+ // for initialisation purposes.
788+ // As far as I'm aware that's the closest thing to a 'correct' way
789+ // to initialize dynamically allocated structs with const components
790+ exprt component_initialisation_lhs = [&result, &component]() -> exprt {
791+ auto member_expr = member_exprt{dereference_exprt{result}, component};
792+ if (component.type ().get_bool (ID_C_constant))
793+ {
794+ return dereference_exprt{
795+ typecast_exprt{address_of_exprt{std::move (member_expr)},
796+ pointer_type (remove_const (component.type ()))}};
797+ }
798+ else
799+ {
800+ return std::move (member_expr);
801+ }
802+ }();
803+ initialize (component_initialisation_lhs, depth, body);
778804 }
779805 return body;
780806}
@@ -797,9 +823,9 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
797823 const optionalt<irep_idt> &lhs_name)
798824{
799825 PRECONDITION (result.type ().id () == ID_pointer);
800- const typet &pointer_type = result.type ().subtype ();
801- PRECONDITION (pointer_type .id () == ID_pointer);
802- const typet &element_type = pointer_type .subtype ();
826+ const typet &dynamic_array_type = result.type ().subtype ();
827+ PRECONDITION (dynamic_array_type .id () == ID_pointer);
828+ const typet &element_type = dynamic_array_type .subtype ();
803829 PRECONDITION (element_type.id () != ID_empty);
804830
805831 // builds:
@@ -831,8 +857,11 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
831857 binary_relation_exprt{
832858 nondet_size, ID_le, from_integer (max_array_size, nondet_size.type ())}}});
833859
834- const symbol_exprt &local_result =
835- get_fresh_local_typed_symexpr (" local_result" , pointer_type, exprt{});
860+ // we want the local result to be mutable so we can initialise it
861+ const typet mutable_dynamic_array_type =
862+ pointer_type (remove_const (element_type));
863+ const symbol_exprt &local_result = get_fresh_local_typed_symexpr (
864+ " local_result" , mutable_dynamic_array_type, exprt{});
836865 body.add (code_declt{local_result});
837866 const namespacet ns{goto_model.symbol_table };
838867 for (auto array_size = min_array_size; array_size <= max_array_size;
0 commit comments