Skip to content

Commit 60398e7

Browse files
committed
Function pointer parameter to function pointer argument
Add mapping from function pointer argument names to local variable names of the harness so users can specify properties of arguments in terms of the names of the arguments rather than having to rely on internal implementation details of the function harness.
1 parent 5bc6c5f commit 60398e7

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

regression/goto-harness/function_pointer_nullable/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
CORE
22
test.c
3-
--harness-type call-function --function entry_point --function-pointer-can-be-null __goto_harness::f_but_may_be_null
3+
--harness-type call-function --function entry_point --function-pointer-can-be-null entry_point::f_but_may_be_null
44
^EXIT=10$
55
^SIGNAL=0$
66
\[entry_point.assertion.1\] line \d+ assertion f != \(void \*\)0: SUCCESS

src/goto-harness/function_call_harness_generator.cpp

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ struct function_call_harness_generatort::implt
8181
void call_function(
8282
const code_function_callt::argumentst &arguments,
8383
code_blockt &function_body);
84+
/// For function parameters that are pointers to functions we want to
85+
/// be able to specify whether or not they can be NULL. To disambiguate
86+
/// this specification from that for a global variable of the same name,
87+
/// we prepend the name of the function to the parameter name. However,
88+
/// what is actually being initialised in the implementation is not the
89+
/// parameter itself, but a correspond function argument (local variable
90+
/// of the harness function). We need a mapping from function parameter
91+
/// name to function argument names, and this is what this function does.
92+
std::unordered_set<irep_idt>
93+
map_function_parameters_to_function_argument_names();
8494
};
8595

8696
function_call_harness_generatort::function_call_harness_generatort(
@@ -218,6 +228,8 @@ void function_call_harness_generatort::implt::generate(
218228
recursive_initialization_config.variables_that_hold_array_sizes.insert(
219229
pair.second);
220230
}
231+
recursive_initialization_config.potential_null_function_pointers =
232+
map_function_parameters_to_function_argument_names();
221233
recursive_initialization_config.pointers_to_treat_as_cstrings =
222234
function_arguments_to_treat_as_cstrings;
223235
recursive_initialization = util_make_unique<recursive_initializationt>(
@@ -335,6 +347,43 @@ void function_call_harness_generatort::validate_options(
335347
"--" FUNCTION_HARNESS_GENERATOR_TREAT_POINTERS_EQUAL_OPT};
336348
}
337349
}
350+
351+
const namespacet ns{goto_model.symbol_table};
352+
353+
// Make sure all function pointers that the user asks are nullable are
354+
// present in the symbol table.
355+
for(const auto &nullable :
356+
p_impl->recursive_initialization_config.potential_null_function_pointers)
357+
{
358+
const auto &function_pointer_symbol_pointer =
359+
goto_model.symbol_table.lookup(nullable);
360+
361+
if(function_pointer_symbol_pointer == nullptr)
362+
{
363+
throw invalid_command_line_argument_exceptiont{
364+
"nullable function pointer `" + id2string(nullable) +
365+
"' not found in symbol table",
366+
"--" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
367+
}
368+
369+
const auto &function_pointer_type =
370+
ns.follow(function_pointer_symbol_pointer->type);
371+
372+
if(!can_cast_type<pointer_typet>(function_pointer_type))
373+
{
374+
throw invalid_command_line_argument_exceptiont{
375+
"`" + id2string(nullable) + "' is not a pointer",
376+
"--" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
377+
}
378+
379+
if(!can_cast_type<code_typet>(
380+
to_pointer_type(function_pointer_type).subtype()))
381+
{
382+
throw invalid_command_line_argument_exceptiont{
383+
"`" + id2string(nullable) + "' is not pointing to a function",
384+
"--" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
385+
}
386+
}
338387
}
339388

340389
const symbolt &
@@ -468,3 +517,25 @@ void function_call_harness_generatort::implt::call_function(
468517

469518
function_body.add(std::move(function_call));
470519
}
520+
521+
std::unordered_set<irep_idt> function_call_harness_generatort::implt::
522+
map_function_parameters_to_function_argument_names()
523+
{
524+
std::unordered_set<irep_idt> nullables;
525+
for(const auto &nullable :
526+
recursive_initialization_config.potential_null_function_pointers)
527+
{
528+
const auto &nullable_name = id2string(nullable);
529+
const auto &function_prefix = id2string(function) + "::";
530+
if(has_prefix(nullable_name, function_prefix))
531+
{
532+
nullables.insert(
533+
"__goto_harness::" + nullable_name.substr(function_prefix.size()));
534+
}
535+
else
536+
{
537+
nullables.insert(nullable_name);
538+
}
539+
}
540+
return nullables;
541+
}

0 commit comments

Comments
 (0)