CBMC
dfcc.cpp
Go to the documentation of this file.
1 /*******************************************************************\
2 
3 Module: Dynamic frame condition checking
4 
5 Author: Remi Delmas, delmarsd@amazon.com
6 
7 \*******************************************************************/
8 
9 #include "dfcc.h"
10 
11 #include <util/config.h>
12 #include <util/expr_util.h>
13 #include <util/format_expr.h>
14 #include <util/format_type.h>
15 #include <util/fresh_symbol.h>
16 #include <util/mathematical_expr.h>
18 #include <util/namespace.h>
19 #include <util/pointer_expr.h>
22 #include <util/prefix.h>
23 #include <util/std_expr.h>
24 #include <util/string_utils.h>
25 
34 
36 #include <ansi-c/c_expr.h>
38 #include <ansi-c/cprover_library.h>
42 #include <langapi/language.h>
43 #include <langapi/language_file.h>
44 #include <langapi/mode.h>
46 
48 
51  std::string reason,
52  std::string correct_format)
53  : cprover_exception_baset(std::move(reason)),
54  correct_format(std::move(correct_format))
55 {
56 }
57 
59 {
60  std::string res;
61 
62  res += "Invalid function-contract mapping";
63  res += "\nReason: " + reason;
64 
65  if(!correct_format.empty())
66  {
67  res += "\nFormat: " + correct_format;
68  }
69 
70  return res;
71 }
72 
73 #include <iostream>
74 
75 static std::pair<irep_idt, irep_idt>
77 {
78  auto const correct_format_message =
79  "the format for function and contract pairs is "
80  "`<function_name>[/<contract_name>]`";
81 
82  std::string cli_flag_str = id2string(cli_flag);
83 
84  auto split = split_string(cli_flag_str, '/', true, false);
85 
86  if(split.size() == 1)
87  {
88  return std::make_pair(cli_flag, cli_flag);
89  }
90  else if(split.size() == 2)
91  {
92  auto function_name = split[0];
93  if(function_name.empty())
94  {
96  "couldn't find function name before '/' in '" + cli_flag_str + "'",
97  correct_format_message};
98  }
99  auto contract_name = split[1];
100  if(contract_name.empty())
101  {
103  "couldn't find contract name after '/' in '" + cli_flag_str + "'",
104  correct_format_message};
105  }
106  return std::make_pair(function_name, contract_name);
107  }
108  else
109  {
111  "couldn't parse '" + cli_flag_str + "'", correct_format_message};
112  }
113 }
114 
115 void dfcc(
116  const optionst &options,
117  goto_modelt &goto_model,
118  const irep_idt &harness_id,
119  const std::optional<irep_idt> &to_check,
120  const bool allow_recursive_calls,
121  const std::set<irep_idt> &to_replace,
122  const bool apply_loop_contracts,
123  const bool unwind_transformed_loops,
124  const std::set<std::string> &to_exclude_from_nondet_static,
125  message_handlert &message_handler)
126 {
127  std::map<irep_idt, irep_idt> to_replace_map;
128  for(const auto &cli_flag : to_replace)
129  to_replace_map.insert(parse_function_contract_pair(cli_flag));
130 
131  dfcc(
132  options,
133  goto_model,
134  harness_id,
135  to_check.has_value() ? parse_function_contract_pair(to_check.value())
136  : std::optional<std::pair<irep_idt, irep_idt>>{},
137  allow_recursive_calls,
138  to_replace_map,
139  apply_loop_contracts,
140  unwind_transformed_loops,
141  to_exclude_from_nondet_static,
142  message_handler);
143 }
144 
145 void dfcc(
146  const optionst &options,
147  goto_modelt &goto_model,
148  const irep_idt &harness_id,
149  const std::optional<std::pair<irep_idt, irep_idt>> &to_check,
150  const bool allow_recursive_calls,
151  const std::map<irep_idt, irep_idt> &to_replace,
152  const bool apply_loop_contracts,
153  const bool unwind_transformed_loops,
154  const std::set<std::string> &to_exclude_from_nondet_static,
155  message_handlert &message_handler)
156 {
157  dfcct{
158  options,
159  goto_model,
160  harness_id,
161  to_check,
162  allow_recursive_calls,
163  to_replace,
165  apply_loop_contracts, unwind_transformed_loops),
166  message_handler,
167  to_exclude_from_nondet_static};
168 }
169 
171  const optionst &options,
172  goto_modelt &goto_model,
173  const irep_idt &harness_id,
174  const std::optional<std::pair<irep_idt, irep_idt>> &to_check,
175  const bool allow_recursive_calls,
176  const std::map<irep_idt, irep_idt> &to_replace,
177  const dfcc_loop_contract_modet loop_contract_mode,
178  message_handlert &message_handler,
179  const std::set<std::string> &to_exclude_from_nondet_static)
180  : options(options),
181  goto_model(goto_model),
182  harness_id(harness_id),
183  to_check(to_check),
184  allow_recursive_calls(allow_recursive_calls),
185  to_replace(to_replace),
186  loop_contract_mode(loop_contract_mode),
187  to_exclude_from_nondet_static(to_exclude_from_nondet_static),
188  message_handler(message_handler),
189  log(message_handler),
190  library(goto_model, message_handler),
191  ns(goto_model.symbol_table),
192  spec_functions(goto_model, message_handler, library),
193  contract_clauses_codegen(goto_model, message_handler, library),
194  instrument(
195  goto_model,
196  message_handler,
197  library,
198  spec_functions,
199  contract_clauses_codegen),
200  memory_predicates(goto_model, library, instrument, message_handler),
201  contract_handler(
202  goto_model,
203  message_handler,
204  library,
205  instrument,
206  memory_predicates,
207  spec_functions,
208  contract_clauses_codegen),
209  swap_and_wrap(
210  goto_model,
211  message_handler,
212  library,
213  instrument,
214  spec_functions,
215  contract_handler),
216  max_assigns_clause_size(0)
217 {
219 }
220 
222 {
223  // check that harness function exists
226  "Harness function '" + id2string(harness_id) +
227  "' either not found or has no body");
228 
229  if(to_check.has_value())
230  {
231  auto pair = to_check.value();
234  "Function to check '" + id2string(pair.first) +
235  "' either not found or has no body");
236 
237  // triggers signature compatibility checking
238  contract_handler.get_pure_contract_symbol(pair.second, pair.first);
239 
241  pair.first != harness_id,
242  "Function '" + id2string(pair.first) +
243  "' cannot be both be checked against a contract and be the harness");
244 
246  pair.second != harness_id,
247  "Function '" + id2string(pair.first) +
248  "' cannot be both the contract to check and be the harness");
249 
251  to_replace.find(pair.first) == to_replace.end(),
252  "Function '" + id2string(pair.first) +
253  "' cannot be both checked against contract and replaced by a contract");
254 
256  !instrument.do_not_instrument(pair.first),
257  "CPROVER function or builtin '" + id2string(pair.first) +
258  "' cannot be checked against a contract");
259  }
260 
261  for(const auto &pair : to_replace)
262  {
263  // for functions to replace with contracts we don't require the replaced
264  // function to have a body because only the contract is actually used
267  "Function to replace '" + id2string(pair.first) + "' not found");
268 
269  // triggers signature compatibility checking
270  contract_handler.get_pure_contract_symbol(pair.second, pair.first);
271 
273  pair.first != harness_id,
274  "Function '" + id2string(pair.first) +
275  "' cannot both be replaced with a contract and be the harness");
276 
278  pair.second != harness_id,
279  "Function '" + id2string(pair.first) +
280  "' cannot both be the contract to use for replacement and be the "
281  "harness");
282  }
283 }
284 
286  std::set<irep_idt> &contract_symbols,
287  std::set<irep_idt> &other_symbols)
288 {
289  // collect contract and other symbols
290  for(auto &entry : goto_model.symbol_table)
291  {
292  const symbolt &symbol = entry.second;
293 
294  // not a function symbol
295  if(symbol.type.id() != ID_code)
296  continue;
297 
298  // is it a pure contract ?
299  const irep_idt &sym_name = symbol.name;
300  if(symbol.is_property && has_prefix(id2string(sym_name), "contract::"))
301  {
302  contract_symbols.insert(sym_name);
303  }
304  else
305  {
306  // it is not a contract
307  other_symbols.insert(sym_name);
308  }
309  }
310 }
311 
313 {
314  // load the cprover library to make sure the model is complete
315  log.status() << "Loading CPROVER C library (" << config.ansi_c.arch << ")"
316  << messaget::eom;
319 
320  // this must be done before loading the dfcc lib
322 
323  // load the dfcc library before instrumentation starts
325 
326  // disable checks on all library functions
328 
329  // add C prover lib again to fetch any dependencies of the dfcc functions
332 }
333 
335 {
336  // instrument the harness function
337  // load the cprover library to make sure the model is complete
338  log.status() << "Instrumenting harness function '" << harness_id << "'"
339  << messaget::eom;
340 
343 
344  other_symbols.erase(harness_id);
345 }
346 
348 {
349  std::set<irep_idt> predicates =
351  for(const auto &predicate : predicates)
352  {
353  log.debug() << "Memory predicate" << predicate << messaget::eom;
354  if(other_symbols.find(predicate) != other_symbols.end())
355  other_symbols.erase(predicate);
356  }
357 }
358 
360 {
361  // swap-and-wrap checked functions with contracts
362  if(to_check.has_value())
363  {
364  const auto &pair = to_check.value();
365  const auto &wrapper_id = pair.first;
366  const auto &contract_id = pair.second;
367  log.status() << "Wrapping '" << wrapper_id << "' with contract '"
368  << contract_id << "' in CHECK mode" << messaget::eom;
369 
372  wrapper_id,
373  contract_id,
376 
377  if(other_symbols.find(wrapper_id) != other_symbols.end())
378  other_symbols.erase(wrapper_id);
379 
380  // update max contract size
381  const std::size_t assigns_clause_size =
383  if(assigns_clause_size > max_assigns_clause_size)
384  max_assigns_clause_size = assigns_clause_size;
385  }
386 }
387 
389 {
390  // swap-and-wrap replaced functions with contracts
391  for(const auto &pair : to_replace)
392  {
393  const auto &wrapper_id = pair.first;
394  const auto &contract_id = pair.second;
395  log.status() << "Wrapping '" << wrapper_id << "' with contract '"
396  << contract_id << "' in REPLACE mode" << messaget::eom;
398  wrapper_id, contract_id, function_pointer_contracts);
399 
400  if(other_symbols.find(wrapper_id) != other_symbols.end())
401  other_symbols.erase(wrapper_id);
402  }
403 }
404 
406 {
407  std::set<irep_idt> swapped;
408  while(!function_pointer_contracts.empty())
409  {
410  std::set<irep_idt> new_contracts;
411  // swap-and-wrap function pointer contracts with themselves
412  for(const auto &fp_contract : function_pointer_contracts)
413  {
414  if(swapped.find(fp_contract) != swapped.end())
415  continue;
416 
417  // contracts for function pointers must be replaced with themselves
418  // so we need to check that:
419  // - the symbol exists as a function symbol
420  // - the symbol exists as a pure contract symbol
421  // - the function symbol is not already swapped for contract checking
422  // - the function symbol is not already swapped with another contract for
423  // replacement
424 
425  const auto str = id2string(fp_contract);
426 
427  // Is it already swapped with another function for contract checking ?
429  !to_check.has_value() || to_check.value().first != str,
430  "Function '" + str +
431  "' used as contract for function pointer cannot be itself the object "
432  "of a contract check.");
433 
434  // Is it already swapped with another function for contract checking ?
435  auto found = to_replace.find(str);
436  if(found != to_replace.end())
437  {
439  found->first == found->second,
440  "Function '" + str +
441  "' used as contract for function pointer already the object of a "
442  "contract replacement with '" +
443  id2string(found->second) + "'");
444  log.status() << "Function pointer contract '" << fp_contract
445  << "' already wrapped with itself in REPLACE mode"
446  << messaget::eom;
447  }
448  else
449  {
450  // we need to swap it with itself
453  "Function pointer contract '" + str + "' not found.");
454 
455  // triggers signature compatibility checking
457 
458  log.status() << "Wrapping function pointer contract '" << fp_contract
459  << "' with itself in REPLACE mode" << messaget::eom;
460 
462  fp_contract, fp_contract, new_contracts);
463  swapped.insert(fp_contract);
464 
465  // remove it from the set of symbols to process
466  if(other_symbols.find(fp_contract) != other_symbols.end())
467  other_symbols.erase(fp_contract);
468  }
469  }
470  // process newly discovered contracts
471  function_pointer_contracts = new_contracts;
472  }
473 }
474 
476 {
477  // instrument all other remaining functions
478  for(const auto &function_id : other_symbols)
479  {
480  // Don't instrument CPROVER and internal functions
481  if(instrument.do_not_instrument(function_id))
482  {
483  continue;
484  }
485 
486  log.status() << "Instrumenting '" << function_id << "'" << messaget::eom;
487 
490  }
491 
493 }
494 
496 {
505 
506  // take the max of function of loop contracts assigns clauses
507  auto assigns_clause_size = instrument.get_max_assigns_clause_size();
508  if(assigns_clause_size > max_assigns_clause_size)
509  max_assigns_clause_size = assigns_clause_size;
510 
511  log.status() << "Specializing cprover_contracts functions for assigns "
512  "clauses of at most "
513  << max_assigns_clause_size << " targets" << messaget::eom;
515 
517 
518  // TODO implement a means to inhibit unreachable functions (possibly via the
519  // code that implements drop-unused-functions followed by
520  // generate-function-bodies):
521  // Traverse the call tree from the given entry point to identify
522  // functions symbols that are effectively called in the model,
523  // Then goes over all functions of the model and turns the bodies of all
524  // functions that are not in the used function set into:
525  // ```c
526  // assert(false, "function identified as unreachable");
527  // assume(false);
528  // ```
529  // That way, if the analysis mistakenly pruned some functions, assertions
530  // will be violated and the analysis will fail.
531  // TODO: add a command line flag to tell the instrumentation to not prune
532  // a function.
534 
537 
538  log.status() << "Removing unused functions" << messaget::eom;
539 
540  // This can prune too many functions if function pointers have not been
541  // yet been removed or if the entry point is not defined.
542  // Another solution would be to rewrite the bodies of functions that seem to
543  // be unreachable into assert(false);assume(false)
546 
548 }
549 
551 {
552  // collect set of functions which are now instrumented
553  std::set<irep_idt> instrumented_functions;
554  instrument.get_instrumented_functions(instrumented_functions);
555  swap_and_wrap.get_swapped_functions(instrumented_functions);
556 
557  log.status() << "Updating init function" << messaget::eom;
561 
562  // Initialize the map of instrumented functions by adding extra instructions
563  // to the harness function
564  auto &init_function = goto_model.goto_functions.function_map[harness_id];
565  auto &body = init_function.body;
566  auto begin = body.instructions.begin();
567  goto_programt payload;
569  instrumented_functions, begin->source_location(), payload);
570  body.destructive_insert(begin, payload);
571 
572  // Define harness as the entry point, overriding any preexisting one.
573  log.status() << "Setting entry point to " << harness_id << messaget::eom;
574  // remove the CPROVER start function
577  // regenerate the CPROVER start function
583 
585 }
void cprover_c_library_factory(const std::set< irep_idt > &functions, const symbol_table_baset &symbol_table, symbol_table_baset &dest_symbol_table, message_handlert &message_handler)
bool generate_ansi_c_start_function(const symbolt &symbol, symbol_table_baset &symbol_table, message_handlert &message_handler, const c_object_factory_parameterst &object_factory_parameters)
Generate a _start function for a specific function.
configt config
Definition: config.cpp:25
API to expression classes that are internal to the C frontend.
Classes providing CFG-based information about symbols to guide simplifications in function and loop a...
struct configt::ansi_ct ansi_c
Base class for exceptions thrown in the cprover project.
Definition: c_errors.h:64
std::string reason
The reason this exception was generated.
Definition: c_errors.h:83
const symbolt & get_pure_contract_symbol(const irep_idt &contract_id, const std::optional< irep_idt > function_id_opt={})
Searches for a symbol named "contract::contract_id" in the symbol table.
const std::size_t get_assigns_clause_size(const irep_idt &contract_id)
Returns the size assigns clause of the given contract in number of targets.
void get_instrumented_functions(std::set< irep_idt > &dest) const
Adds the names of instrumented functions to dest.
std::size_t get_max_assigns_clause_size() const
void instrument_harness_function(const irep_idt &function_id, const dfcc_loop_contract_modet loop_contract_mode, std::set< irep_idt > &function_pointer_contracts)
Instruments a GOTO function used as a proof harness.
bool do_not_instrument(const irep_idt &id) const
True iff the symbol must not be instrumented because it is an internal symbol or a CPROVER symbol.
void instrument_function(const irep_idt &function_id, const dfcc_loop_contract_modet loop_contract_mode, std::set< irep_idt > &function_pointer_contracts)
Instruments a GOTO function by adding an extra write set parameter and instrumenting its body instruc...
void add_instrumented_functions_map_init_instructions(const std::set< irep_idt > &instrumented_functions, const source_locationt &source_location, goto_programt &dest)
Generates instructions to initialize the instrumented function map symbol from the given set of instr...
void inhibit_front_end_builtins()
Adds an ASSERT(false) body to all front-end functions __CPROVER_object_whole __CPROVER_object_upto __...
void disable_checks()
Adds "checked" pragmas to instructions of all library functions instructions.
void specialize(const std::size_t contract_assigns_size_hint)
Specializes the library by unwinding loops in library functions to the given assigns clause size.
void load(std::set< irep_idt > &to_instrument)
After calling this function, all library types and functions are present in the the goto_model.
std::set< irep_idt > lift_predicates(std::set< irep_idt > &discovered_function_pointer_contracts)
Collects and lifts all user-defined memory predicates.
void swap_and_wrap_check(const dfcc_loop_contract_modet loop_contract_mode, const irep_idt &function_id, const irep_idt &contract_id, std::set< irep_idt > &function_pointer_contracts, bool allow_recursive_calls)
void swap_and_wrap_replace(const irep_idt &function_id, const irep_idt &contract_id, std::set< irep_idt > &function_pointer_contracts)
void get_swapped_functions(std::set< irep_idt > &dest) const
Adds the set of swapped functions to dest.
Entry point into the contracts transformation.
Definition: dfcc.h:153
goto_modelt & goto_model
Definition: dfcc.h:205
std::set< irep_idt > function_pointer_contracts
Definition: dfcc.h:233
const optionst & options
Definition: dfcc.h:204
std::set< irep_idt > pure_contract_symbols
Definition: dfcc.h:231
void instrument_harness_function()
Definition: dfcc.cpp:334
void instrument_other_functions()
Definition: dfcc.cpp:475
dfcct(const optionst &options, goto_modelt &goto_model, const irep_idt &harness_id, const std::optional< std::pair< irep_idt, irep_idt >> &to_check, const bool allow_recursive_calls, const std::map< irep_idt, irep_idt > &to_replace, const dfcc_loop_contract_modet loop_contract_mode, message_handlert &message_handler, const std::set< std::string > &to_exclude_from_nondet_static)
Class constructor.
Definition: dfcc.cpp:170
void reinitialize_model()
Re-initialise the GOTO model.
Definition: dfcc.cpp:550
const std::set< std::string > & to_exclude_from_nondet_static
Definition: dfcc.h:211
void link_model_and_load_dfcc_library()
Definition: dfcc.cpp:312
dfcc_swap_and_wrapt swap_and_wrap
Definition: dfcc.h:224
dfcc_lift_memory_predicatest memory_predicates
Definition: dfcc.h:222
void wrap_checked_function()
Definition: dfcc.cpp:359
void lift_memory_predicates()
Definition: dfcc.cpp:347
messaget log
Definition: dfcc.h:213
const dfcc_loop_contract_modet loop_contract_mode
Definition: dfcc.h:210
const std::optional< std::pair< irep_idt, irep_idt > > & to_check
Definition: dfcc.h:207
void check_transform_goto_model_preconditions()
Checks preconditions on arguments of transform_goto_model.
Definition: dfcc.cpp:221
std::size_t max_assigns_clause_size
Tracks the maximum number of targets in any assigns clause handled in the transformation (used to spe...
Definition: dfcc.h:228
void transform_goto_model()
Applies function contracts and loop contracts transformation to GOTO model using the dynamic frame co...
Definition: dfcc.cpp:495
dfcc_instrumentt instrument
Definition: dfcc.h:221
dfcc_libraryt library
Definition: dfcc.h:217
void wrap_replaced_functions()
Definition: dfcc.cpp:388
message_handlert & message_handler
Definition: dfcc.h:212
const irep_idt & harness_id
Definition: dfcc.h:206
const bool allow_recursive_calls
Definition: dfcc.h:208
std::set< irep_idt > other_symbols
Definition: dfcc.h:232
dfcc_contract_handlert contract_handler
Definition: dfcc.h:223
const std::map< irep_idt, irep_idt > & to_replace
Definition: dfcc.h:209
void partition_function_symbols(std::set< irep_idt > &pure_contract_symbols, std::set< irep_idt > &other_symbols)
Partitions the function symbols of the symbol table into pure contracts and other function symbols sy...
Definition: dfcc.cpp:285
void wrap_discovered_function_pointer_contracts()
Definition: dfcc.cpp:405
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
Definition: dstring.h:38
function_mapt function_map
static irep_idt entry_point()
Get the identifier of the entry point to a goto model.
bool can_produce_function(const irep_idt &id) const override
Determines if this model can produce a body for the given function.
Definition: goto_model.h:95
symbol_tablet symbol_table
Symbol table.
Definition: goto_model.h:31
goto_functionst goto_functions
GOTO functions.
Definition: goto_model.h:34
A generic container class for the GOTO intermediate representation of one function.
Definition: goto_program.h:73
Exception thrown for bad function/contract specification pairs passed on the CLI.
Definition: dfcc.h:74
invalid_function_contract_pair_exceptiont(std::string reason, std::string correct_format="")
Definition: dfcc.cpp:50
std::string what() const override
A human readable description of what went wrong.
Definition: dfcc.cpp:58
const irep_idt & id() const
Definition: irep.h:384
mstreamt & status() const
Definition: message.h:414
mstreamt & debug() const
Definition: message.h:429
message_handlert & get_message_handler()
Definition: message.h:184
static eomt eom
Definition: message.h:297
const symbolst & symbols
Read-only field, used to look up symbols given their names.
virtual void erase(const symbolst::const_iterator &entry) override
Remove a symbol from the symbol table.
Symbol table entry.
Definition: symbol.h:28
bool is_property
Definition: symbol.h:67
typet type
Type of symbol.
Definition: symbol.h:31
irep_idt name
The unique identifier.
Definition: symbol.h:40
bool has_prefix(const std::string &s, const std::string &prefix)
Definition: converter.cpp:13
static std::pair< irep_idt, irep_idt > parse_function_contract_pair(const irep_idt &cli_flag)
Definition: dfcc.cpp:76
Main class orchestrating the the whole program transformation for function contracts with Dynamic Fra...
Collects all user-defined predicates that call functions is_fresh, pointer_in_range,...
dfcc_loop_contract_modet dfcc_loop_contract_mode_from_bools(bool apply_loop_contracts, bool unwind_transformed_loops)
Generates an enum value from boolean flags for application and unwinding.
dfcc_loop_contract_modet
Enumeration representing the instrumentation mode for loop contracts.
Deprecated expression utility functions.
Fresh auxiliary symbol creation.
Goto Programs with Functions.
Goto Programs with Functions.
Function Inlining This gives a number of different interfaces to the function inlining functionality ...
Symbol Table + CFG.
void dfcc(const optionst &options, goto_modelt &goto_model, const irep_idt &harness_id, const std::optional< irep_idt > &to_check, const bool allow_recursive_calls, const std::set< irep_idt > &to_replace, const bool apply_loop_contracts, const bool unwind_transformed_loops, const std::set< std::string > &to_exclude_from_nondet_static, message_handlert &message_handler)
Applies function contracts transformation to GOTO model, using the dynamic frame condition checking a...
Definition: dfcc.cpp:115
Initialize a Goto Program.
const std::string & id2string(const irep_idt &d)
Definition: irep.h:40
Abstract interface to support a programming language.
double log(double x)
Definition: math.c:2776
API to expression classes for 'mathematical' expressions.
Mathematical types.
static void nondet_static(const namespacet &ns, goto_modelt &goto_model, const irep_idt &fct_name)
Nondeterministically initializes global scope variables in a goto-function.
Nondeterministically initializes global scope variables, except for constants (such as string literal...
API to expression classes for Pointers.
Pointer Logic.
Various predicates over pointers in programs.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
Definition: remove_skip.cpp:87
Program Transformation.
void remove_unused_functions(goto_modelt &goto_model, message_handlert &message_handler)
Unused function removal.
#define PRECONDITION_WITH_DIAGNOSTICS(CONDITION,...)
Definition: invariant.h:464
void recreate_initialize_function(goto_modelt &goto_model, message_handlert &message_handler)
Regenerates the CPROVER_INITIALIZE function, which initializes all non-function symbols of the goto m...
#define INITIALIZE_FUNCTION
API to expression classes.
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
irep_idt arch
Definition: config.h:221
static symbolt & get_function_symbol(symbol_table_baset &, const irep_idt &function_id)
Returns the symbolt for function_id.
Definition: dfcc_utils.cpp:72
static bool function_symbol_with_body_exists(const goto_modelt &, const irep_idt &function_id)
Definition: dfcc_utils.cpp:65
static bool function_symbol_exists(const goto_modelt &, const irep_idt &function_id)
Returns true iff the given symbol exists and satisfies requirements.
Definition: dfcc_utils.cpp:58