Skip to content

Commit aecd491

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 6461a1f commit aecd491

File tree

6 files changed

+61
-160
lines changed

6 files changed

+61
-160
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
@@ -2089,16 +2089,14 @@ void java_bytecode_convert_methodt::convert_invoke(
20892089
// less accurate.
20902090
if(method_symbol != symbol_table.symbols.end())
20912091
{
2092-
const auto &restored_type =
2093-
original_return_type(symbol_table, invoked_method_id);
20942092
// Note the number of parameters might change here due to constructors using
20952093
// invokespecial will have zero arguments (the `this` is added below)
20962094
// but the symbol for the <init> will have the this parameter.
20972095
INVARIANT(
20982096
to_java_method_type(arg0.type()).return_type().id() ==
2099-
restored_type.return_type().id(),
2097+
to_code_type(method_symbol->second.type).return_type().id(),
21002098
"Function return type must not change in kind");
2101-
arg0.type() = restored_type;
2099+
arg0.type() = method_symbol->second.type;
21022100
}
21032101

21042102
// 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: 16 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -713,37 +713,24 @@ void goto_programt::instructiont::validate(
713713
!symbol_expr_type_matches_symbol_table &&
714714
table_symbol->type.id() == ID_code)
715715
{
716-
// Return removal sets the return type of a function symbol table
717-
// entry to 'void', but some callsites still expect the original
718-
// type (e.g. if a function is passed as a parameter)
719-
symbol_expr_type_matches_symbol_table =
720-
goto_symbol_expr.type() ==
721-
original_return_type(ns.get_symbol_table(), goto_id);
722-
716+
// If a function declaration and its definition are in different
717+
// translation units they may have different return types.
718+
// Thus, the return type in the symbol table may differ
719+
// from the return type in the symbol expr.
723720
if(
724-
!symbol_expr_type_matches_symbol_table &&
725-
goto_symbol_expr.type().id() == ID_code)
721+
goto_symbol_expr.type().source_location().get_file() !=
722+
table_symbol->type.source_location().get_file())
726723
{
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-
}
724+
// temporarily fixup the return types
725+
auto goto_symbol_expr_type =
726+
to_code_type(goto_symbol_expr.type());
727+
auto table_symbol_type = to_code_type(table_symbol->type);
728+
729+
goto_symbol_expr_type.return_type() =
730+
table_symbol_type.return_type();
731+
732+
symbol_expr_type_matches_symbol_table =
733+
base_type_eq(goto_symbol_expr_type, table_symbol_type, ns);
747734
}
748735
}
749736

src/goto-programs/remove_returns.cpp

Lines changed: 39 additions & 101 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)
@@ -164,73 +157,56 @@ bool remove_returnst::do_function_calls(
164157
const irep_idt function_id =
165158
to_symbol_expr(function_call.function()).get_identifier();
166159

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

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

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

232206
// update the call
233207
i_it->set_function_call(function_call);
208+
209+
requires_update = true;
234210
}
235211
}
236212
}
@@ -309,31 +285,6 @@ void remove_returns(goto_modelt &goto_model)
309285
rr(goto_model.goto_functions);
310286
}
311287

312-
/// Get code type of a function that has had remove_returns run upon it
313-
/// \param symbol_table: global symbol table
314-
/// \param function_id: function to get the type of
315-
/// \return the function's type with its `return_type()` restored to its
316-
/// original value
317-
code_typet original_return_type(
318-
const symbol_table_baset &symbol_table,
319-
const irep_idt &function_id)
320-
{
321-
// look up the function symbol
322-
const symbolt &function_symbol = symbol_table.lookup_ref(function_id);
323-
code_typet type = to_code_type(function_symbol.type);
324-
325-
// do we have X#return_value?
326-
std::string rv_name=id2string(function_id)+RETURN_VALUE_SUFFIX;
327-
328-
symbol_tablet::symbolst::const_iterator rv_it=
329-
symbol_table.symbols.find(rv_name);
330-
331-
if(rv_it != symbol_table.symbols.end())
332-
type.return_type() = rv_it->second.type;
333-
334-
return type;
335-
}
336-
337288
/// turns an assignment to fkt#return_value back into 'return x'
338289
bool remove_returnst::restore_returns(
339290
goto_functionst::function_mapt::iterator f_it)
@@ -349,13 +300,6 @@ bool remove_returnst::restore_returns(
349300
if(rv_it==symbol_table.symbols.end())
350301
return true;
351302

352-
// look up the function symbol
353-
symbolt &function_symbol=*symbol_table.get_writeable(function_id);
354-
355-
// restore the return type
356-
f_it->second.type=original_return_type(symbol_table, function_id);
357-
function_symbol.type=f_it->second.type;
358-
359303
// remove the return_value symbol from the symbol_table
360304
irep_idt rv_name_id=rv_it->second.name;
361305
symbol_table.erase(rv_it);
@@ -407,12 +351,6 @@ void remove_returnst::undo_function_calls(
407351
const irep_idt function_id=
408352
to_symbol_expr(function_call.function()).get_identifier();
409353

410-
const symbolt &function_symbol=ns.lookup(function_id);
411-
412-
// fix the type
413-
to_code_type(function_call.function().type()).return_type()=
414-
to_code_type(function_symbol.type).return_type();
415-
416354
// find "f(...); lhs=f#return_value; DEAD f#return_value;"
417355
// and revert to "lhs=f(...);"
418356
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

src/goto-programs/validate_goto_model.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,7 @@ void validate_goto_modelt::check_returns_removed()
133133
DATA_CHECK(
134134
vm,
135135
function_call.lhs().is_nil(),
136-
"function call return should be nil");
137-
138-
const auto &callee = to_code_type(function_call.function().type());
139-
DATA_CHECK(
140-
vm,
141-
callee.return_type().id() == ID_empty,
142-
"called function must have empty return type");
136+
"function call lhs return should be nil");
143137
}
144138
}
145139
}

0 commit comments

Comments
 (0)