@@ -84,14 +84,14 @@ static void restrict_function_pointer(
8484}
8585} // namespace
8686
87- function_pointer_restrictionst::invalid_restriction_exceptiont::
88- invalid_restriction_exceptiont (std::string reason, std::string correct_format)
87+ invalid_restriction_exceptiont::invalid_restriction_exceptiont (
88+ std::string reason,
89+ std::string correct_format)
8990 : reason(std::move(reason)), correct_format(std::move(correct_format))
9091{
9192}
9293
93- std::string
94- function_pointer_restrictionst::invalid_restriction_exceptiont::what () const
94+ std::string invalid_restriction_exceptiont::what () const
9595{
9696 std::string res;
9797
@@ -169,8 +169,13 @@ void function_pointer_restrictionst::typecheck_function_pointer_restrictions(
169169void restrict_function_pointers (
170170 message_handlert &message_handler,
171171 goto_modelt &goto_model,
172- const function_pointer_restrictionst &restrictions )
172+ const optionst &options )
173173{
174+ const auto restrictions = function_pointer_restrictionst::from_options (
175+ options, goto_model, message_handler);
176+ if (restrictions.restrictions .empty ())
177+ return ;
178+
174179 for (auto &function_item : goto_model.goto_functions .function_map )
175180 {
176181 goto_functiont &goto_function = function_item.second ;
@@ -276,13 +281,15 @@ function_pointer_restrictionst::restrictionst function_pointer_restrictionst::
276281function_pointer_restrictionst::restrictionst
277282function_pointer_restrictionst::parse_function_pointer_restrictions_from_file (
278283 const std::list<std::string> &filenames,
284+ const goto_modelt &goto_model,
279285 message_handlert &message_handler)
280286{
281287 auto merged_restrictions = function_pointer_restrictionst::restrictionst{};
282288
283289 for (auto const &filename : filenames)
284290 {
285- auto const restrictions = read_from_file (filename, message_handler);
291+ auto const restrictions =
292+ read_from_file (filename, goto_model, message_handler);
286293
287294 merged_restrictions = merge_function_pointer_restrictions (
288295 std::move (merged_restrictions), restrictions.restrictions );
@@ -291,6 +298,66 @@ function_pointer_restrictionst::parse_function_pointer_restrictions_from_file(
291298 return merged_restrictions;
292299}
293300
301+ // / Parse \p candidate to distinguish whether it refers to a function pointer
302+ // / symbol directly (as produced by \ref label_function_pointer_call_sites), or
303+ // / a source location via its statement label. In the latter case, resolve the
304+ // / name to the underlying function pointer symbol.
305+ static std::string resolve_pointer_name (
306+ const std::string &candidate,
307+ const goto_modelt &goto_model)
308+ {
309+ const auto last_dot = candidate.rfind (' .' );
310+ if (
311+ last_dot == std::string::npos || last_dot + 1 == candidate.size () ||
312+ isdigit (candidate[last_dot + 1 ]))
313+ {
314+ return candidate;
315+ }
316+
317+ std::string pointer_name = candidate;
318+
319+ const auto function_id = pointer_name.substr (0 , last_dot);
320+ const auto label = pointer_name.substr (last_dot + 1 );
321+
322+ bool found = false ;
323+ const auto it = goto_model.goto_functions .function_map .find (function_id);
324+ if (it != goto_model.goto_functions .function_map .end ())
325+ {
326+ optionalt<source_locationt> location;
327+ for (const auto &instruction : it->second .body .instructions )
328+ {
329+ if (
330+ std::find (
331+ instruction.labels .begin (), instruction.labels .end (), label) !=
332+ instruction.labels .end ())
333+ {
334+ location = instruction.source_location ();
335+ }
336+
337+ if (
338+ instruction.is_function_call () &&
339+ instruction.call_function ().id () == ID_dereference &&
340+ location.has_value () && instruction.source_location () == *location)
341+ {
342+ auto const &called_function_pointer =
343+ to_dereference_expr (instruction.call_function ()).pointer ();
344+ pointer_name =
345+ id2string (to_symbol_expr (called_function_pointer).get_identifier ());
346+ found = true ;
347+ break ;
348+ }
349+ }
350+ }
351+ if (!found)
352+ {
353+ throw invalid_restriction_exceptiont{
354+ " non-existent pointer name " + pointer_name,
355+ " pointers should be identifiers or <function_name>.<label>" };
356+ }
357+
358+ return pointer_name;
359+ }
360+
294361function_pointer_restrictionst::restrictiont
295362function_pointer_restrictionst::parse_function_pointer_restriction (
296363 const std::string &restriction_opt,
@@ -324,51 +391,8 @@ function_pointer_restrictionst::parse_function_pointer_restriction(
324391 " couldn't find target name before '/' in `" + restriction_opt + " '" };
325392 }
326393
327- auto pointer_name = restriction_opt.substr (0 , pointer_name_end);
328- const auto last_dot = pointer_name.rfind (' .' );
329- if (
330- last_dot != std::string::npos && last_dot + 1 != pointer_name.size () &&
331- !isdigit (pointer_name[last_dot + 1 ]))
332- {
333- const auto function_id = pointer_name.substr (0 , last_dot);
334- const auto label = pointer_name.substr (last_dot + 1 );
335-
336- bool found = false ;
337- const auto it = goto_model.goto_functions .function_map .find (function_id);
338- if (it != goto_model.goto_functions .function_map .end ())
339- {
340- optionalt<source_locationt> location;
341- for (const auto &instruction : it->second .body .instructions )
342- {
343- if (
344- std::find (
345- instruction.labels .begin (), instruction.labels .end (), label) !=
346- instruction.labels .end ())
347- {
348- location = instruction.source_location ();
349- }
350-
351- if (
352- instruction.is_function_call () &&
353- instruction.call_function ().id () == ID_dereference &&
354- location.has_value () && instruction.source_location () == *location)
355- {
356- auto const &called_function_pointer =
357- to_dereference_expr (instruction.call_function ()).pointer ();
358- pointer_name =
359- id2string (to_symbol_expr (called_function_pointer).get_identifier ());
360- found = true ;
361- break ;
362- }
363- }
364- }
365- if (!found)
366- {
367- throw invalid_restriction_exceptiont{" non-existent pointer name " +
368- pointer_name,
369- restriction_format_message};
370- }
371- }
394+ std::string pointer_name = resolve_pointer_name (
395+ restriction_opt.substr (0 , pointer_name_end), goto_model);
372396
373397 auto const target_names_substring =
374398 restriction_opt.substr (pointer_name_end + 1 );
@@ -470,7 +494,7 @@ function_pointer_restrictionst function_pointer_restrictionst::from_options(
470494 auto const restriction_file_opts =
471495 options.get_list_option (RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT);
472496 file_restrictions = parse_function_pointer_restrictions_from_file (
473- restriction_file_opts, message_handler);
497+ restriction_file_opts, goto_model, message_handler);
474498 typecheck_function_pointer_restrictions (goto_model, file_restrictions);
475499 }
476500 catch (const invalid_restriction_exceptiont &e)
@@ -498,8 +522,9 @@ function_pointer_restrictionst function_pointer_restrictionst::from_options(
498522 merge_function_pointer_restrictions (file_restrictions, name_restrictions))};
499523}
500524
501- function_pointer_restrictionst
502- function_pointer_restrictionst::from_json (const jsont &json)
525+ function_pointer_restrictionst function_pointer_restrictionst::from_json (
526+ const jsont &json,
527+ const goto_modelt &goto_model)
503528{
504529 function_pointer_restrictionst::restrictionst restrictions;
505530
@@ -510,7 +535,9 @@ function_pointer_restrictionst::from_json(const jsont &json)
510535
511536 for (auto const &restriction : to_json_object (json))
512537 {
513- restrictions.emplace (irep_idt{restriction.first }, [&] {
538+ std::string pointer_name =
539+ resolve_pointer_name (restriction.first , goto_model);
540+ restrictions.emplace (irep_idt{pointer_name}, [&] {
514541 if (!restriction.second .is_array ())
515542 {
516543 throw deserialization_exceptiont{" Value of " + restriction.first +
@@ -540,6 +567,7 @@ function_pointer_restrictionst::from_json(const jsont &json)
540567
541568function_pointer_restrictionst function_pointer_restrictionst::read_from_file (
542569 const std::string &filename,
570+ const goto_modelt &goto_model,
543571 message_handlert &message_handler)
544572{
545573 auto inFile = std::ifstream{filename};
@@ -551,7 +579,7 @@ function_pointer_restrictionst function_pointer_restrictionst::read_from_file(
551579 " failed to read function pointer restrictions from " + filename};
552580 }
553581
554- return from_json (json);
582+ return from_json (json, goto_model );
555583}
556584
557585jsont function_pointer_restrictionst::to_json () const
0 commit comments