Skip to content

Commit 6ef344b

Browse files
author
Matthias Güdemann
committed
Gather all resolved calls, filter for concrete ones
This fixes an issue in test-generator where a call to `toString` is dispatched to the `toString` method from `java.lang.Object` is used instead of the overridden method from `ArrayList`. Cite from the issue about the current implementation: > It tracks a `visited` set preventing it from listing callees twice when > multiple inheritance is in play (e.g. Java interfaces). Unfortunately this > malfunctions when we visit a type twice, once via its interfaces and once via > its concrete subclass which provides a definition This fix removes the `visited` set and therefore traverses the whole class hierarchy (in the case of java.lang.Object, else a sub-tree) to find appropriate implementation methods.
1 parent 933d635 commit 6ef344b

File tree

1 file changed

+23
-7
lines changed

1 file changed

+23
-7
lines changed

src/goto-programs/remove_virtual_functions.cpp

+23-7
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ class remove_virtual_functionst
5858
const symbol_exprt &,
5959
const irep_idt &,
6060
dispatch_table_entriest &,
61-
std::set<irep_idt> &visited,
6261
const function_call_resolvert &) const;
6362
exprt
6463
get_method(const irep_idt &class_id, const irep_idt &component_name) const;
@@ -269,7 +268,6 @@ void remove_virtual_functionst::get_child_functions_rec(
269268
const symbol_exprt &last_method_defn,
270269
const irep_idt &component_name,
271270
dispatch_table_entriest &functions,
272-
std::set<irep_idt> &visited,
273271
const function_call_resolvert &resolve_function_call) const
274272
{
275273
auto findit=class_hierarchy.class_map.find(this_id);
@@ -278,8 +276,6 @@ void remove_virtual_functionst::get_child_functions_rec(
278276

279277
for(const auto &child : findit->second.children)
280278
{
281-
if(!visited.insert(child).second)
282-
continue;
283279
exprt method=get_method(child, component_name);
284280
dispatch_table_entryt function(child);
285281
if(method.is_not_nil())
@@ -313,17 +309,22 @@ void remove_virtual_functionst::get_child_functions_rec(
313309
function.symbol_expr,
314310
component_name,
315311
functions,
316-
visited,
317312
resolve_function_call);
318313
}
319314
}
320315

316+
/// Used to get dispatch entries to call for the given function
317+
/// \param function: function that should be called
318+
/// \param[out] `functions` is assigned a list of dispatch entries, i.e., pairs of
319+
/// class names and function symbol to call when encountering the class.
321320
void remove_virtual_functionst::get_functions(
322321
const exprt &function,
323322
dispatch_table_entriest &functions)
324323
{
324+
// class part of function to call
325325
const irep_idt class_id=function.get(ID_C_class);
326326
const std::string class_id_string(id2string(class_id));
327+
// method/function name of function to call
327328
const irep_idt component_name=function.get(ID_component_name);
328329
const std::string component_name_string(id2string(component_name));
329330
INVARIANT(!class_id.empty(), "All virtual functions must have a class");
@@ -359,17 +360,32 @@ void remove_virtual_functionst::get_functions(
359360
}
360361

361362
// iterate over all children, transitively
362-
std::set<irep_idt> visited;
363363
get_child_functions_rec(
364364
class_id,
365365
root_function.symbol_expr,
366366
component_name,
367367
functions,
368-
visited,
369368
resolve_function_call);
370369

371370
if(root_function.symbol_expr!=symbol_exprt())
372371
functions.push_back(root_function);
372+
373+
// remove all classes from dispatch table where concrete call has been found
374+
std::set<irep_idt> concrete_call;
375+
for(const auto &entry : functions)
376+
{
377+
if(entry.symbol_expr != root_function.symbol_expr)
378+
concrete_call.insert(entry.class_id);
379+
}
380+
381+
std::remove_if(
382+
functions.begin(),
383+
functions.end(),
384+
[&concrete_call, &root_function](const dispatch_table_entryt &entry) {
385+
return
386+
concrete_call.find(entry.class_id) != concrete_call.end() &&
387+
entry.symbol_expr == root_function.symbol_expr;
388+
});
373389
}
374390

375391
exprt remove_virtual_functionst::get_method(

0 commit comments

Comments
 (0)