CBMC
memory_snapshot_harness_generator.cpp
Go to the documentation of this file.
1 /******************************************************************\
2 
3 Module: Harness to initialise memory from memory snapshot
4 
5 Author: Daniel Poetzl
6 
7 \******************************************************************/
8 
10 
11 #include <util/arith_tools.h>
12 #include <util/c_types.h>
13 #include <util/exception_utils.h>
14 #include <util/fresh_symbol.h>
15 #include <util/string2int.h>
16 #include <util/string_utils.h>
17 #include <util/symbol_table.h>
18 
21 
23 #include <json/json_parser.h>
24 
26 
27 #include <algorithm>
28 
30  const std::string &option,
31  const std::list<std::string> &values)
32 {
36  {
37  // the option belongs to recursive initialization
38  }
40  {
42  values.begin(), values.end());
43  }
45  {
46  for(auto const &array_size_pair : values)
47  {
48  try
49  {
50  std::string array;
51  std::string size;
52  split_string(array_size_pair, ':', array, size);
53  // --associated-array-size implies --treat-pointer-as-array
54  // but it is not an error to specify both, so we don't check
55  // for duplicates here
57  array);
58  auto const inserted =
61  if(!inserted.second)
62  {
64  "can not have two associated array sizes for one array",
66  }
67  }
68  catch(const deserialization_exceptiont &)
69  {
71  "'" + array_size_pair +
72  "' is in an invalid format for array size pair",
74  "array_name:size_name, where both are the names of global "
75  "variables"};
76  }
77  }
78  }
79  else if(option == MEMORY_SNAPSHOT_HARNESS_SNAPSHOT_OPT)
80  {
82  }
84  {
86  }
88  {
89  std::vector<std::string> havoc_candidates =
90  split_string(values.front(), ',', true);
91  for(const auto &candidate : havoc_candidates)
92  {
93  variables_to_havoc.insert(candidate);
94  }
95  }
97  {
99  }
100  else
101  {
103  "unrecognized option for memory snapshot harness generator",
104  "--" + option);
105  }
106 }
107 
109  const goto_modelt &goto_model)
110 {
111  if(memory_snapshot_file.empty())
112  {
114  "option --memory_snapshot is required",
115  "--harness-type initialize-with-memory-snapshot");
116  }
117 
119  {
121  "choose either source or goto location to specify the entry point",
122  "--initial-source/goto-location");
123  }
124 
125  if(!initial_source_location_line.empty())
126  {
129  goto_model.goto_functions);
130  }
131  else
132  {
135  goto_model.goto_functions);
136  }
137 
138  const symbol_table_baset &symbol_table = goto_model.symbol_table;
139 
140  const symbolt *called_function_symbol =
141  symbol_table.lookup(entry_location.function_name);
142 
143  if(called_function_symbol == nullptr)
144  {
146  "function `" + id2string(entry_location.function_name) +
147  "` not found in the symbol table",
148  "--initial-location");
149  }
150 }
151 
153  const symbol_exprt &func_init_done_var,
154  goto_modelt &goto_model) const
155 {
156  goto_functionst &goto_functions = goto_model.goto_functions;
157 
158  goto_functiont &goto_function =
159  goto_functions.function_map[entry_location.function_name];
160 
161  goto_programt &goto_program = goto_function.body;
162 
163  const goto_programt::const_targett start_it =
164  goto_program.instructions.begin();
165 
166  auto ins_it1 = goto_program.insert_before(
167  start_it,
169  goto_program.const_cast_target(start_it), func_init_done_var));
170 
171  auto ins_it2 = goto_program.insert_after(
172  ins_it1,
174  code_assignt(func_init_done_var, true_exprt())));
175 
176  goto_program.compute_location_numbers();
177  goto_program.insert_after(
178  ins_it2,
181 }
182 
184  const symbolt &snapshot_symbol,
185  symbol_table_baset &symbol_table) const
186 {
187  symbolt &tmp_symbol = get_fresh_aux_symbol(
188  snapshot_symbol.type,
189  "", // no prefix name
190  id2string(snapshot_symbol.base_name),
191  snapshot_symbol.location,
192  snapshot_symbol.mode,
193  symbol_table);
194  tmp_symbol.is_static_lifetime = true;
195  tmp_symbol.value = snapshot_symbol.value;
196 
197  return tmp_symbol;
198 }
199 
201 {
202  if(t.id() != ID_pointer)
203  return 0;
204  else
205  return pointer_depth(to_pointer_type(t).base_type()) + 1;
206 }
207 
209  const symbol_table_baset &snapshot,
210  goto_modelt &goto_model) const
211 {
212  recursive_initializationt recursive_initialization{
213  recursive_initialization_config, goto_model};
214 
215  std::vector<std::pair<irep_idt, symbolt>> ordered_snapshot_symbols;
216  // sort the snapshot symbols so that the non-pointer symbols are first, then
217  // pointers, then pointers-to-pointers, etc. so that we don't assign
218  // uninitialized values
219  {
220  std::vector<std::pair<irep_idt, symbolt>> selected_snapshot_symbols;
221  using relationt = typename preordert<irep_idt>::relationt;
222  relationt reference_relation;
223 
224  for(const auto &snapshot_pair : snapshot)
225  {
226  const auto name = id2string(snapshot_pair.first);
227  if(name.find(CPROVER_PREFIX) != 0)
228  {
230  snapshot_pair.second.value,
231  [&reference_relation, &snapshot_pair](const irep_idt &id) {
232  reference_relation.insert(std::make_pair(snapshot_pair.first, id));
233  });
234  selected_snapshot_symbols.push_back(snapshot_pair);
235  }
236  }
237  preordert<irep_idt> reference_order{reference_relation};
238  reference_order.sort(selected_snapshot_symbols, ordered_snapshot_symbols);
239  }
240 
241  code_blockt code{};
242 
243  // add initialization for existing globals
244  for(const auto &pair : goto_model.symbol_table)
245  {
246  const auto &global_symbol = pair.second;
248  {
249  auto symeexr = global_symbol.symbol_expr();
250  if(symeexr.type() == global_symbol.value.type())
251  code.add(code_assignt{symeexr, global_symbol.value});
252  }
253  }
254 
255  for(const auto &pair : ordered_snapshot_symbols)
256  {
257  const symbolt &snapshot_symbol = pair.second;
258  symbol_table_baset &symbol_table = goto_model.symbol_table;
259 
260  auto should_get_fresh = [&symbol_table](const symbolt &symbol) {
261  return symbol_table.lookup(symbol.base_name) == nullptr &&
262  !symbol.is_type;
263  };
264  const symbolt &fresh_or_snapshot_symbol =
265  should_get_fresh(snapshot_symbol)
266  ? fresh_symbol_copy(snapshot_symbol, symbol_table)
267  : snapshot_symbol;
268 
270  fresh_or_snapshot_symbol))
271  continue;
272 
273  if(variables_to_havoc.count(fresh_or_snapshot_symbol.base_name) == 0)
274  {
275  code.add(code_assignt{fresh_or_snapshot_symbol.symbol_expr(),
276  fresh_or_snapshot_symbol.value});
277  }
278  else
279  {
280  recursive_initialization.initialize(
281  fresh_or_snapshot_symbol.symbol_expr(),
282  from_integer(0, size_type()),
283  code);
284  }
285  }
286  return code;
287 }
288 
290  const symbolt &called_function_symbol,
291  code_blockt &code) const
292 {
293  const code_typet &code_type = to_code_type(called_function_symbol.type);
294 
296 
297  for(const code_typet::parametert &parameter : code_type.parameters())
298  {
299  arguments.push_back(side_effect_expr_nondett{
300  parameter.type(), called_function_symbol.location});
301  }
302 
303  code.add(code_function_callt{called_function_symbol.symbol_expr(),
304  std::move(arguments)});
305 }
306 
309  goto_modelt &goto_model,
310  const symbolt &function) const
311 {
312  const auto r = goto_model.symbol_table.insert(function);
313  CHECK_RETURN(r.second);
314 
315  auto function_iterator_pair = goto_model.goto_functions.function_map.emplace(
316  function.name, goto_functiont{});
317 
318  CHECK_RETURN(function_iterator_pair.second);
319 
320  goto_functiont &harness_function = function_iterator_pair.first->second;
321 
322  goto_convert(
323  goto_model.symbol_table, goto_model.goto_functions, message_handler);
324  harness_function.body.add(goto_programt::make_end_function());
325 }
326 
328  const std::string &file,
329  symbol_table_baset &snapshot) const
330 {
331  jsont json;
332 
334 
335  if(r)
336  {
337  throw deserialization_exceptiont("failed to read JSON memory snapshot");
338  }
339 
340  if(json.is_array())
341  {
342  // since memory-analyzer produces an array JSON we need to search it
343  // to find the first JSON object that is a symbol table
344  const auto &jarr = to_json_array(json);
345  for(auto const &arr_element : jarr)
346  {
347  if(!arr_element.is_object())
348  continue;
349  const auto &json_obj = to_json_object(arr_element);
350  const auto it = json_obj.find("symbolTable");
351  if(it != json_obj.end())
352  {
353  symbol_table_from_json(json_obj, snapshot);
354  return;
355  }
356  }
358  "JSON memory snapshot does not contain symbol table");
359  }
360  else
361  {
362  // throws a deserialization_exceptiont or an
363  // incorrect_goto_program_exceptiont
364  // on failure to read JSON symbol table
365  symbol_table_from_json(json, snapshot);
366  }
367 }
368 
370  goto_modelt &goto_model,
371  const irep_idt &harness_function_name)
372 {
373  symbol_tablet snapshot;
375 
376  symbol_tablet &symbol_table = goto_model.symbol_table;
377  goto_functionst &goto_functions = goto_model.goto_functions;
378 
379  const symbolt *called_function_symbol =
380  symbol_table.lookup(entry_location.function_name);
381  recursive_initialization_config.mode = called_function_symbol->mode;
382 
383  // introduce a symbol for a Boolean variable to indicate the point at which
384  // the function initialisation is completed
385  auto &func_init_done_symbol = get_fresh_aux_symbol(
386  bool_typet(),
388  "func_init_done",
390  called_function_symbol->mode,
391  symbol_table);
392  func_init_done_symbol.is_static_lifetime = true;
393  func_init_done_symbol.value = false_exprt();
394  symbol_exprt func_init_done_var = func_init_done_symbol.symbol_expr();
395 
396  add_init_section(func_init_done_var, goto_model);
397 
398  code_blockt harness_function_body =
399  add_assignments_to_globals(snapshot, goto_model);
400 
401  harness_function_body.add(code_assignt{func_init_done_var, false_exprt{}});
402 
404  *called_function_symbol, harness_function_body);
405 
406  // Create harness function symbol
407 
408  symbolt harness_function_symbol{
409  harness_function_name,
410  code_typet({}, empty_typet()),
411  called_function_symbol->mode};
412  harness_function_symbol.base_name = harness_function_name;
413  harness_function_symbol.pretty_name = harness_function_name;
414  harness_function_symbol.is_lvalue = true;
415  harness_function_symbol.value = harness_function_body;
416 
417  // Add harness function to goto model and symbol table
418  insert_harness_function_into_goto_model(goto_model, harness_function_symbol);
419 
420  goto_functions.update();
421 }
422 
425  const std::string &cmdl_option)
426 {
427  std::vector<std::string> start = split_string(cmdl_option, ':', true);
428 
429  if(
430  start.empty() || start.front().empty() ||
431  (start.size() == 2 && start.back().empty()) || start.size() > 2)
432  {
434  "invalid initial location specification", "--initial-location");
435  }
436 
437  if(start.size() == 2)
438  {
439  const auto location_number = string2optional_unsigned(start.back());
440  CHECK_RETURN(location_number.has_value());
441  return entry_goto_locationt{start.front(), *location_number};
442  }
443  else
444  {
445  return entry_goto_locationt{start.front()};
446  }
447 }
448 
451  const std::string &cmdl_option)
452 {
453  std::string initial_file_string;
454  std::string initial_line_string;
455  split_string(
456  cmdl_option, ':', initial_file_string, initial_line_string, true);
457 
458  if(initial_file_string.empty() || initial_line_string.empty())
459  {
461  "invalid initial location specification", "--initial-file-line");
462  }
463 
464  const auto line_number = string2optional_unsigned(initial_line_string);
465  CHECK_RETURN(line_number.has_value());
466  return entry_source_locationt{initial_file_string, *line_number};
467 }
468 
471  const entry_goto_locationt &entry_goto_location,
472  const goto_functionst &goto_functions)
473 {
474  PRECONDITION(!entry_goto_location.function_name.empty());
475  const irep_idt &function_name = entry_goto_location.function_name;
476 
477  // by function(+location): search for the function then jump to n-th
478  // location, then check the number
479  const auto &goto_function =
480  goto_functions.function_map.find(entry_goto_location.function_name);
481  if(
482  goto_function != goto_functions.function_map.end() &&
483  goto_function->second.body_available())
484  {
485  const auto &goto_program = goto_function->second.body;
486 
487  const auto corresponding_instruction =
488  entry_goto_location.find_first_corresponding_instruction(
489  goto_program.instructions);
490 
491  if(corresponding_instruction != goto_program.instructions.end())
492  return entry_locationt{function_name, corresponding_instruction};
493  }
495  "could not find the specified entry point", "--initial-goto-location");
496 }
497 
500  const entry_source_locationt &entry_source_location,
501  const goto_functionst &goto_functions)
502 {
503  PRECONDITION(!entry_source_location.file_name.empty());
504 
505  source_location_matcht best_match;
506  // by line: iterate over all instructions until source location match
507  for(const auto &entry : goto_functions.function_map)
508  {
509  const auto &goto_function = entry.second;
510  // if !body_available() then body.instruction.empty() and that's fine
511  const auto &goto_program = goto_function.body;
512 
513  const auto candidate_instruction =
514  entry_source_location.find_first_corresponding_instruction(
515  goto_program.instructions);
516 
517  if(candidate_instruction.first != goto_program.instructions.end())
518  {
519  best_match.match_up(
520  candidate_instruction.second, entry.first, candidate_instruction.first);
521  }
522  }
523 
524  if(best_match.match_found)
525  return entry_locationt{best_match.function_name, best_match.instruction};
526  else
528  "could not find the specified entry point", "--initial-source-location");
529 }
530 
533  const goto_programt::instructionst &instructions) const
534 {
535  if(!location_number.has_value())
536  return instructions.begin();
537 
538  return std::find_if(
539  instructions.begin(),
540  instructions.end(),
541  [this](const goto_programt::instructiont &instruction) {
542  return *location_number == instruction.location_number;
543  });
544 }
545 
546 std::pair<goto_programt::const_targett, size_t>
549  const goto_programt::instructionst &instructions) const
550 {
551  auto it = std::find_if(
552  instructions.begin(),
553  instructions.end(),
554  [this](const goto_programt::instructiont &instruction) {
555  return instruction.source_location().get_file() == file_name &&
556  safe_string2unsigned(id2string(
557  instruction.source_location().get_line())) >= line_number;
558  });
559 
560  if(it == instructions.end())
561  return {it, 0};
562  else
563  return {it,
564  safe_string2unsigned(id2string(it->source_location().get_line())) -
565  line_number};
566 }
constant_exprt from_integer(const mp_integer &int_value, const typet &type)
The Boolean type.
Definition: std_types.h:36
A goto_instruction_codet representing an assignment in the program.
A codet representing sequential composition of program statements.
Definition: std_code.h:130
void add(const codet &code)
Definition: std_code.h:168
goto_instruction_codet representation of a function call statement.
exprt::operandst argumentst
Base type of functions.
Definition: std_types.h:583
const parameterst & parameters() const
Definition: std_types.h:699
Thrown when failing to deserialize a value from some low level format, like JSON or raw bytes.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
bool empty() const
Definition: dstring.h:89
The empty type.
Definition: std_types.h:51
typet & type()
Return the type of the expression.
Definition: expr.h:84
The Boolean constant false.
Definition: std_expr.h:3064
A collection of goto functions.
function_mapt function_map
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
Definition: goto_function.h:24
goto_programt body
Definition: goto_function.h:26
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
This class represents an instruction in the GOTO intermediate representation.
Definition: goto_program.h:181
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
instructionst instructions
The list of instructions in the goto program.
Definition: goto_program.h:622
targett const_cast_target(const_targett t)
Convert a const_targett to a targett - use with care and avoid whenever possible.
Definition: goto_program.h:626
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
instructionst::const_iterator const_targett
Definition: goto_program.h:615
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
std::list< instructiont > instructionst
Definition: goto_program.h:612
targett insert_after(const_targett target)
Insertion after the instruction pointed-to by the given instruction iterator target.
Definition: goto_program.h:708
void compute_location_numbers(unsigned &nr)
Compute location numbers.
Definition: goto_program.h:766
targett add(instructiont &&instruction)
Adds a given instruction at the end.
Definition: goto_program.h:739
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
targett insert_before(const_targett target)
Insertion before the instruction pointed-to by the given instruction iterator target.
Definition: goto_program.h:692
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
const irep_idt & id() const
Definition: irep.h:384
Definition: json.h:27
void add_init_section(const symbol_exprt &func_init_done_var, goto_modelt &goto_model) const
Modify the entry-point function to start from the user-specified initial location.
entry_locationt entry_location
data to initialize the entry function
void insert_harness_function_into_goto_model(goto_modelt &goto_model, const symbolt &function) const
Insert the function into the symbol table (and the goto functions map) of the goto_model.
const symbolt & fresh_symbol_copy(const symbolt &snapshot_symbol, symbol_table_baset &symbol_table) const
Introduce a new symbol into symbol_table with the same name and type as snapshot_symbol.
entry_locationt initialize_entry_via_goto(const entry_goto_locationt &entry_goto_location, const goto_functionst &goto_functions)
Find and return the entry instruction (requested by the user as goto location: function name + locati...
entry_source_locationt parse_source_location(const std::string &cmdl_option)
Parse a command line option to extract the user specified entry source location.
entry_locationt initialize_entry_via_source(const entry_source_locationt &entry_source_location, const goto_functionst &goto_functions)
Find and return the entry instruction (requested by the user as source location: file name + line num...
code_blockt add_assignments_to_globals(const symbol_table_baset &snapshot, goto_modelt &goto_model) const
For each global symbol in the snapshot symbol table either: 1) add code_assignt assigning a value fro...
void handle_option(const std::string &option, const std::list< std::string > &values) override
Collect the memory-snapshot specific cmdline options (one at a time)
entry_goto_locationt parse_goto_location(const std::string &cmdl_option)
Parse a command line option to extract the user specified entry goto location.
void collect_references(const exprt &expr, Adder &&add_reference) const
void generate(goto_modelt &goto_model, const irep_idt &harness_function_name) override
The main function of this harness, consists of the following:
void add_call_with_nondet_arguments(const symbolt &called_function_symbol, code_blockt &code) const
Create as many non-deterministic arguments as there are arguments of the called_function_symbol and a...
recursive_initialization_configt recursive_initialization_config
void get_memory_snapshot(const std::string &file, symbol_table_baset &snapshot) const
Parse the snapshot JSON file and initialise the symbol table.
void validate_options(const goto_modelt &goto_model) override
Check that user options make sense: On their own, e.g.
std::string memory_snapshot_file
data to store the command-line options
size_t pointer_depth(const typet &t) const
Recursively compute the pointer depth.
Class for generating initialisation code for compound structures.
static bool is_initialization_allowed(const symbolt &symbol)
A side_effect_exprt that returns a non-deterministically chosen value.
Definition: std_code.h:1520
static const source_locationt & nil()
Expression to hold a symbol (variable)
Definition: std_expr.h:131
The symbol table base class interface.
const symbolt * lookup(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
The symbol table.
Definition: symbol_table.h:14
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
Symbol table entry.
Definition: symbol.h:28
irep_idt base_name
Base (non-scoped) name.
Definition: symbol.h:46
bool is_static_lifetime
Definition: symbol.h:70
bool is_type
Definition: symbol.h:61
source_locationt location
Source code location of definition of symbol.
Definition: symbol.h:37
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
Definition: symbol.cpp:121
typet type
Type of symbol.
Definition: symbol.h:31
exprt value
Initial value of symbol.
Definition: symbol.h:34
irep_idt mode
Language mode.
Definition: symbol.h:49
The Boolean constant true.
Definition: std_expr.h:3055
The type of an expression, extends irept.
Definition: type.h:29
#define CPROVER_PREFIX
symbolt & get_fresh_aux_symbol(const typet &type, const std::string &name_prefix, const std::string &basename_prefix, const source_locationt &source_location, const irep_idt &symbol_mode, const namespacet &ns, symbol_table_baset &symbol_table)
Installs a fresh-named symbol with respect to the given namespace ns with the requested name pattern ...
Fresh auxiliary symbol creation.
void goto_convert(const codet &code, symbol_table_baset &symbol_table, goto_programt &dest, message_handlert &message_handler, const irep_idt &mode)
Goto Programs with Functions.
Symbol Table + CFG.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
static int8_t r
Definition: irep_hash.h:60
json_arrayt & to_json_array(jsont &json)
Definition: json.h:424
json_objectt & to_json_object(jsont &json)
Definition: json.h:442
bool parse_json(std::istream &in, const std::string &filename, message_handlert &message_handler, jsont &dest)
Definition: json_parser.cpp:27
void symbol_table_from_json(const jsont &in, symbol_table_baset &symbol_table)
#define MEMORY_SNAPSHOT_HARNESS_INITIAL_SOURCE_LOC_OPT
#define MEMORY_SNAPSHOT_HARNESS_HAVOC_VARIABLES_OPT
#define MEMORY_SNAPSHOT_HARNESS_ASSOCIATED_ARRAY_SIZE_OPT
#define MEMORY_SNAPSHOT_HARNESS_SNAPSHOT_OPT
#define MEMORY_SNAPSHOT_HARNESS_TREAT_POINTER_AS_ARRAY_OPT
#define MEMORY_SNAPSHOT_HARNESS_INITIAL_GOTO_LOC_OPT
std::string require_exactly_one_value(const std::string &option, const std::list< std::string > &values)
Returns the only value of a single element list, throws an exception if not passed a single element l...
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
Definition: pointer_expr.h:93
static void json(json_objectT &result, const irep_idt &property_id, const property_infot &property_info)
Definition: properties.cpp:120
#define CHECK_RETURN(CONDITION)
Definition: invariant.h:495
#define PRECONDITION(CONDITION)
Definition: invariant.h:463
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
Definition: std_types.h:788
std::optional< unsigned > string2optional_unsigned(const std::string &str, int base)
Convert string to unsigned similar to the stoul or stoull functions, return nullopt when the conversi...
Definition: string2int.cpp:65
unsigned safe_string2unsigned(const std::string &str, int base)
Definition: string2int.cpp:16
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
User provided goto location: function name and (maybe) location number; the structure wraps this opti...
goto_programt::const_targett find_first_corresponding_instruction(const goto_programt::instructionst &instructions) const
Returns the first goto_programt::instructiont represented by this goto location, i....
Wraps the information needed to identify the entry point.
User provided source location: file name and line number; the structure wraps this option with a pars...
std::pair< goto_programt::const_targett, size_t > find_first_corresponding_instruction(const goto_programt::instructionst &instructions) const
Returns the first goto_programt::instructiont represented by this source location,...
void sort(const std::vector< std::pair< Key, T >> &input, std::vector< std::pair< Key, T >> &output)
Wraps the information for source location match candidates.
void match_up(const size_t &candidate_distance, const irep_idt &candidate_function_name, const goto_programt::const_targett &candidate_instruction)
std::map< irep_idt, irep_idt > array_name_to_associated_array_size_variable
bool handle_option(const std::string &option, const std::list< std::string > &values)
Parse the options specific for recursive initialisation.
std::set< irep_idt > pointers_to_treat_as_arrays
Author: Diffblue Ltd.
#define size_type
Definition: unistd.c:347