Skip to content

Commit a7eaa8e

Browse files
author
Owen Jones
committed
Deal with virtual function calls with no candidate targets
During virtual method resolution, if a virtual function call has no candidate targets then we add the class it was called on as an instantiated class.
1 parent f2b58be commit a7eaa8e

File tree

1 file changed

+51
-7
lines changed

1 file changed

+51
-7
lines changed

src/java_bytecode/ci_lazy_methods.cpp

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,9 @@ bool ci_lazy_methodst::operator()(
122122
std::unordered_set<irep_idt> methods_already_populated;
123123
std::unordered_set<exprt, irep_hash> virtual_function_calls;
124124

125-
bool any_new_methods = true;
125+
bool any_new_classes = true;
126+
while(any_new_classes)
127+
{bool any_new_methods = true;
126128
while(any_new_methods)
127129
{
128130
any_new_methods=false;
@@ -152,16 +154,58 @@ bool ci_lazy_methodst::operator()(
152154
}
153155
}
154156

155-
// Given the object types we now know may be created, populate more
156-
// possible virtual function call targets:
157+
// Given the object types we now know may be created, populate more
158+
// possible virtual function call targets:
157159

158-
debug() << "CI lazy methods: add virtual method targets ("
159-
<< virtual_function_calls.size() << " callsites)" << eom;
160+
debug() << "CI lazy methods: add virtual method targets ("
161+
<< virtual_function_calls.size() << " callsites)" << eom;
160162

161-
for(const exprt &function : virtual_function_calls)
163+
for(const exprt &function : virtual_function_calls)
164+
{
165+
get_virtual_method_targets(
166+
function,
167+
instantiated_classes,
168+
methods_to_convert_later,
169+
symbol_table);
170+
}
171+
}
172+
173+
any_new_classes = false;
174+
175+
// Look for virtual callsites with no candidate targets. If we have
176+
// invokevirtual A.f and we don't believe either A or any of its children
177+
// may exist, we assume specifically A is somehow instantiated. Note this
178+
// may result in an abstract class being classified as instantiated, which
179+
// stands in for some unknown concrete subclass: in this case the called
180+
// method will be a stub.
181+
for(const exprt &virtual_function_call : virtual_function_calls)
162182
{
183+
std::unordered_set<irep_idt> candidate_target_methods;
163184
get_virtual_method_targets(
164-
function, instantiated_classes, methods_to_convert_later, symbol_table);
185+
virtual_function_call,
186+
instantiated_classes,
187+
candidate_target_methods,
188+
symbol_table);
189+
190+
if(!candidate_target_methods.empty())
191+
continue;
192+
193+
// Add the call class to instantiated_classes and assert that it
194+
// didn't already exist
195+
const irep_idt &call_class = virtual_function_call.get(ID_C_class);
196+
auto ret_class = instantiated_classes.insert(call_class);
197+
CHECK_RETURN(ret_class.second);
198+
any_new_classes = true;
199+
200+
// Check that `get_virtual_method_target` returns a method now
201+
const irep_idt &call_basename =
202+
virtual_function_call.get(ID_component_name);
203+
const irep_idt method_name = get_virtual_method_target(
204+
instantiated_classes, call_basename, call_class, symbol_table);
205+
CHECK_RETURN(!method_name.empty());
206+
207+
// Add what it returns to methods_to_convert_later
208+
methods_to_convert_later.insert(method_name);
165209
}
166210
}
167211

0 commit comments

Comments
 (0)