@@ -169,6 +169,10 @@ code_blockt recursive_initializationt::build_constructor_body(
169
169
}
170
170
else if (type.id () == ID_pointer)
171
171
{
172
+ if (type.subtype ().id () == ID_code)
173
+ {
174
+ return build_function_pointer_constructor (result_symbol);
175
+ }
172
176
if (lhs_name.has_value ())
173
177
{
174
178
if (should_be_treated_as_cstring (*lhs_name) && type == char_type ())
@@ -192,7 +196,7 @@ code_blockt recursive_initializationt::build_constructor_body(
192
196
}
193
197
}
194
198
195
- const irep_idt & recursive_initializationt::build_constructor (const exprt &expr)
199
+ irep_idt recursive_initializationt::build_constructor (const exprt &expr)
196
200
{
197
201
// for `expr` of type T builds a declaration of a function:
198
202
//
@@ -786,7 +790,7 @@ code_blockt recursive_initializationt::build_dynamic_array_constructor(
786
790
787
791
bool recursive_initializationt::needs_freeing (const exprt &expr) const
788
792
{
789
- if (expr.type ().id () != ID_pointer)
793
+ if (expr.type ().id () != ID_pointer || expr. type (). subtype (). id () == ID_code )
790
794
return false ;
791
795
if (common_arguments_origin.has_value () && expr.id () == ID_symbol)
792
796
{
@@ -797,3 +801,54 @@ bool recursive_initializationt::needs_freeing(const exprt &expr) const
797
801
}
798
802
return true ;
799
803
}
804
+
805
+ code_blockt recursive_initializationt::build_function_pointer_constructor (
806
+ const exprt &result)
807
+ {
808
+ PRECONDITION (can_cast_type<pointer_typet>(result.type ()));
809
+ const auto &result_type = to_pointer_type (result.type ());
810
+ PRECONDITION (can_cast_type<pointer_typet>(result_type.subtype ()));
811
+ const auto &function_pointer_type = to_pointer_type (result_type.subtype ());
812
+ PRECONDITION (can_cast_type<code_typet>(function_pointer_type.subtype ()));
813
+ const auto &function_type = to_code_type (function_pointer_type.subtype ());
814
+
815
+ std::vector<symbol_exprt> targets;
816
+
817
+ for (const auto &sym : goto_model.get_symbol_table ())
818
+ {
819
+ if (sym.second .type == function_type)
820
+ {
821
+ targets.push_back (sym.second .symbol_expr ());
822
+ }
823
+ }
824
+
825
+ code_blockt body{};
826
+
827
+ const auto function_pointer_selector =
828
+ get_fresh_local_symexpr (" function_pointer_selector" );
829
+ body.add (
830
+ code_assignt{function_pointer_selector,
831
+ side_effect_expr_nondett{function_pointer_selector.type ()}});
832
+ auto function_pointer_index = std::size_t {0 };
833
+
834
+ for (const auto &target : targets)
835
+ {
836
+ auto const assign =
837
+ code_assignt{dereference_exprt{result}, address_of_exprt{target}};
838
+ if (function_pointer_index != targets.size () - 1 )
839
+ {
840
+ auto const condition = equal_exprt{
841
+ function_pointer_selector,
842
+ from_integer (function_pointer_index, function_pointer_selector.type ())};
843
+ auto const then = code_blockt{{assign, code_returnt{}}};
844
+ body.add (code_ifthenelset{condition, then});
845
+ }
846
+ else
847
+ {
848
+ body.add (assign);
849
+ }
850
+ ++function_pointer_index;
851
+ }
852
+
853
+ return body;
854
+ }
0 commit comments