Skip to content

Commit 05e5be3

Browse files
committed
Return value removal: handle missing declarations more gracefully
If a function is used before it is defined, a signature of int f(void) is assumed. Then trying to use the (possibly non-existent) return value fails during return-statement removal. In such cases, just assume a non-deterministic value is being returned. Found by running C-Reduce on a CSmith-generated example.
1 parent 52b9097 commit 05e5be3

File tree

4 files changed

+50
-3
lines changed

4 files changed

+50
-3
lines changed

regression/cbmc/return7/main.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
void a()
2+
{
3+
// Uses the implicit signature of undefined functions: int c(void)
4+
int b;
5+
b = c();
6+
__CPROVER_assert(b == 0, "expected to fail");
7+
}
8+
void c(void)
9+
{
10+
// Actually... don't return anything
11+
// So the results will be non-deterministic
12+
}
13+
14+
int main(int argc, char **argv)
15+
{
16+
a();
17+
return 0;
18+
}

regression/cbmc/return7/test.desc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
CORE
2+
main.c
3+
4+
^VERIFICATION FAILED$
5+
^EXIT=10$
6+
^SIGNAL=0$
7+
--
8+
Reason: Check return value
9+
^warning: ignoring

src/goto-programs/builtin_functions.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -762,6 +762,16 @@ void goto_convertt::do_function_call_symbol(
762762
code_function_callt function_call(lhs, function, arguments);
763763
function_call.add_source_location() = function.source_location();
764764

765+
// remove void-typed assignments, which may have been created when the
766+
// front-end was unable to detect them in type checking for a lack of
767+
// available declarations
768+
if(
769+
lhs.is_not_nil() &&
770+
to_code_type(symbol->type).return_type().id() == ID_empty)
771+
{
772+
function_call.lhs().make_nil();
773+
}
774+
765775
copy(function_call, FUNCTION_CALL, dest);
766776

767777
return;
@@ -1435,6 +1445,16 @@ void goto_convertt::do_function_call_symbol(
14351445
code_function_callt function_call(lhs, function, arguments);
14361446
function_call.add_source_location()=function.source_location();
14371447

1448+
// remove void-typed assignments, which may have been created when the
1449+
// front-end was unable to detect them in type checking for a lack of
1450+
// available declarations
1451+
if(
1452+
lhs.is_not_nil() &&
1453+
to_code_type(symbol->type).return_type().id() == ID_empty)
1454+
{
1455+
function_call.lhs().make_nil();
1456+
}
1457+
14381458
copy(function_call, FUNCTION_CALL, dest);
14391459
}
14401460
}

src/goto-programs/remove_returns.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,10 @@ bool remove_returnst::do_function_calls(
175175
optionalt<symbol_exprt> return_value;
176176

177177
if(!is_stub)
178-
{
179178
return_value = get_or_create_return_value_symbol(function_id);
180-
CHECK_RETURN(return_value.has_value());
181179

180+
if(return_value.has_value())
181+
{
182182
// The return type in the definition of the function may differ
183183
// from the return type in the declaration. We therefore do a
184184
// cast.
@@ -199,7 +199,7 @@ bool remove_returnst::do_function_calls(
199199
// fry the previous assignment
200200
i_it->call_lhs().make_nil();
201201

202-
if(!is_stub)
202+
if(return_value.has_value())
203203
{
204204
goto_program.insert_after(
205205
t_a,

0 commit comments

Comments
 (0)