Go to the documentation of this file.
44 int param_counter = 0;
45 for(
auto ¶meter : parameters)
47 if(parameter.get_identifier().empty())
49 const std::string param_base_name =
50 parameter.get_base_name().empty()
54 id2string(function_name) +
"::" + param_base_name;
55 parameter.set_base_name(param_base_name);
56 parameter.set_identifier(new_param_identifier);
58 new_param_sym.
name = new_param_identifier;
59 new_param_sym.
type = parameter.type();
60 new_param_sym.
base_name = param_base_name;
61 new_param_sym.
mode = function_symbol.mode;
62 new_param_sym.
module = function_symbol.module;
63 new_param_sym.
location = function_symbol.location;
64 symbol_table.
add(new_param_sym);
67 function.set_parameter_identifiers(
to_code_type(function_symbol.type));
76 const irep_idt &function_name)
const override
78 auto const &function_symbol = symbol_table.
lookup_ref(function_name);
81 auto instruction =
function.body.add(std::move(i));
82 instruction->source_location_nonconst() = function_symbol.
location;
96 const irep_idt &function_name)
const override
98 auto const &function_symbol = symbol_table.
lookup_ref(function_name);
101 auto instruction =
function.body.add(std::move(i));
102 instruction->source_location_nonconst() = function_symbol.
location;
103 instruction->source_location_nonconst().
set_function(function_name);
106 auto assert_instruction =
108 assert_instruction->source_location_nonconst().set_comment(
109 "undefined function should be unreachable");
110 assert_instruction->source_location_nonconst().set_property_class(
123 const irep_idt &function_name)
const override
125 auto const &function_symbol = symbol_table.
lookup_ref(function_name);
128 auto instruction =
function.body.add(std::move(i));
129 instruction->source_location_nonconst() = function_symbol.
location;
130 instruction->source_location_nonconst().
set_function(function_name);
133 auto assert_instruction =
135 assert_instruction->source_location_nonconst().set_comment(
136 "undefined function should be unreachable");
137 assert_instruction->source_location_nonconst().set_property_class(
176 const std::size_t initial_depth,
201 init_code.
append(assignments);
211 const std::string ¶m_name,
212 std::size_t param_number)
const
221 return std::binary_search(
232 const irep_idt &function_name)
const override
238 auto max_param_number = std::max_element(
240 if(*max_param_number >=
function.parameter_identifiers.size())
243 "function " +
id2string(function_name) +
" does not take " +
245 "--generate-havocing-body"};
249 const auto ¶meter =
function.parameter_identifiers[number];
251 if(parameter_symbol.
type.
id() != ID_pointer)
255 id2string(function_name) +
" is not a pointer",
256 "--generate-havocing-body"};
261 auto const &function_symbol = symbol_table.
lookup_ref(function_name);
264 auto instruction =
function.body.add(std::move(i));
265 instruction->source_location_nonconst() = function_symbol.
location;
269 for(std::size_t i = 0; i <
function.parameter_identifiers.size(); ++i)
271 const auto ¶meter =
function.parameter_identifiers[i];
274 parameter_symbol.
type.
id() == ID_pointer &&
280 auto goto_instruction =
293 function_symbol.location,
298 function.body.destructive_append(dest);
301 goto_instruction->complete_goto(label_instruction);
307 auto const &global_sym = symbol_table.
lookup_ref(global_id);
314 function_symbol.location,
319 function.body.destructive_append(dest);
325 typet type(return_type);
326 type.
remove(ID_C_constant);
332 function_symbol.location,
345 function_symbol.location,
350 function.body.destructive_append(dest);
378 : runtime_error(reason)
386 const std::string &options,
391 if(options.empty() || options ==
"nondet-return")
393 return util_make_unique<havoc_generate_function_bodiest>(
394 std::vector<irep_idt>{},
396 object_factory_parameters,
400 if(options ==
"assume-false")
402 return util_make_unique<assume_false_generate_function_bodiest>();
405 if(options ==
"assert-false")
407 return util_make_unique<assert_false_generate_function_bodiest>();
410 if(options ==
"assert-false-assume-false")
416 const std::vector<std::string> option_components =
split_string(options,
',');
417 if(!option_components.empty() && option_components[0] ==
"havoc")
419 std::regex globals_regex;
420 std::regex params_regex;
421 std::vector<std::size_t> param_numbers;
422 for(std::size_t i = 1; i < option_components.size(); ++i)
424 const std::vector<std::string> key_value_pair =
426 if(key_value_pair.size() != 2)
429 "Expected key_value_pair of form argument:value");
431 if(key_value_pair[0] ==
"globals")
433 globals_regex = key_value_pair[1];
435 else if(key_value_pair[0] ==
"params")
437 auto param_identifiers =
split_string(key_value_pair[1],
';');
438 if(param_identifiers.size() == 1)
440 auto maybe_nondet_param_number =
442 if(!maybe_nondet_param_number.has_value())
444 params_regex = key_value_pair[1];
449 param_identifiers.begin(),
450 param_identifiers.end(),
451 std::back_inserter(param_numbers),
452 [](
const std::string ¶m_id) {
453 auto maybe_nondet_param_number = string2optional_size_t(param_id);
455 maybe_nondet_param_number.has_value(),
456 param_id +
" not a number");
457 return *maybe_nondet_param_number;
459 std::sort(param_numbers.begin(), param_numbers.end());
464 "Unknown option \"" + key_value_pair[0] +
"\"");
467 std::vector<irep_idt> globals_to_havoc;
470 const std::regex cprover_prefix = std::regex(
"__CPROVER.*");
471 for(
auto const &symbol : symbol_table.
symbols)
474 symbol.second.is_lvalue && symbol.second.is_static_lifetime &&
475 std::regex_match(
id2string(symbol.first), globals_regex))
477 if(std::regex_match(
id2string(symbol.first), cprover_prefix))
479 messages.
warning() <<
"generate function bodies: "
480 <<
"matched global '" <<
id2string(symbol.first)
481 <<
"' begins with __CPROVER, "
482 <<
"havoc-ing this global may interfere"
485 globals_to_havoc.push_back(symbol.first);
488 if(param_numbers.empty())
489 return util_make_unique<havoc_generate_function_bodiest>(
490 std::move(globals_to_havoc),
491 std::move(params_regex),
492 object_factory_parameters,
495 return util_make_unique<havoc_generate_function_bodiest>(
496 std::move(globals_to_havoc),
497 std::move(param_numbers),
498 object_factory_parameters,
512 const std::regex &functions_regex,
518 const std::regex cprover_prefix = std::regex(
"__CPROVER.*");
519 bool did_generate_body =
false;
523 !
function.second.body_available() &&
524 std::regex_match(
id2string(
function.first), functions_regex))
526 if(std::regex_match(
id2string(
function.first), cprover_prefix))
528 messages.
warning() <<
"generate function bodies: matched function '"
530 <<
"' begins with __CPROVER "
531 <<
"the generated body for this function "
534 did_generate_body =
true;
539 if(!did_generate_body)
542 <<
"generate function bodies: No function name matched regex"
548 const std::string &function_name,
549 const std::string &call_site_id,
567 auto const symbol = symbol_pair.second;
568 if(symbol.type.id() == ID_code && symbol.name == function_name)
570 function_mode = symbol.mode;
571 function_type = symbol.type;
579 symbolt havoc_function_symbol{};
580 havoc_function_symbol.
name = havoc_function_symbol.base_name =
581 havoc_function_symbol.pretty_name = function_name +
"." + call_site_id;
583 havoc_function_symbol.is_lvalue =
true;
584 havoc_function_symbol.mode = function_mode;
585 havoc_function_symbol.type = function_type;
589 auto const &generated_havoc =
599 !
function.second.body_available() &&
600 havoc_function_symbol.name ==
id2string(
function.first))
607 auto is_havoc_function_call = [&function_name](
const exprt &expr) {
608 if(expr.id() != ID_symbol)
610 std::string called_function_name =
612 if(called_function_name == function_name)
615 return (
has_prefix(called_function_name, function_name +
"."));
619 std::size_t counter = 0;
622 for(
auto &instruction :
function.second.body.instructions)
624 if(instruction.is_function_call())
626 auto &called_function =
628 if(is_havoc_function_call(called_function))
630 if(++counter == *call_site_number)
632 called_function = generated_havoc.symbol_expr();
Class that provides messages with a built-in verbosity 'level'.
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
A codet representing sequential composition of program statements.
static exprt conditional_cast(const exprt &expr, const typet &type)
void generate_function_body(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const
Replace the function body with one based on the replace_function_body class being used.
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
const code_function_callt & to_code_function_call(const goto_instruction_codet &code)
optionalt< std::vector< std::size_t > > param_numbers_to_havoc
static instructiont make_dead(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
void set_function(const irep_idt &function)
void generate_function_body_impl(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const override
Produce a body for the passed function At this point the body of function is always empty,...
#define CHECK_RETURN(CONDITION)
The type of an expression, extends irept.
static instructiont make_set_return_value(exprt return_value, const source_locationt &l=source_locationt::nil())
static abstract_object_pointert transform(const exprt &expr, const std::vector< abstract_object_pointert > &operands, const abstract_environmentt &environment, const namespacet &ns)
typet type
Type of symbol.
Operator to dereference a pointer.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
virtual void generate_function_body_impl(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const =0
Produce a body for the passed function At this point the body of function is always empty,...
static instructiont make_end_function(const source_locationt &l=source_locationt::nil())
Base class for all expressions.
irep_idt base_name
Base (non-scoped) name.
void generate_function_bodies(const std::regex &functions_regex, const generate_function_bodiest &generate_function_body, goto_modelt &model, message_handlert &message_handler)
Generate function bodies with some default behavior: assert-false, assume-false, assert-false-assume-...
Base class for replace_function_body implementations.
std::string to_string(const string_not_contains_constraintt &expr)
Used for debug printing.
function_mapt function_map
Expression to hold a symbol (variable)
static instructiont make_decl(const symbol_exprt &symbol, const source_locationt &l=source_locationt::nil())
optionalt< std::regex > parameters_to_havoc
generate_function_bodies_errort(const std::string &reason)
void goto_convert(const codet &code, symbol_table_baset &symbol_table, goto_programt &dest, message_handlert &message_handler, const irep_idt &mode)
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
std::unique_ptr< T > util_make_unique(Ts &&... ts)
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
void split_string(const std::string &s, char delim, std::vector< std::string > &result, bool strip, bool remove_empty)
const c_object_factory_parameterst & object_factory_parameters
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
irep_idt mode
Language mode.
void generate_function_body_impl(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const override
Produce a body for the passed function At this point the body of function is always empty,...
void havoc_expr_rec(const exprt &lhs, const std::size_t initial_depth, const source_locationt &source_location, const irep_idt &function_id, symbol_tablet &symbol_table, goto_programt &dest) const
bool has_prefix(const std::string &s, const std::string &prefix)
The null pointer constant.
symbolt & get_writeable_ref(const irep_idt &name)
Find a symbol in the symbol table for read-write access.
const std::string & id2string(const irep_idt &d)
static optionalt< smt_termt > get_identifier(const exprt &expr, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_handle_identifiers, const std::unordered_map< exprt, smt_identifier_termt, irep_hash > &expression_identifiers)
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
havoc_generate_function_bodiest(std::vector< irep_idt > globals_to_havoc, std::vector< std::size_t > param_numbers_to_havoc, const c_object_factory_parameterst &object_factory_parameters, message_handlert &message_handler)
#define PRECONDITION(CONDITION)
void generate_function_body_impl(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const override
Produce a body for the passed function At this point the body of function is always empty,...
void generate_function_body_impl(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const override
Produce a body for the passed function At this point the body of function is always empty,...
class symbol_exprt symbol_expr() const
Produces a symbol_exprt for a symbol.
const pointer_typet & to_pointer_type(const typet &type)
Cast a typet to a pointer_typet.
virtual std::pair< symbolt &, bool > insert(symbolt symbol) override
Author: Diffblue Ltd.
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const irep_idt & id() const
A goto function, consisting of function body (see body) and parameter identifiers (see parameter_iden...
The Boolean constant false.
optionalt< std::size_t > string2optional_size_t(const std::string &str, int base)
Convert string to size_t similar to the stoul or stoull functions, return nullopt when the conversion...
const parameterst & parameters() const
const std::vector< irep_idt > globals_to_havoc
nonstd::optional< T > optionalt
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
bool add(const symbolt &symbol)
Add a new symbol to the symbol table.
message_handlert & get_message_handler()
void gen_nondet_init(code_blockt &assignments, const exprt &expr, const std::size_t depth=0, recursion_sett recursion_set=recursion_sett(), const bool assign_const=true)
Creates a nondet for expr, including calling itself recursively to make appropriate symbols to point ...
goto_functionst goto_functions
GOTO functions.
source_locationt location
Source code location of definition of symbol.
havoc_generate_function_bodiest(std::vector< irep_idt > globals_to_havoc, std::regex parameters_to_havoc, const c_object_factory_parameterst &object_factory_parameters, message_handlert &message_handler)
void append(const code_blockt &extra_block)
Add all the codets from extra_block to the current code_blockt.
const symbolst & symbols
Read-only field, used to look up symbols given their names.
bool should_havoc_param(const std::string ¶m_name, std::size_t param_number) const
const typet & base_type() const
The type of the data what we point to.
A generic container class for the GOTO intermediate representation of one function.
@ DYNAMIC
Allocate dynamic objects (using ALLOCATE)
const typet & return_type() const
std::unique_ptr< generate_function_bodiest > generate_function_bodies_factory(const std::string &options, const c_object_factory_parameterst &object_factory_parameters, const symbol_tablet &symbol_table, message_handlert &message_handler)
Create the type that actually generates the functions.
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
std::set< irep_idt > recursion_sett
Symbol table entry of function parameter.
void generate_parameter_names(goto_functiont &function, symbol_tablet &symbol_table, const irep_idt &function_name) const
Generate parameter names for unnamed parameters.
void remove(const irep_idt &name)
irep_idt module
Name of module the symbol belongs to.
mstreamt & warning() const
Thrown when users pass incorrect command line arguments, for example passing no files to analysis or ...
This class represents an instruction in the GOTO intermediate representation.
symbol_tablet symbol_table
Symbol table.
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 ...
irep_idt name
The unique identifier.
bool get_bool(const irep_idt &name) const
static instructiont make_incomplete_goto(const exprt &_cond, const source_locationt &l=source_locationt::nil())
void declare_created_symbols(code_blockt &init_code)