8
8
9
9
// / \file
10
10
// / Remove Virtual Function (Method) Calls
11
+ #include < algorithm>
11
12
12
13
#include " remove_virtual_functions.h"
13
14
#include " class_hierarchy.h"
@@ -47,15 +48,20 @@ class remove_virtual_functionst
47
48
goto_programt::targett target);
48
49
49
50
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;
50
56
void get_child_functions_rec (
51
57
const irep_idt &,
52
58
const symbol_exprt &,
53
59
const irep_idt &,
54
60
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 ;
59
65
};
60
66
61
67
remove_virtual_functionst::remove_virtual_functionst (
@@ -192,6 +198,10 @@ void remove_virtual_functionst::remove_virtual_function(
192
198
{
193
199
// No definition for this type; shouldn't be possible...
194
200
t1->make_assertion (false_exprt ());
201
+ t1->source_location .set_comment (
202
+ (" cannot find calls for " +
203
+ id2string (code.function ().get (ID_identifier)) + " dispatching " +
204
+ id2string (fun.class_id )));
195
205
}
196
206
insertit.first ->second =t1;
197
207
// goto final
@@ -247,6 +257,7 @@ void remove_virtual_functionst::remove_virtual_function(
247
257
// / `last_method_defn`: the most-derived parent of `this_id` to define the
248
258
// / requested function
249
259
// / `component_name`: name of the function searched for
260
+ // / `resolve_function_call`: function to resolve abstract method call
250
261
// / \return `functions` is assigned a list of {class name, function symbol}
251
262
// / pairs indicating that if `this` is of the given class, then the call will
252
263
// / target the given function. Thus if A <: B <: C and A and C provide
@@ -257,7 +268,8 @@ void remove_virtual_functionst::get_child_functions_rec(
257
268
const symbol_exprt &last_method_defn,
258
269
const irep_idt &component_name,
259
270
dispatch_table_entriest &functions,
260
- std::set<irep_idt> &visited) const
271
+ std::set<irep_idt> &visited,
272
+ const function_call_resolvert &resolve_function_call) const
261
273
{
262
274
auto findit=class_hierarchy.class_map .find (this_id);
263
275
if (findit==class_hierarchy.class_map .end ())
@@ -278,14 +290,30 @@ void remove_virtual_functionst::get_child_functions_rec(
278
290
{
279
291
function.symbol_expr =last_method_defn;
280
292
}
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
+ }
281
308
functions.push_back (function);
282
309
283
310
get_child_functions_rec (
284
311
child,
285
312
function.symbol_expr ,
286
313
component_name,
287
314
functions,
288
- visited);
315
+ visited,
316
+ resolve_function_call);
289
317
}
290
318
}
291
319
@@ -294,21 +322,30 @@ void remove_virtual_functionst::get_functions(
294
322
dispatch_table_entriest &functions)
295
323
{
296
324
const irep_idt class_id=function.get (ID_C_class);
325
+ const std::string class_id_string (id2string (class_id));
297
326
const irep_idt component_name=function.get (ID_component_name);
327
+ const std::string component_name_string (id2string (component_name));
298
328
INVARIANT (!class_id.empty (), " All virtual functions must have a class" );
299
329
300
330
resolve_concrete_function_callt get_virtual_call_target (
301
331
symbol_table, class_hierarchy);
302
- const resolve_concrete_function_callt::concrete_function_callt &
303
- 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
+
304
341
dispatch_table_entryt root_function;
305
342
306
343
if (resolved_call.is_valid ())
307
344
{
308
345
root_function.class_id =resolved_call.get_class_identifier ();
309
346
310
- const symbolt &called_symbol=
311
- * 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 ());
312
349
313
350
root_function.symbol_expr =called_symbol.symbol_expr ();
314
351
root_function.symbol_expr .set (
@@ -327,7 +364,8 @@ void remove_virtual_functionst::get_functions(
327
364
root_function.symbol_expr ,
328
365
component_name,
329
366
functions,
330
- visited);
367
+ visited,
368
+ resolve_function_call);
331
369
332
370
if (root_function.symbol_expr !=symbol_exprt ())
333
371
functions.push_back (root_function);
0 commit comments