Skip to content

Commit 460c788

Browse files
author
Daniel Kroening
committed
remove_returns now preserves signature
This simplifies removal, and removes the need to query the 'original' return type.
1 parent d4aeb3c commit 460c788

File tree

5 files changed

+42
-161
lines changed

5 files changed

+42
-161
lines changed

jbmc/src/java_bytecode/java_bytecode_convert_method.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,16 +2079,14 @@ void java_bytecode_convert_methodt::convert_invoke(
20792079
// less accurate.
20802080
if(method_symbol != symbol_table.symbols.end())
20812081
{
2082-
const auto &restored_type =
2083-
original_return_type(symbol_table, invoked_method_id);
20842082
// Note the number of parameters might change here due to constructors using
20852083
// invokespecial will have zero arguments (the `this` is added below)
20862084
// but the symbol for the <init> will have the this parameter.
20872085
INVARIANT(
20882086
to_java_method_type(arg0.type()).return_type().id() ==
2089-
restored_type.return_type().id(),
2087+
to_code_type(method_symbol->second.type).return_type().id(),
20902088
"Function return type must not change in kind");
2091-
arg0.type() = restored_type;
2089+
arg0.type() = method_symbol->second.type;
20922090
}
20932091

20942092
// Note arg0 and arg0.type() are subject to many side-effects in this method,

src/goto-checker/symex_coverage.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,8 @@ goto_program_coverage_recordt::goto_program_coverage_recordt(
160160
// </method>
161161
xml.set_attribute("name", id2string(gf_it->first));
162162

163-
code_typet sig_type =
164-
original_return_type(ns.get_symbol_table(), gf_it->first);
165-
xml.set_attribute("signature", from_type(ns, gf_it->first, sig_type));
163+
xml.set_attribute(
164+
"signature", from_type(ns, gf_it->first, gf_it->second.type));
166165

167166
xml.set_attribute("line-rate", rate_detailed(lines_covered, lines_total));
168167
xml.set_attribute("branch-rate", rate(branches_covered, branches_total));

src/goto-programs/goto_program.cpp

Lines changed: 0 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -708,45 +708,6 @@ void goto_programt::instructiont::validate(
708708
bool symbol_expr_type_matches_symbol_table =
709709
base_type_eq(goto_symbol_expr.type(), table_symbol->type, ns);
710710

711-
if(
712-
!symbol_expr_type_matches_symbol_table &&
713-
table_symbol->type.id() == ID_code)
714-
{
715-
// Return removal sets the return type of a function symbol table
716-
// entry to 'void', but some callsites still expect the original
717-
// type (e.g. if a function is passed as a parameter)
718-
symbol_expr_type_matches_symbol_table = base_type_eq(
719-
goto_symbol_expr.type(),
720-
original_return_type(ns.get_symbol_table(), goto_id),
721-
ns);
722-
723-
if(
724-
!symbol_expr_type_matches_symbol_table &&
725-
goto_symbol_expr.type().id() == ID_code)
726-
{
727-
// If a function declaration and its definition are in different
728-
// translation units they may have different return types,
729-
// which remove_returns patches up with a typecast. If thats
730-
// the case, then the return type in the symbol table may differ
731-
// from the return type in the symbol expr
732-
if(
733-
goto_symbol_expr.type().source_location().get_file() !=
734-
table_symbol->type.source_location().get_file())
735-
{
736-
// temporarily fixup the return types
737-
auto goto_symbol_expr_type =
738-
to_code_type(goto_symbol_expr.type());
739-
auto table_symbol_type = to_code_type(table_symbol->type);
740-
741-
goto_symbol_expr_type.return_type() =
742-
table_symbol_type.return_type();
743-
744-
symbol_expr_type_matches_symbol_table =
745-
base_type_eq(goto_symbol_expr_type, table_symbol_type, ns);
746-
}
747-
}
748-
}
749-
750711
if(
751712
!symbol_expr_type_matches_symbol_table &&
752713
goto_symbol_expr.type().id() == ID_array &&

src/goto-programs/remove_returns.cpp

Lines changed: 37 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,6 @@ void remove_returnst::replace_returns(
106106
// add return_value symbol to symbol_table, if not already created:
107107
const auto return_symbol = get_or_create_return_value_symbol(function_id);
108108

109-
// look up the function symbol
110-
symbolt &function_symbol = *symbol_table.get_writeable(function_id);
111-
112-
// make the return type 'void'
113-
function.type.return_type() = empty_typet();
114-
function_symbol.type = function.type;
115-
116109
goto_programt &goto_program = function.body;
117110

118111
Forall_goto_program_instructions(i_it, goto_program)
@@ -160,67 +153,50 @@ void remove_returnst::do_function_calls(
160153
const irep_idt function_id =
161154
to_symbol_expr(function_call.function()).get_identifier();
162155

163-
optionalt<symbol_exprt> return_value;
164-
typet old_return_type;
165-
bool is_stub = function_is_stub(function_id);
166-
167-
if(is_stub)
168-
{
169-
old_return_type =
170-
to_code_type(function_call.function().type()).return_type();
171-
}
172-
else
173-
{
174-
// The callee may or may not already have been transformed by this pass,
175-
// so its symbol-table entry may already have void return type.
176-
// To simplify matters, create its return-value global now (if not
177-
// already done), and use that to determine its true return type.
178-
return_value = get_or_create_return_value_symbol(function_id);
179-
if(!return_value.has_value()) // really void-typed?
180-
continue;
181-
old_return_type = return_value->type();
182-
}
183-
184156
// Do we return anything?
185-
if(old_return_type != empty_typet())
157+
if(
158+
to_code_type(function_call.function().type()).return_type() !=
159+
empty_typet() &&
160+
function_call.lhs().is_not_nil())
186161
{
187162
// replace "lhs=f(...)" by
188163
// "f(...); lhs=f#return_value; DEAD f#return_value;"
189164

190-
// fix the type
191-
to_code_type(function_call.function().type()).return_type()=
192-
empty_typet();
165+
exprt rhs;
166+
167+
bool is_stub = function_is_stub(function_id);
168+
optionalt<symbol_exprt> return_value;
169+
170+
if(!is_stub)
171+
{
172+
return_value = get_or_create_return_value_symbol(function_id);
173+
CHECK_RETURN(return_value.has_value());
174+
175+
// The return type in the definition of the function may differ
176+
// from the return type in the declaration. We therefore do a
177+
// cast.
178+
rhs = typecast_exprt::conditional_cast(
179+
*return_value, function_call.lhs().type());
180+
}
181+
else
182+
{
183+
rhs = side_effect_expr_nondett(
184+
function_call.lhs().type(), i_it->source_location);
185+
}
186+
187+
goto_programt::targett t_a = goto_program.insert_after(
188+
i_it,
189+
goto_programt::make_assignment(
190+
code_assignt(function_call.lhs(), rhs), i_it->source_location));
191+
192+
// fry the previous assignment
193+
function_call.lhs().make_nil();
193194

194-
if(function_call.lhs().is_not_nil())
195+
if(!is_stub)
195196
{
196-
exprt rhs;
197-
198-
if(!is_stub)
199-
{
200-
// The return type in the definition of the function may differ
201-
// from the return type in the declaration. We therefore do a
202-
// cast.
203-
rhs = typecast_exprt::conditional_cast(
204-
*return_value, function_call.lhs().type());
205-
}
206-
else
207-
rhs = side_effect_expr_nondett(
208-
function_call.lhs().type(), i_it->source_location);
209-
210-
goto_programt::targett t_a = goto_program.insert_after(
211-
i_it,
212-
goto_programt::make_assignment(
213-
code_assignt(function_call.lhs(), rhs), i_it->source_location));
214-
215-
// fry the previous assignment
216-
function_call.lhs().make_nil();
217-
218-
if(!is_stub)
219-
{
220-
goto_program.insert_after(
221-
t_a,
222-
goto_programt::make_dead(*return_value, i_it->source_location));
223-
}
197+
goto_program.insert_after(
198+
t_a,
199+
goto_programt::make_dead(*return_value, i_it->source_location));
224200
}
225201

226202
// update the call
@@ -299,31 +275,6 @@ void remove_returns(goto_modelt &goto_model)
299275
rr(goto_model.goto_functions);
300276
}
301277

302-
/// Get code type of a function that has had remove_returns run upon it
303-
/// \param symbol_table: global symbol table
304-
/// \param function_id: function to get the type of
305-
/// \return the function's type with its `return_type()` restored to its
306-
/// original value
307-
code_typet original_return_type(
308-
const symbol_table_baset &symbol_table,
309-
const irep_idt &function_id)
310-
{
311-
// look up the function symbol
312-
const symbolt &function_symbol = symbol_table.lookup_ref(function_id);
313-
code_typet type = to_code_type(function_symbol.type);
314-
315-
// do we have X#return_value?
316-
std::string rv_name=id2string(function_id)+RETURN_VALUE_SUFFIX;
317-
318-
symbol_tablet::symbolst::const_iterator rv_it=
319-
symbol_table.symbols.find(rv_name);
320-
321-
if(rv_it != symbol_table.symbols.end())
322-
type.return_type() = rv_it->second.type;
323-
324-
return type;
325-
}
326-
327278
/// turns an assignment to fkt#return_value back into 'return x'
328279
bool remove_returnst::restore_returns(
329280
goto_functionst::function_mapt::iterator f_it)
@@ -339,13 +290,6 @@ bool remove_returnst::restore_returns(
339290
if(rv_it==symbol_table.symbols.end())
340291
return true;
341292

342-
// look up the function symbol
343-
symbolt &function_symbol=*symbol_table.get_writeable(function_id);
344-
345-
// restore the return type
346-
f_it->second.type=original_return_type(symbol_table, function_id);
347-
function_symbol.type=f_it->second.type;
348-
349293
// remove the return_value symbol from the symbol_table
350294
irep_idt rv_name_id=rv_it->second.name;
351295
symbol_table.erase(rv_it);
@@ -397,12 +341,6 @@ void remove_returnst::undo_function_calls(
397341
const irep_idt function_id=
398342
to_symbol_expr(function_call.function()).get_identifier();
399343

400-
const symbolt &function_symbol=ns.lookup(function_id);
401-
402-
// fix the type
403-
to_code_type(function_call.function().type()).return_type()=
404-
to_code_type(function_symbol.type).return_type();
405-
406344
// find "f(...); lhs=f#return_value; DEAD f#return_value;"
407345
// and revert to "lhs=f(...);"
408346
goto_programt::instructionst::iterator next = std::next(i_it);

src/goto-programs/remove_returns.h

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,18 +66,7 @@ Date: September 2009
6666
/// r = func#return_value;
6767
///
6868
/// ```
69-
///
70-
/// As `return` instructions are removed, the return types of the function types
71-
/// are set to void as well (represented by the type `empty_typet`). This
72-
/// applies both to the functions (i.e., the member `type` of `goto_functiont`)
73-
/// and to the call sites (i.e., the type
74-
/// `to_code_function_call(code).function().type()` with `code` being the code
75-
/// member of the `instructiont` instance that represents the function call).
76-
///
77-
/// The types of function pointer expressions in the goto program are however
78-
/// not changed. For example, in an assignment where `func` is assigned to a
79-
/// function pointer, such as `int (*f)(void) = func`, the function types
80-
/// appearing in the lhs and rhs both retain the integer return type.
69+
/// `remove_returns()` does not change the signature of the function.
8170

8271
#ifndef CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H
8372
#define CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H
@@ -106,8 +95,4 @@ void restore_returns(symbol_table_baset &, goto_functionst &);
10695

10796
void restore_returns(goto_modelt &);
10897

109-
code_typet original_return_type(
110-
const symbol_table_baset &symbol_table,
111-
const irep_idt &function_id);
112-
11398
#endif // CPROVER_GOTO_PROGRAMS_REMOVE_RETURNS_H

0 commit comments

Comments
 (0)