Skip to content

Commit 61b0d6d

Browse files
author
Matthias Güdemann
authored
Merge pull request #1666 from mgudemann/bugfix/removed_required_virtual_calls
[TG-1523] fix removed required virtual calls
2 parents fabc99e + 3365054 commit 61b0d6d

17 files changed

+152
-11
lines changed
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
public abstract class AbstractList<E>
2+
implements List<E>
3+
{
4+
public Iterator<E> iterator() {
5+
return new Itr();
6+
}
7+
8+
public ListIterator<E> listIterator() {
9+
return listIterator(0);
10+
}
11+
12+
public boolean equals(Object o) {
13+
if (o == this)
14+
return true;
15+
if (!(o instanceof List))
16+
return false;
17+
18+
ListIterator<E> e1 = listIterator();
19+
ListIterator<?> e2 = ((List<?>) o).listIterator();
20+
while (e1.hasNext() && e2.hasNext()) {
21+
E o1 = e1.next();
22+
Object o2 = e2.next();
23+
if (!(o1==null ? o2==null : o1.equals(o2)))
24+
return false;
25+
}
26+
return !(e1.hasNext() || e2.hasNext());
27+
}
28+
29+
private class Itr implements Iterator<E> {
30+
Itr() {
31+
}
32+
33+
public boolean hasNext() {
34+
return false;
35+
}
36+
37+
public E next() {
38+
return null;
39+
}
40+
41+
}
42+
}
Binary file not shown.
Binary file not shown.
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
public class ArrayList<E> extends AbstractList<E>
2+
implements List<E>
3+
{
4+
public ListIterator<E> listIterator() {
5+
return new ListItr(0);
6+
}
7+
public ListIterator<E> listIterator(int index) {
8+
return new ListItr(index);
9+
}
10+
private class ListItr extends Itr implements ListIterator<E> {
11+
ListItr(int index) {
12+
super();
13+
}
14+
15+
public boolean hasPrevious() {
16+
return false;
17+
}
18+
}
19+
20+
private class Itr implements Iterator<E> {
21+
Itr() {
22+
}
23+
24+
public boolean hasNext() {
25+
return false;
26+
}
27+
public E next() {
28+
return null;
29+
}
30+
}
31+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
public class ArrayListEquals {
2+
3+
public int check2(ArrayList<Integer> l1) {
4+
ArrayList<Integer> al = new ArrayList<Integer>();
5+
if(l1.equals(al))
6+
return 1;
7+
else
8+
return 0;
9+
}
10+
11+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public interface Iterator<E> {
2+
boolean hasNext();
3+
E next();
4+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
public interface List<E> {
2+
ListIterator<E> listIterator();
3+
ListIterator<E> listIterator(int index);
4+
}
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
public interface ListIterator<E> extends Iterator<E> {
2+
boolean hasNext();
3+
boolean hasPrevious();
4+
E next();
5+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
CORE
2+
ArrayListEquals.class
3+
--lazy-methods --java-max-vla-length 48 --unwind 8 --java-unwind-enum-static --trace --cover location --function ArrayListEquals.check2 --show-goto-functions
4+
e2 . ArrayList\$Itr.hasNext:\(\)Z\(\);
5+
--
6+
e2 . ListIterator.hasNext:\(\)Z\(\);

src/goto-programs/remove_virtual_functions.cpp

+49-11
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(
@@ -192,6 +198,10 @@ void remove_virtual_functionst::remove_virtual_function(
192198
{
193199
// No definition for this type; shouldn't be possible...
194200
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)));
195205
}
196206
insertit.first->second=t1;
197207
// goto final
@@ -247,6 +257,7 @@ void remove_virtual_functionst::remove_virtual_function(
247257
/// `last_method_defn`: the most-derived parent of `this_id` to define the
248258
/// requested function
249259
/// `component_name`: name of the function searched for
260+
/// `resolve_function_call`: function to resolve abstract method call
250261
/// \return `functions` is assigned a list of {class name, function symbol}
251262
/// pairs indicating that if `this` is of the given class, then the call will
252263
/// 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(
257268
const symbol_exprt &last_method_defn,
258269
const irep_idt &component_name,
259270
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
261273
{
262274
auto findit=class_hierarchy.class_map.find(this_id);
263275
if(findit==class_hierarchy.class_map.end())
@@ -278,14 +290,30 @@ void remove_virtual_functionst::get_child_functions_rec(
278290
{
279291
function.symbol_expr=last_method_defn;
280292
}
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+
}
281308
functions.push_back(function);
282309

283310
get_child_functions_rec(
284311
child,
285312
function.symbol_expr,
286313
component_name,
287314
functions,
288-
visited);
315+
visited,
316+
resolve_function_call);
289317
}
290318
}
291319

@@ -294,21 +322,30 @@ void remove_virtual_functionst::get_functions(
294322
dispatch_table_entriest &functions)
295323
{
296324
const irep_idt class_id=function.get(ID_C_class);
325+
const std::string class_id_string(id2string(class_id));
297326
const irep_idt component_name=function.get(ID_component_name);
327+
const std::string component_name_string(id2string(component_name));
298328
INVARIANT(!class_id.empty(), "All virtual functions must have a class");
299329

300330
resolve_concrete_function_callt get_virtual_call_target(
301331
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+
304341
dispatch_table_entryt root_function;
305342

306343
if(resolved_call.is_valid())
307344
{
308345
root_function.class_id=resolved_call.get_class_identifier();
309346

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());
312349

313350
root_function.symbol_expr=called_symbol.symbol_expr();
314351
root_function.symbol_expr.set(
@@ -327,7 +364,8 @@ void remove_virtual_functionst::get_functions(
327364
root_function.symbol_expr,
328365
component_name,
329366
functions,
330-
visited);
367+
visited,
368+
resolve_function_call);
331369

332370
if(root_function.symbol_expr!=symbol_exprt())
333371
functions.push_back(root_function);

0 commit comments

Comments
 (0)