Skip to content

Commit 2b6dc8b

Browse files
author
Matthias Güdemann
committed
Resolve concrete function call if no implementation is found
1 parent 04f2faf commit 2b6dc8b

File tree

1 file changed

+47
-12
lines changed

1 file changed

+47
-12
lines changed

src/goto-programs/remove_virtual_functions.cpp

Lines changed: 47 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ Author: Daniel Kroening, [email protected]
88

99
/// \file
1010
/// Remove Virtual Function (Method) Calls
11+
#include <algorithm>
1112

1213
#include "remove_virtual_functions.h"
1314
#include "class_hierarchy.h"
@@ -47,15 +48,20 @@ class remove_virtual_functionst
4748
goto_programt::targett target);
4849

4950
void get_functions(const exprt &, dispatch_table_entriest &);
51+
typedef std::function<
52+
resolve_concrete_function_callt::concrete_function_callt(
53+
const irep_idt &,
54+
const irep_idt &)>
55+
function_call_resolvert;
5056
void get_child_functions_rec(
5157
const irep_idt &,
5258
const symbol_exprt &,
5359
const irep_idt &,
5460
dispatch_table_entriest &,
55-
std::set<irep_idt> &visited) const;
56-
exprt get_method(
57-
const irep_idt &class_id,
58-
const irep_idt &component_name) const;
61+
std::set<irep_idt> &visited,
62+
const function_call_resolvert &) const;
63+
exprt
64+
get_method(const irep_idt &class_id, const irep_idt &component_name) const;
5965
};
6066

6167
remove_virtual_functionst::remove_virtual_functionst(
@@ -194,7 +200,8 @@ void remove_virtual_functionst::remove_virtual_function(
194200
t1->make_assertion(false_exprt());
195201
t1->source_location.set_comment(
196202
("cannot find calls for " +
197-
id2string(code.function().get(ID_identifier))));
203+
id2string(code.function().get(ID_identifier)) + " dispatching " +
204+
id2string(fun.class_id)));
198205
}
199206
insertit.first->second=t1;
200207
// goto final
@@ -250,6 +257,7 @@ void remove_virtual_functionst::remove_virtual_function(
250257
/// `last_method_defn`: the most-derived parent of `this_id` to define the
251258
/// requested function
252259
/// `component_name`: name of the function searched for
260+
/// `resolve_function_call`: function to resolve abstract method call
253261
/// \return `functions` is assigned a list of {class name, function symbol}
254262
/// pairs indicating that if `this` is of the given class, then the call will
255263
/// target the given function. Thus if A <: B <: C and A and C provide
@@ -260,7 +268,8 @@ void remove_virtual_functionst::get_child_functions_rec(
260268
const symbol_exprt &last_method_defn,
261269
const irep_idt &component_name,
262270
dispatch_table_entriest &functions,
263-
std::set<irep_idt> &visited) const
271+
std::set<irep_idt> &visited,
272+
const function_call_resolvert &resolve_function_call) const
264273
{
265274
auto findit=class_hierarchy.class_map.find(this_id);
266275
if(findit==class_hierarchy.class_map.end())
@@ -281,14 +290,30 @@ void remove_virtual_functionst::get_child_functions_rec(
281290
{
282291
function.symbol_expr=last_method_defn;
283292
}
293+
if(function.symbol_expr == symbol_exprt())
294+
{
295+
const resolve_concrete_function_callt::concrete_function_callt
296+
&resolved_call = resolve_function_call(child, component_name);
297+
if(resolved_call.is_valid())
298+
{
299+
function.class_id = resolved_call.get_class_identifier();
300+
const symbolt &called_symbol =
301+
symbol_table.lookup_ref(resolved_call.get_virtual_method_name());
302+
303+
function.symbol_expr = called_symbol.symbol_expr();
304+
function.symbol_expr.set(
305+
ID_C_class, resolved_call.get_class_identifier());
306+
}
307+
}
284308
functions.push_back(function);
285309

286310
get_child_functions_rec(
287311
child,
288312
function.symbol_expr,
289313
component_name,
290314
functions,
291-
visited);
315+
visited,
316+
resolve_function_call);
292317
}
293318
}
294319

@@ -297,21 +322,30 @@ void remove_virtual_functionst::get_functions(
297322
dispatch_table_entriest &functions)
298323
{
299324
const irep_idt class_id=function.get(ID_C_class);
325+
const std::string class_id_string(id2string(class_id));
300326
const irep_idt component_name=function.get(ID_component_name);
327+
const std::string component_name_string(id2string(component_name));
301328
INVARIANT(!class_id.empty(), "All virtual functions must have a class");
302329

303330
resolve_concrete_function_callt get_virtual_call_target(
304331
symbol_table, class_hierarchy);
305-
const resolve_concrete_function_callt::concrete_function_callt &
306-
resolved_call=get_virtual_call_target(class_id, component_name);
332+
const function_call_resolvert resolve_function_call =
333+
[&get_virtual_call_target](
334+
const irep_idt &class_id, const irep_idt &component_name) {
335+
return get_virtual_call_target(class_id, component_name);
336+
};
337+
338+
const resolve_concrete_function_callt::concrete_function_callt
339+
&resolved_call = get_virtual_call_target(class_id, component_name);
340+
307341
dispatch_table_entryt root_function;
308342

309343
if(resolved_call.is_valid())
310344
{
311345
root_function.class_id=resolved_call.get_class_identifier();
312346

313-
const symbolt &called_symbol=
314-
*symbol_table.lookup(resolved_call.get_virtual_method_name());
347+
const symbolt &called_symbol =
348+
symbol_table.lookup_ref(resolved_call.get_virtual_method_name());
315349

316350
root_function.symbol_expr=called_symbol.symbol_expr();
317351
root_function.symbol_expr.set(
@@ -330,7 +364,8 @@ void remove_virtual_functionst::get_functions(
330364
root_function.symbol_expr,
331365
component_name,
332366
functions,
333-
visited);
367+
visited,
368+
resolve_function_call);
334369

335370
if(root_function.symbol_expr!=symbol_exprt())
336371
functions.push_back(root_function);

0 commit comments

Comments
 (0)