@@ -12,6 +12,7 @@ Author: Diffblue Ltd.
12
12
#include < util/arith_tools.h>
13
13
#include < util/c_types.h>
14
14
#include < util/exception_utils.h>
15
+ #include < util/prefix.h>
15
16
#include < util/std_code.h>
16
17
#include < util/std_expr.h>
17
18
#include < util/string2int.h>
@@ -80,6 +81,16 @@ struct function_call_harness_generatort::implt
80
81
void call_function (
81
82
const code_function_callt::argumentst &arguments,
82
83
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 corresponding 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 ();
83
94
};
84
95
85
96
function_call_harness_generatort::function_call_harness_generatort (
@@ -226,6 +237,8 @@ void function_call_harness_generatort::implt::generate(
226
237
recursive_initialization_config.variables_that_hold_array_sizes .insert (
227
238
pair.second );
228
239
}
240
+ recursive_initialization_config.potential_null_function_pointers =
241
+ map_function_parameters_to_function_argument_names ();
229
242
recursive_initialization_config.pointers_to_treat_as_cstrings =
230
243
function_arguments_to_treat_as_cstrings;
231
244
recursive_initialization = util_make_unique<recursive_initializationt>(
@@ -346,6 +359,43 @@ void function_call_harness_generatort::validate_options(
346
359
}
347
360
}
348
361
}
362
+
363
+ const namespacet ns{goto_model.symbol_table };
364
+
365
+ // Make sure all function pointers that the user asks are nullable are
366
+ // present in the symbol table.
367
+ for (const auto &nullable :
368
+ p_impl->recursive_initialization_config .potential_null_function_pointers )
369
+ {
370
+ const auto &function_pointer_symbol_pointer =
371
+ goto_model.symbol_table .lookup (nullable);
372
+
373
+ if (function_pointer_symbol_pointer == nullptr )
374
+ {
375
+ throw invalid_command_line_argument_exceptiont{
376
+ " nullable function pointer `" + id2string (nullable) +
377
+ " ' not found in symbol table" ,
378
+ " --" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
379
+ }
380
+
381
+ const auto &function_pointer_type =
382
+ ns.follow (function_pointer_symbol_pointer->type );
383
+
384
+ if (!can_cast_type<pointer_typet>(function_pointer_type))
385
+ {
386
+ throw invalid_command_line_argument_exceptiont{
387
+ " `" + id2string (nullable) + " ' is not a pointer" ,
388
+ " --" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
389
+ }
390
+
391
+ if (!can_cast_type<code_typet>(
392
+ to_pointer_type (function_pointer_type).subtype ()))
393
+ {
394
+ throw invalid_command_line_argument_exceptiont{
395
+ " `" + id2string (nullable) + " ' is not pointing to a function" ,
396
+ " --" COMMON_HARNESS_GENERATOR_FUNCTION_POINTER_CAN_BE_NULL_OPT};
397
+ }
398
+ }
349
399
}
350
400
351
401
const symbolt &
@@ -490,3 +540,25 @@ void function_call_harness_generatort::implt::call_function(
490
540
491
541
function_body.add (std::move (function_call));
492
542
}
543
+
544
+ std::unordered_set<irep_idt> function_call_harness_generatort::implt::
545
+ map_function_parameters_to_function_argument_names ()
546
+ {
547
+ std::unordered_set<irep_idt> nullables;
548
+ for (const auto &nullable :
549
+ recursive_initialization_config.potential_null_function_pointers )
550
+ {
551
+ const auto &nullable_name = id2string (nullable);
552
+ const auto &function_prefix = id2string (function) + " ::" ;
553
+ if (has_prefix (nullable_name, function_prefix))
554
+ {
555
+ nullables.insert (
556
+ " __goto_harness::" + nullable_name.substr (function_prefix.size ()));
557
+ }
558
+ else
559
+ {
560
+ nullables.insert (nullable_name);
561
+ }
562
+ }
563
+ return nullables;
564
+ }
0 commit comments