91 std::unordered_set<irep_idt>
99 p_impl->message_handler = &message_handler;
105 const std::string &option,
106 const std::list<std::string> &values)
111 if(
p_impl->recursive_initialization_config.handle_option(option, values))
121 p_impl->nondet_globals =
true;
125 p_impl->function_parameters_to_treat_as_arrays.insert(
126 values.begin(), values.end());
130 for(
auto const &value : values)
132 for(
auto const ¶m_cluster :
split_string(value,
';'))
134 std::set<irep_idt> equal_param_set;
135 for(
auto const ¶m_id :
split_string(param_cluster,
','))
137 equal_param_set.insert(param_id);
139 p_impl->function_parameters_to_treat_equal.push_back(equal_param_set);
145 for(
auto const &array_size_pair : values)
155 p_impl->function_parameters_to_treat_as_arrays.insert(array);
156 auto const inserted =
157 p_impl->function_parameter_to_associated_array_size.emplace(
162 "can not have two associated array sizes for one array",
169 "'" + array_size_pair +
170 "' is in an invalid format for array size pair",
172 "array_name:size_name, where both are the names of function "
179 p_impl->function_parameters_to_treat_as_cstrings.insert(
180 values.begin(), values.end());
184 p_impl->recursive_initialization_config.arguments_may_be_equal =
true;
192 p_impl->recursive_initialization_config
193 .potential_null_function_pointers,
194 p_impl->recursive_initialization_config.potential_null_function_pointers
196 [](
const std::string &opt) ->
irep_idt { return irep_idt{opt}; });
204 p_impl->recursive_initialization_config
205 .potential_null_function_pointers,
206 p_impl->recursive_initialization_config.potential_null_function_pointers
208 [](
const std::string &opt) ->
irep_idt { return irep_idt{opt}; });
213 "function harness generator cannot handle this option",
"--" + option};
219 const irep_idt &harness_function_name)
221 p_impl->generate(goto_model, harness_function_name);
226 const irep_idt &harness_function_name)
279 auto globals = std::vector<symbol_exprt>{};
280 for(
const auto &symbol_table_entry : *symbol_table)
282 const auto &symbol = symbol_table_entry.second;
285 globals.push_back(symbol.symbol_expr());
288 for(
auto const &global : globals)
290 generate_initialisation_code_for(function_body, global);
299 recursive_initialization->initialize(
301 if(recursive_initialization->needs_freeing(lhs))
308 if(
p_impl->function == ID_empty_string)
310 "required parameter entry function not set",
313 p_impl->recursive_initialization_config.min_dynamic_array_size >
314 p_impl->recursive_initialization_config.max_dynamic_array_size)
317 "min dynamic array size cannot be greater than max dynamic array size",
322 const auto function_to_call_pointer =
324 if(function_to_call_pointer ==
nullptr)
328 "' does not exist in the symbol table",
333 for(
auto const &equal_cluster :
p_impl->function_parameters_to_treat_equal)
335 for(
auto const &pointer_id : equal_cluster)
337 std::string decorated_pointer_id =
339 bool is_a_param =
false;
341 for(
auto const &formal_param : ftype.parameters())
343 if(formal_param.get_identifier() == decorated_pointer_id)
346 if(formal_param.type().id() != ID_pointer)
349 id2string(pointer_id) +
" is not a pointer parameter",
352 if(common_type.
id() != ID_empty)
354 if(common_type != formal_param.type())
357 "pointer arguments of conflicting type",
362 common_type = formal_param.type();
368 id2string(pointer_id) +
" is not a parameter",
378 for(
const auto &nullable :
379 p_impl->recursive_initialization_config.potential_null_function_pointers)
381 const auto &function_pointer_symbol_pointer =
384 if(function_pointer_symbol_pointer ==
nullptr)
387 "nullable function pointer `" +
id2string(nullable) +
388 "' not found in symbol table",
392 const auto &function_pointer_type =
393 ns.follow(function_pointer_symbol_pointer->type);
398 "`" +
id2string(nullable) +
"' is not a pointer",
406 "`" +
id2string(nullable) +
"' is not pointing to a function",
415 auto function_found = symbol_table->lookup(
function);
417 if(function_found ==
nullptr)
420 "function that should be harnessed is not found " +
id2string(
function),
424 return *function_found;
430 if(symbol_table->lookup(harness_function_name))
433 "harness function already exists in the symbol table",
444 symbolt harness_function_symbol{};
445 harness_function_symbol.
name = harness_function_symbol.base_name =
446 harness_function_symbol.pretty_name = harness_function_name;
448 harness_function_symbol.is_lvalue =
true;
451 harness_function_symbol.value = std::move(function_body);
453 symbol_table->insert(harness_function_symbol);
455 goto_convert(*symbol_table, *goto_functions, *message_handler);
464 const auto ¶meters = function_type.parameters();
472 std::map<irep_idt, irep_idt> parameter_name_to_argument_name;
473 for(
const auto ¶meter : parameters)
475 auto argument = allocate_objects.allocate_automatic_local_object(
476 remove_const(parameter.type()), parameter.get_base_name());
477 parameter_name_to_argument_name.insert(
478 {parameter.get_base_name(), argument.get_identifier()});
479 arguments.push_back(argument);
482 for(
const auto &pair : parameter_name_to_argument_name)
484 auto const ¶meter_name = pair.first;
485 auto const &argument_name = pair.second;
486 if(function_parameters_to_treat_as_arrays.count(parameter_name) != 0)
488 function_arguments_to_treat_as_arrays.insert(argument_name);
491 if(function_parameters_to_treat_as_cstrings.count(parameter_name) != 0)
493 function_arguments_to_treat_as_cstrings.insert(argument_name);
496 auto it = function_parameter_to_associated_array_size.find(parameter_name);
497 if(it != function_parameter_to_associated_array_size.end())
499 auto const &associated_array_size_parameter = it->second;
500 auto associated_array_size_argument =
501 parameter_name_to_argument_name.find(associated_array_size_parameter);
503 associated_array_size_argument == parameter_name_to_argument_name.end())
506 "could not find parameter to associate the array size of array \"" +
507 id2string(parameter_name) +
"\" (Expected parameter: \"" +
508 id2string(associated_array_size_parameter) +
"\" on function \"" +
513 function_argument_to_associated_array_size.insert(
514 {argument_name, associated_array_size_argument->second});
519 for(
auto const &equal_cluster : function_parameters_to_treat_equal)
521 std::set<irep_idt> cluster_argument_names;
522 for(
auto const ¶meter_name : equal_cluster)
525 parameter_name_to_argument_name.count(parameter_name) != 0,
526 id2string(parameter_name) +
" is not a parameter");
527 cluster_argument_names.insert(
528 parameter_name_to_argument_name[parameter_name]);
530 function_arguments_to_treat_equal.push_back(cluster_argument_names);
533 allocate_objects.declare_created_symbols(function_body);
542 for(
auto const &argument : arguments)
544 generate_initialisation_code_for(function_body, argument);
545 if(recursive_initialization->needs_freeing(argument))
549 std::move(arguments)};
552 function_body.
add(std::move(function_call));
558 std::unordered_set<irep_idt> nullables;
559 for(
const auto &nullable :
560 recursive_initialization_config.potential_null_function_pointers)
562 const auto &nullable_name =
id2string(nullable);
563 const auto &function_prefix =
id2string(
function) +
"::";
564 if(
has_prefix(nullable_name, function_prefix))
567 "__goto_harness::" + nullable_name.substr(function_prefix.size()));
571 nullables.insert(nullable_name);