@@ -9,9 +9,14 @@ Author: Diffblue Ltd.
9
9
#include " restrict_function_pointers.h"
10
10
11
11
#include < ansi-c/expr2c.h>
12
+ #include < json/json_parser.h>
12
13
#include < util/expr_iterator.h>
13
14
#include < util/string_utils.h>
14
15
16
+ #include < algorithm>
17
+ #include < fstream>
18
+ #include < iostream>
19
+
15
20
namespace
16
21
{
17
22
void typecheck_function_pointer_restrictions (
@@ -77,7 +82,7 @@ source_locationt make_function_pointer_restriction_assertion_source_location(
77
82
<< " must be " ;
78
83
if (restriction.second .size () == 1 )
79
84
{
80
- comment << restriction.second .front ();
85
+ comment << * restriction.second .begin ();
81
86
}
82
87
else
83
88
{
@@ -197,13 +202,46 @@ void restrict_function_pointers(
197
202
}
198
203
}
199
204
200
- function_pointer_restrictionst
201
- function_pointer_restrictionst::from_options (const optionst &options)
205
+ void parse_function_pointer_restriction_options_from_cmdline (
206
+ const cmdlinet &cmdline,
207
+ optionst &options)
208
+ {
209
+ options.set_option (
210
+ RESTRICT_FUNCTION_POINTER_OPT,
211
+ cmdline.get_values (RESTRICT_FUNCTION_POINTER_OPT));
212
+ options.set_option (
213
+ RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT,
214
+ cmdline.get_values (RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT));
215
+ }
216
+
217
+ namespace
218
+ {
219
+ function_pointer_restrictionst::restrictionst
220
+ merge_function_pointer_restrictions (
221
+ const function_pointer_restrictionst::restrictionst &lhs,
222
+ const function_pointer_restrictionst::restrictionst &rhs)
223
+ {
224
+ auto result = lhs;
225
+ for (auto const &restriction : rhs)
226
+ {
227
+ auto emplace_result = result.emplace (restriction.first , restriction.second );
228
+ if (!emplace_result.second )
229
+ {
230
+ for (auto const &target : restriction.second )
231
+ {
232
+ emplace_result.first ->second .insert (target);
233
+ }
234
+ }
235
+ }
236
+ return result;
237
+ }
238
+
239
+ function_pointer_restrictionst::restrictionst
240
+ parse_function_pointer_restrictions_from_command_line (
241
+ const std::list<std::string> &restriction_opts)
202
242
{
203
243
auto function_pointer_restrictions =
204
- std::unordered_map<irep_idt, std::vector<irep_idt>>{};
205
- auto const restriction_opts =
206
- options.get_list_option (RESTRICT_FUNCTION_POINTER_OPT);
244
+ function_pointer_restrictionst::restrictionst{};
207
245
for (auto const &restriction_opt : restriction_opts)
208
246
{
209
247
// the format for restrictions is <pointer_name>/<target[,more_targets]*>
@@ -244,11 +282,11 @@ function_pointer_restrictionst::from_options(const optionst &options)
244
282
restriction_format_message};
245
283
}
246
284
auto const target_names = ([&target_name_strings] {
247
- auto target_names = std::vector <irep_idt>(target_name_strings. size ()) ;
285
+ auto target_names = std::unordered_set <irep_idt>{} ;
248
286
std::transform (
249
287
target_name_strings.begin (),
250
288
target_name_strings.end (),
251
- target_names. begin ( ),
289
+ std::inserter ( target_names, target_names. end () ),
252
290
string2id);
253
291
return target_names;
254
292
})();
@@ -273,5 +311,106 @@ function_pointer_restrictionst::from_options(const optionst &options)
273
311
" --" RESTRICT_FUNCTION_POINTER_OPT};
274
312
};
275
313
}
276
- return {function_pointer_restrictions};
314
+ return function_pointer_restrictions;
315
+ }
316
+
317
+ function_pointer_restrictionst::restrictionst
318
+ parse_function_pointer_restrictions_from_file (
319
+ const std::list<std::string> &filenames,
320
+ message_handlert &message_handler)
321
+ {
322
+ auto merged_restrictions = function_pointer_restrictionst::restrictionst{};
323
+ for (auto const &filename : filenames)
324
+ {
325
+ auto const restrictions =
326
+ function_pointer_restrictionst::read_from_file (filename, message_handler);
327
+ merged_restrictions = merge_function_pointer_restrictions (
328
+ merged_restrictions, restrictions.restrictions );
329
+ }
330
+ return merged_restrictions;
331
+ }
332
+ } // namespace
333
+
334
+ function_pointer_restrictionst function_pointer_restrictionst::from_options (
335
+ const optionst &options,
336
+ message_handlert &message_handler)
337
+ {
338
+ auto const restriction_opts =
339
+ options.get_list_option (RESTRICT_FUNCTION_POINTER_OPT);
340
+ auto const commandline_restrictions =
341
+ parse_function_pointer_restrictions_from_command_line (restriction_opts);
342
+ auto const file_restrictions = parse_function_pointer_restrictions_from_file (
343
+ options.get_list_option (RESTRICT_FUNCTION_POINTER_FROM_FILE_OPT),
344
+ message_handler);
345
+ return {merge_function_pointer_restrictions (
346
+ file_restrictions, commandline_restrictions)};
347
+ }
348
+
349
+ function_pointer_restrictionst function_pointer_restrictionst::read_from_file (
350
+ const std::string &filename,
351
+ message_handlert &message_handler)
352
+ {
353
+ auto failed = [](bool failFlag) { return failFlag; };
354
+ function_pointer_restrictionst::restrictionst restrictions;
355
+ auto inFile = std::ifstream{filename};
356
+ jsont json;
357
+ if (failed (parse_json (inFile, filename, message_handler, json)))
358
+ {
359
+ throw system_exceptiont{
360
+ " failed to read function pointer restrictions from " + filename};
361
+ }
362
+ if (!json.is_object ())
363
+ {
364
+ throw system_exceptiont{" top level item is not an object" };
365
+ }
366
+ for (auto const &kv_pair : to_json_object (json))
367
+ {
368
+ restrictions.emplace (irep_idt{kv_pair.first }, [&] {
369
+ if (!kv_pair.second .is_array ())
370
+ {
371
+ throw system_exceptiont{" In " + filename + " , value of " +
372
+ kv_pair.first + " is not an array" };
373
+ }
374
+ auto possible_targets = std::unordered_set<irep_idt>{};
375
+ auto const &array = to_json_array (kv_pair.second );
376
+ std::transform (
377
+ array.begin (),
378
+ array.end (),
379
+ std::inserter (possible_targets, possible_targets.end ()),
380
+ [&](const jsont &array_element) {
381
+ if (!array_element.is_string ())
382
+ {
383
+ throw system_exceptiont{" In " + filename + " , value of " +
384
+ kv_pair.first +
385
+ " contains a non-string array element" };
386
+ }
387
+ return irep_idt{to_json_string (array_element).value };
388
+ });
389
+ return possible_targets;
390
+ }());
391
+ }
392
+ return function_pointer_restrictionst{restrictions};
393
+ }
394
+ void function_pointer_restrictionst::write_to_file (
395
+ const std::string &filename) const
396
+ {
397
+ auto function_pointer_restrictions_json = jsont{};
398
+ auto &restrictions_json_object =
399
+ function_pointer_restrictions_json.make_object ();
400
+ for (auto const &restriction : restrictions)
401
+ {
402
+ auto &targets_array =
403
+ restrictions_json_object[id2string (restriction.first )].make_array ();
404
+ for (auto const &target : restriction.second )
405
+ {
406
+ targets_array.push_back (json_stringt{target});
407
+ }
408
+ }
409
+ auto outFile = std::ofstream{filename};
410
+ if (!outFile)
411
+ {
412
+ throw system_exceptiont{" cannot open " + filename +
413
+ " for writing function pointer restrictions" };
414
+ }
415
+ function_pointer_restrictions_json.output (outFile);
277
416
}
0 commit comments