Skip to content

Commit 8192246

Browse files
author
Owen Jones
committed
Make remove_virtual_function() consistent
If there is more than one possible virtual function, we cast the object to the appropriate type in each case, but if there is only one possibility we don't. This PR makes us cast the object when there is only one possibility as well. Note that just because there is only one possibility, it does not mean that the object already has the correct type. Also, if the object is already the correct type then the cast isn't inserted, in all cases.
1 parent b36a90a commit 8192246

File tree

1 file changed

+28
-14
lines changed

1 file changed

+28
-14
lines changed

src/goto-programs/remove_virtual_functions.cpp

+28-14
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,28 @@ void remove_virtual_functionst::remove_virtual_function(
9696
virtual_dispatch_fallback_actiont::CALL_LAST_FUNCTION);
9797
}
9898

99+
/// Create a concrete function call to replace a virtual one
100+
/// \param call [in/out]: the function call to update
101+
/// \param function_symbol: the function to be called
102+
/// \param ns: namespace
103+
static void create_static_function_call(
104+
code_function_callt &call,
105+
const symbol_exprt &function_symbol,
106+
const namespacet &ns)
107+
{
108+
call.function() = function_symbol;
109+
// Cast the `this` pointer to the correct type for the new callee:
110+
const auto &callee_type =
111+
to_code_type(ns.lookup(function_symbol.get_identifier()).type);
112+
const code_typet::parametert *this_param = callee_type.get_this();
113+
INVARIANT(
114+
this_param != nullptr,
115+
"Virtual function callees must have a `this` argument");
116+
typet need_type = this_param->type();
117+
if(!type_eq(call.arguments()[0].type(), need_type, ns))
118+
call.arguments()[0].make_typecast(need_type);
119+
}
120+
99121
void remove_virtual_functionst::remove_virtual_function(
100122
goto_programt &goto_program,
101123
goto_programt::targett target,
@@ -121,8 +143,10 @@ void remove_virtual_functionst::remove_virtual_function(
121143
if(functions.begin()->symbol_expr==symbol_exprt())
122144
target->make_skip();
123145
else
124-
to_code_function_call(target->code).function()=
125-
functions.begin()->symbol_expr;
146+
{
147+
create_static_function_call(
148+
to_code_function_call(target->code), functions.front().symbol_expr, ns);
149+
}
126150
return;
127151
}
128152

@@ -187,18 +211,8 @@ void remove_virtual_functionst::remove_virtual_function(
187211
{
188212
// call function
189213
t1->make_function_call(code);
190-
auto &newcall=to_code_function_call(t1->code);
191-
newcall.function()=fun.symbol_expr;
192-
// Cast the `this` pointer to the correct type for the new callee:
193-
const auto &callee_type=
194-
to_code_type(ns.lookup(fun.symbol_expr.get_identifier()).type);
195-
const code_typet::parametert *this_param = callee_type.get_this();
196-
INVARIANT(
197-
this_param != nullptr,
198-
"Virtual function callees must have a `this` argument");
199-
typet need_type=this_param->type();
200-
if(!type_eq(newcall.arguments()[0].type(), need_type, ns))
201-
newcall.arguments()[0].make_typecast(need_type);
214+
create_static_function_call(
215+
to_code_function_call(t1->code), fun.symbol_expr, ns);
202216
}
203217
else
204218
{

0 commit comments

Comments
 (0)