@@ -84,14 +84,14 @@ static void restrict_function_pointer(
84
84
}
85
85
} // namespace
86
86
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)
89
90
: reason(std::move(reason)), correct_format(std::move(correct_format))
90
91
{
91
92
}
92
93
93
- std::string
94
- function_pointer_restrictionst::invalid_restriction_exceptiont::what () const
94
+ std::string invalid_restriction_exceptiont::what () const
95
95
{
96
96
std::string res;
97
97
@@ -169,8 +169,13 @@ void function_pointer_restrictionst::typecheck_function_pointer_restrictions(
169
169
void restrict_function_pointers (
170
170
message_handlert &message_handler,
171
171
goto_modelt &goto_model,
172
- const function_pointer_restrictionst &restrictions )
172
+ const optionst &options )
173
173
{
174
+ const auto restrictions = function_pointer_restrictionst::from_options (
175
+ options, goto_model, message_handler);
176
+ if (restrictions.restrictions .empty ())
177
+ return ;
178
+
174
179
for (auto &function_item : goto_model.goto_functions .function_map )
175
180
{
176
181
goto_functiont &goto_function = function_item.second ;
@@ -276,13 +281,15 @@ function_pointer_restrictionst::restrictionst function_pointer_restrictionst::
276
281
function_pointer_restrictionst::restrictionst
277
282
function_pointer_restrictionst::parse_function_pointer_restrictions_from_file (
278
283
const std::list<std::string> &filenames,
284
+ const goto_modelt &goto_model,
279
285
message_handlert &message_handler)
280
286
{
281
287
auto merged_restrictions = function_pointer_restrictionst::restrictionst{};
282
288
283
289
for (auto const &filename : filenames)
284
290
{
285
- auto const restrictions = read_from_file (filename, message_handler);
291
+ auto const restrictions =
292
+ read_from_file (filename, goto_model, message_handler);
286
293
287
294
merged_restrictions = merge_function_pointer_restrictions (
288
295
std::move (merged_restrictions), restrictions.restrictions );
@@ -291,6 +298,66 @@ function_pointer_restrictionst::parse_function_pointer_restrictions_from_file(
291
298
return merged_restrictions;
292
299
}
293
300
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
+
294
361
function_pointer_restrictionst::restrictiont
295
362
function_pointer_restrictionst::parse_function_pointer_restriction (
296
363
const std::string &restriction_opt,
@@ -324,51 +391,8 @@ function_pointer_restrictionst::parse_function_pointer_restriction(
324
391
" couldn't find target name before '/' in `" + restriction_opt + " '" };
325
392
}
326
393
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);
372
396
373
397
auto const target_names_substring =
374
398
restriction_opt.substr (pointer_name_end + 1 );
@@ -470,7 +494,7 @@ function_pointer_restrictionst function_pointer_restrictionst::from_options(
470
494
auto const restriction_file_opts =
471
495
options.get_list_option (RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT);
472
496
file_restrictions = parse_function_pointer_restrictions_from_file (
473
- restriction_file_opts, message_handler);
497
+ restriction_file_opts, goto_model, message_handler);
474
498
typecheck_function_pointer_restrictions (goto_model, file_restrictions);
475
499
}
476
500
catch (const invalid_restriction_exceptiont &e)
@@ -498,8 +522,9 @@ function_pointer_restrictionst function_pointer_restrictionst::from_options(
498
522
merge_function_pointer_restrictions (file_restrictions, name_restrictions))};
499
523
}
500
524
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)
503
528
{
504
529
function_pointer_restrictionst::restrictionst restrictions;
505
530
@@ -510,7 +535,9 @@ function_pointer_restrictionst::from_json(const jsont &json)
510
535
511
536
for (auto const &restriction : to_json_object (json))
512
537
{
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}, [&] {
514
541
if (!restriction.second .is_array ())
515
542
{
516
543
throw deserialization_exceptiont{" Value of " + restriction.first +
@@ -540,6 +567,7 @@ function_pointer_restrictionst::from_json(const jsont &json)
540
567
541
568
function_pointer_restrictionst function_pointer_restrictionst::read_from_file (
542
569
const std::string &filename,
570
+ const goto_modelt &goto_model,
543
571
message_handlert &message_handler)
544
572
{
545
573
auto inFile = std::ifstream{filename};
@@ -551,7 +579,7 @@ function_pointer_restrictionst function_pointer_restrictionst::read_from_file(
551
579
" failed to read function pointer restrictions from " + filename};
552
580
}
553
581
554
- return from_json (json);
582
+ return from_json (json, goto_model );
555
583
}
556
584
557
585
jsont function_pointer_restrictionst::to_json () const
0 commit comments