Go to the documentation of this file.
48 typedef std::function<
107 const auto &callee_parameters =
112 callee_parameters.size() == call_args.size(),
113 "function overrides must have matching argument counts");
115 for(std::size_t i = 0; i < call_args.size(); ++i)
117 const typet &need_type = callee_parameters[i].type();
119 if(call_args[i].type() != need_type)
125 call_args[i].type().
id() == ID_pointer,
126 "where overriding function argument types differ, "
127 "those arguments must be pointer-typed");
148 const exprt &argument_for_this,
155 instr_it = std::prev(instr_it);
157 if(instr_it->is_assert())
162 if(!instr_it->is_assume())
167 exprt guard = instr_it->condition();
169 bool changed =
false;
173 if(*expr_it == argument_for_this)
175 expr_it.mutate() = temp_var_for_this;
183 checks_directly_preceding_function_call.
instructions.cbegin(),
188 return checks_directly_preceding_function_call;
206 exprt &argument_for_this,
217 argument_for_this.
type(),
225 new_code_for_this_argument.
add(
227 new_code_for_this_argument.
add(
229 temp_var_for_this, argument_for_this, vcall_source_loc));
233 goto_program, target, argument_for_this, temp_var_for_this);
236 checks_directly_preceding_function_call);
238 argument_for_this = temp_var_for_this;
269 target->is_function_call(),
270 "remove_virtual_function must target a FUNCTION_CALL instruction");
275 if(functions.empty())
277 target->turn_into_skip();
283 if(functions.size()==1 &&
286 if(!functions.front().symbol_expr.has_value())
288 target->turn_into_skip();
294 target->call_lhs(), target->call_function(), target->call_arguments());
296 target->call_function() = c.function();
297 target->call_arguments() = c.arguments();
302 const auto &vcall_source_loc = target->source_location();
305 target->call_lhs(), target->call_function(), target->call_arguments());
315 new_code_for_this_argument);
331 this_expr.
type().
id() == ID_pointer,
"this parameter must be a pointer");
334 "this parameter must not be a void pointer");
338 exprt this_class_identifier =
350 INVARIANT(!functions.empty(),
"Function dispatch table cannot be empty.");
351 const auto &last_function_symbol = functions.back().symbol_expr;
353 std::map<irep_idt, goto_programt::targett> calls;
355 for(
auto it=functions.crbegin(), itend=functions.crend(); it!=itend; ++it)
358 irep_idt id_or_empty = fun.symbol_expr.has_value()
359 ? fun.symbol_expr->get_identifier()
366 if(fun.symbol_expr.has_value())
369 auto new_call = code;
376 insertit.first->second = t1;
384 t1->source_location_nonconst().set_comment(
385 "cannot find calls for " +
389 insertit.first->second = t1;
401 fun.symbol_expr.has_value() == last_function_symbol.has_value() &&
402 (!fun.symbol_expr.has_value() ||
403 *fun.symbol_expr == *last_function_symbol))
411 fun_class_identifier, this_class_identifier);
416 it != functions.crbegin() &&
417 std::prev(it)->symbol_expr.has_value() == fun.symbol_expr.has_value() &&
418 (!fun.symbol_expr.has_value() ||
419 *(std::prev(it)->symbol_expr) == *fun.symbol_expr))
422 !new_code_gotos.
empty(),
423 "a dispatch table entry has been processed already, "
424 "which should have created a GOTO");
426 new_code_gotos.
instructions.back().condition(), class_id_test);
431 insertit.first->second, class_id_test, vcall_source_loc));
451 source_location = target->source_location();
452 if(!property_class.
empty())
461 target->turn_into_skip();
486 "remove_virtual_function must take a function call instruction whose "
487 "function is a class method descriptor ");
489 !
as_const(*target).call_arguments().empty(),
490 "virtual function calls must have at least a this-argument");
529 for(
const auto &child : findit->second.children)
533 auto it = entry_map.find(child);
535 it != entry_map.end() &&
536 (!it->second.symbol_expr.has_value() ||
538 id2string(it->second.symbol_expr->get_identifier()),
539 "java::java.lang.Object")))
548 function.symbol_expr->set(ID_C_class, child);
552 function.symbol_expr=last_method_defn;
554 if(!
function.symbol_expr.has_value())
560 function.class_id = resolved_call->get_class_identifier();
562 resolved_call->get_full_component_identifier());
565 function.symbol_expr->
set(
566 ID_C_class, resolved_call->get_class_identifier());
569 functions.push_back(
function);
570 entry_map.emplace(child,
function);
573 child,
function.symbol_expr, component_name, functions, entry_map);
582 const exprt &
function,
586 const irep_idt class_id=
function.get(ID_C_class);
587 const std::string class_id_string(
id2string(class_id));
588 const irep_idt function_name =
function.get(ID_component_name);
589 const std::string function_name_string(
id2string(function_name));
590 INVARIANT(!class_id.
empty(),
"All virtual functions must have a class");
600 root_function.
class_id = resolved_call->get_class_identifier();
607 ID_C_class, resolved_call->get_class_identifier());
613 class_id, root_function.
symbol_expr, function_name, functions, entry_map);
616 functions.push_back(root_function);
626 irep_idt a_id = a.symbol_expr.has_value()
627 ? a.symbol_expr->get_identifier()
629 irep_idt b_id = b.symbol_expr.has_value()
630 ? b.symbol_expr->get_identifier()
633 if(has_prefix(id2string(a_id),
"java::java.lang.Object"))
635 else if(has_prefix(id2string(b_id),
"java::java.lang.Object"))
639 int cmp = a_id.compare(b_id);
641 return a.class_id < b.class_id;
655 const irep_idt &component_name)
const
659 class_id, component_name);
675 bool did_something=
false;
677 for(goto_programt::instructionst::iterator
682 if(target->is_function_call())
699 return did_something;
706 bool did_something=
false;
708 for(goto_functionst::function_mapt::iterator f_it=
713 const irep_idt &function_id = f_it->first;
733 class_hierarchy(symbol_table);
782 class_hierarchy(
function.get_symbol_table());
785 function.get_function_id(),
function.get_goto_function().body);
801 function.get_function_id(),
function.get_goto_function().body);
861 const exprt &
function,
867 get_callees.get_functions(
function, overridden_functions);
dstringt has one field, an unsigned integer no which is an index into a static table of strings.
@ CALL_LAST_FUNCTION
When no callee type matches, call the last passed function, which is expected to be some safe default...
const irep_idt & get_comment() const
virtual_dispatch_fallback_actiont
Specifies remove_virtual_function's behaviour when the actual supplied parameter does not match any o...
const irep_idt & get_property_class() const
const symbolt & lookup_ref(const irep_idt &name) const
Find a symbol in the symbol table for read-only access.
bool has_subexpr(const exprt &expr, const std::function< bool(const exprt &)> &pred)
returns true if the expression has a subexpression that satisfies pred
Non-graph-based representation of the class hierarchy.
void set_comment(const irep_idt &comment)
depth_iteratort depth_end()
std::set< irep_idt > get_callees(const call_grapht::directed_grapht &graph, const irep_idt &function)
Get functions directly callable from a given function.
optionalt< resolve_inherited_componentt::inherited_componentt > get_inherited_method_implementation(const irep_idt &call_basename, const irep_idt &classname, const symbol_tablet &symbol_table)
Given a class and a component, identify the concrete method it is resolved to.
@ ASSUME_FALSE
When no callee type matches, ASSUME false, thus preventing any complete trace from using this path.
void get_child_functions_rec(const irep_idt &, const optionalt< symbol_exprt > &, const irep_idt &, dispatch_table_entriest &, dispatch_table_entries_mapt &) const
Used by get_functions to track the most-derived parent that provides an override of a given function.
The type of an expression, extends irept.
void remove_skip(goto_programt &goto_program, goto_programt::targett begin, goto_programt::targett end)
remove unnecessary skip statements
static void create_static_function_call(code_function_callt &call, const symbol_exprt &function_symbol, const namespacet &ns)
Create a concrete function call to replace a virtual one.
exprt get_class_identifier_field(const exprt &this_expr_in, const struct_tag_typet &suggested_type, const namespacet &ns)
void update()
Update all indices.
targett add(instructiont &&instruction)
Adds a given instruction at the end.
void remove_virtual_functions(symbol_table_baset &symbol_table, goto_functionst &goto_functions)
Remove virtual function calls from all functions in the specified list and replace them with their mo...
void compute_location_numbers()
bool empty() const
Is the program empty?
Base class for all expressions.
A struct tag type, i.e., struct_typet with an identifier.
std::vector< dispatch_table_entryt > dispatch_table_entriest
remove_virtual_functionst(symbol_table_baset &_symbol_table, const class_hierarchyt &_class_hierarchy)
std::function< optionalt< resolve_inherited_componentt::inherited_componentt > const irep_idt &, const irep_idt &)> function_call_resolvert
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())
static goto_programt::targett replace_virtual_function_with_dispatch_table(symbol_table_baset &symbol_table, const irep_idt &function_id, goto_programt &goto_program, goto_programt::targett target, const dispatch_table_entriest &functions, virtual_dispatch_fallback_actiont fallback_action)
Replace virtual function call with a static function call Achieved by substituting a virtual function...
static instructiont make_assignment(const code_assignt &_code, const source_locationt &l=source_locationt::nil())
Create an assignment instruction.
static instructiont make_goto(targett _target, const source_locationt &l=source_locationt::nil())
bool remove_virtual_functions(const irep_idt &function_id, goto_programt &goto_program)
Remove all virtual function calls in a GOTO program and replace them with calls to their most derived...
const irep_idt & get(const irep_idt &name) const
void get_functions(const exprt &, dispatch_table_entriest &) const
Used to get dispatch entries to call for the given function.
A namespacet is essentially one or two symbol tables bound together, to allow for symbol lookups in t...
static instructiont make_function_call(const code_function_callt &_code, const source_locationt &l=source_locationt::nil())
Create a function call instruction.
goto_programt::targett remove_virtual_function(const irep_idt &function_id, goto_programt &goto_program, goto_programt::targett target)
Replace specified virtual function call with a static call to its most derived implementation.
typet & type()
Return the type of the expression.
bool lookup(const irep_idt &name, const symbolt *&symbol) const override
See documentation for namespace_baset::lookup().
goto_instruction_codet representation of a function call statement.
targett insert_before(const_targett target)
Insertion before the instruction pointed-to by the given instruction iterator target.
const code_typet & to_code_type(const typet &type)
Cast a typet to a code_typet.
const class_hierarchyt & class_hierarchy
static instructiont make_assertion(const exprt &g, const source_locationt &l=source_locationt::nil())
irep_idt mode
Language mode.
const T & as_const(T &value)
Return a reference to the same object but ensures the type is const.
bool has_prefix(const std::string &s, const std::string &prefix)
void destructive_insert(const_targett target, goto_programt &p)
Inserts the given program p before target.
const std::string & id2string(const irep_idt &d)
get_virtual_calleest(const symbol_table_baset &_symbol_table, const class_hierarchyt &_class_hierarchy)
static instructiont make_skip(const source_locationt &l=source_locationt::nil())
void set(const irep_idt &name, const irep_idt &value)
const irep_idt & get_identifier() const
The symbol table base class interface.
const symbol_table_baset & symbol_table
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.
optionalt< symbol_exprt > symbol_expr
const symbol_exprt & to_symbol_expr(const exprt &expr)
Cast an exprt to a symbol_exprt.
const irep_idt & id() const
std::map< irep_idt, dispatch_table_entryt > dispatch_table_entries_mapt
The Boolean constant false.
const parameterst & parameters() const
nonstd::optional< T > optionalt
void destructive_append(goto_programt &p)
Appends the given program p to *this. p is destroyed.
goto_programt::targett remove_virtual_function(symbol_tablet &symbol_table, const irep_idt &function_id, goto_programt &goto_program, goto_programt::targett instruction, const dispatch_table_entriest &dispatch_table, virtual_dispatch_fallback_actiont fallback_action)
Replace virtual function call with a static function call Achieved by substituting a virtual function...
instructionst instructions
The list of instructions in the goto program.
Deprecated expression utility functions.
A collection of goto functions.
static void process_this_argument(const irep_idt &function_id, const goto_programt &goto_program, const goto_programt::targett target, exprt &argument_for_this, symbol_table_baset &symbol_table, const source_locationt &vcall_source_loc, goto_programt &new_code_for_this_argument)
If argument_for_this contains a dereference then create a temporary variable for it and use that inst...
goto_functionst goto_functions
GOTO functions.
symbol_table_baset & symbol_table
bool can_cast_expr< class_method_descriptor_exprt >(const exprt &base)
depth_iteratort depth_begin()
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.
static goto_programt analyse_checks_directly_preceding_function_call(const goto_programt &goto_program, goto_programt::const_targett instr_it, const exprt &argument_for_this, const symbol_exprt &temp_var_for_this)
Duplicate ASSUME instructions involving argument_for_this for temp_var_for_this.
instructionst::const_iterator const_targett
static instructiont make_assumption(const exprt &g, const source_locationt &l=source_locationt::nil())
static irep_idt build_full_component_identifier(const irep_idt &class_name, const irep_idt &component_name)
Build a component name as found in a GOTO symbol table equivalent to the name of a concrete component...
#define INVARIANT(CONDITION, REASON)
This macro uses the wrapper function 'invariant_violated_string'.
Semantic type conversion.
The Boolean constant true.
A constant literal expression.
void collect_virtual_function_callees(const exprt &function, const symbol_table_baset &symbol_table, const class_hierarchyt &class_hierarchy, dispatch_table_entriest &overridden_functions)
Given a function expression representing a virtual method of a class, the function computes all overr...
static std::string comment(const rw_set_baset::entryt &entry, bool write)
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 ...
exprt get_method(const irep_idt &class_id, const irep_idt &component_name) const
Returns symbol pointing to a specified method in a specified class.
Interface providing access to a single function in a GOTO model, plus its associated symbol table.
const class_hierarchyt & class_hierarchy
instructionst::iterator targett
void set_property_class(const irep_idt &property_class)
void operator()(goto_functionst &functions)
Remove virtual function calls from all functions in the specified list and replace them with their mo...