Skip to content

Commit 0e54364

Browse files
committed
calls to functions without body
1 parent 676b359 commit 0e54364

File tree

3 files changed

+111
-52
lines changed

3 files changed

+111
-52
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
int function_without_body();
2+
3+
int main()
4+
{
5+
int x = function_without_body();
6+
return 0;
7+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
call_no_body1.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\(\d+\) ∀ ς : state \. S21\(ς\) ⇒ S22\(ς\[❝main::\$tmp::return_value_function_without_body❞:=nondet22\]\)$
7+
^\(\d+\) ∀ ς : state \. S22\(ς\) ⇒ S23\(ς\[❝main::1::x❞:=ς\(❝main::\$tmp::return_value_function_without_body❞\)\]\)$
8+
--

src/cprover/state_encoding.cpp

Lines changed: 96 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ mathematical_function_typet state_predicate_type()
4747
class state_encodingt
4848
{
4949
public:
50-
void operator()(const goto_functiont &, encoding_targett &);
50+
void operator()(
51+
const goto_functionst &,
52+
const goto_functiont &,
53+
encoding_targett &);
5154

5255
protected:
5356
using loct = goto_programt::const_targett;
@@ -245,6 +248,7 @@ void state_encodingt::setup_incoming(const goto_functiont &goto_function)
245248
}
246249

247250
void state_encodingt::operator()(
251+
const goto_functionst &goto_functions,
248252
const goto_functiont &goto_function,
249253
encoding_targett &dest)
250254
{
@@ -353,63 +357,103 @@ void state_encodingt::operator()(
353357
}
354358
else if(loc->is_function_call())
355359
{
356-
// Evaluate the arguments of the call in the 'in state'
357-
multi_ary_exprt arguments_evaluated(ID_tuple, {}, typet(ID_tuple));
358-
arguments_evaluated.reserve_operands(loc->call_arguments().size());
359-
360-
const auto in_state = in_state_expr(loc);
361-
362-
for(auto &argument : loc->call_arguments())
363-
arguments_evaluated.add_to_operands(evaluate_expr(loc, in_state, argument));
364-
365-
auto function_entry_state = state_expr_with_suffix(loc, "Entry");
366-
367-
dest << forall_states_expr(loc,
368-
function_application_exprt(function_entry_state, {state_expr()}));
369-
370-
// Function return state (suffix PostReturn).
371-
// This is the state after exiting the function but prior to
372-
// assigning the LHS of the function call.
373-
auto return_state = state_expr_with_suffix(loc, "PostReturn");
374-
375-
/*
376-
constraints.push_back(
377-
multi_ary_exprt(
378-
ID_goto_contract,
379-
{loc->call_function(), in_state, return_state, arguments_evaluated},
380-
bool_typet()));
381-
*/
382-
383-
// assign the return value, if any
384-
if(loc->call_lhs().is_not_nil())
360+
// Function pointer?
361+
const auto &function = loc->call_function();
362+
if(function.id() == ID_dereference)
385363
{
386-
exprt equality_rhs = return_state;
387-
388-
/*
389-
auto &return_type = loc->call_lhs().type();
390-
auto rhs_evaluated =
391-
evaluate_expr(
392-
loc,
393-
return_state,
394-
symbol_exprt("return_value", return_type));
364+
// TBD.
365+
PRECONDITION(false);
366+
}
367+
else if(function.id() == ID_symbol)
368+
{
369+
// Do we have a function body?
370+
auto identifier = to_symbol_expr(function).get_identifier();
371+
auto f = goto_functions.function_map.find(identifier);
372+
if(f == goto_functions.function_map.end())
373+
DATA_INVARIANT(false, "failed find function in function_map");
374+
if(f->second.body_available())
375+
{
376+
// Evaluate the arguments of the call in the 'in state'
377+
multi_ary_exprt arguments_evaluated(ID_tuple, {}, typet(ID_tuple));
378+
arguments_evaluated.reserve_operands(loc->call_arguments().size());
395379

396-
multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet());
380+
const auto in_state = in_state_expr(loc);
397381

398-
auto lhs = out_state_expr(source);
382+
for(auto &argument : loc->call_arguments())
383+
arguments_evaluated.add_to_operands(
384+
evaluate_expr(loc, in_state, argument));
399385

400-
auto rhs = update_exprt(
401-
return_state,
402-
designator,
403-
rhs_evaluated);
386+
auto function_entry_state = state_expr_with_suffix(loc, "Entry");
404387

405-
// 'out state' equality
406-
constraints.push_back(equal_exprt(lhs, rhs));
407-
*/
388+
dest << forall_states_expr(
389+
loc,
390+
function_application_exprt(function_entry_state, {state_expr()}));
391+
392+
// Function return state (suffix PostReturn).
393+
// This is the state after exiting the function but prior to
394+
// assigning the LHS of the function call.
395+
auto return_state = state_expr_with_suffix(loc, "PostReturn");
396+
397+
/*
398+
constraints.push_back(
399+
multi_ary_exprt(
400+
ID_goto_contract,
401+
{loc->call_function(), in_state, return_state, arguments_evaluated},
402+
bool_typet()));
403+
*/
404+
405+
// assign the return value, if any
406+
if(loc->call_lhs().is_not_nil())
407+
{
408+
exprt equality_rhs = return_state;
409+
410+
/*
411+
auto &return_type = loc->call_lhs().type();
412+
auto rhs_evaluated =
413+
evaluate_expr(
414+
loc,
415+
return_state,
416+
symbol_exprt("return_value", return_type));
417+
418+
multi_ary_exprt designator(ID_designator, { loc->call_lhs() }, typet());
419+
420+
auto lhs = out_state_expr(source);
421+
422+
auto rhs = update_exprt(
423+
return_state,
424+
designator,
425+
rhs_evaluated);
426+
427+
// 'out state' equality
428+
constraints.push_back(equal_exprt(lhs, rhs));
429+
*/
430+
}
431+
else
432+
{
433+
// 'out state' equality
434+
dest << equal_exprt(out_state_expr(loc), return_state);
435+
}
436+
}
437+
else
438+
{
439+
// no function body -- do LHS assignment nondeterministically, if any
440+
if(loc->call_lhs().is_not_nil())
441+
{
442+
auto rhs = side_effect_expr_nondett(
443+
loc->call_lhs().type(), loc->source_location());
444+
dest << assignment_constraint(loc, loc->call_lhs(), std::move(rhs));
445+
}
446+
else
447+
{
448+
// This is a SKIP.
449+
dest << equal_exprt(out_state_expr(loc), in_state_expr(loc));
450+
}
451+
}
408452
}
409453
else
410454
{
411-
// 'out state' equality
412-
dest << equal_exprt(out_state_expr(loc), return_state);
455+
DATA_INVARIANT(
456+
false, "got function that's neither a symbol nor a function pointer");
413457
}
414458
}
415459
else if(loc->is_set_return_value())
@@ -433,7 +477,7 @@ void state_encoding(
433477
goto_functionst::entry_point());
434478
PRECONDITION(f_entry != goto_model.goto_functions.function_map.end());
435479

436-
state_encodingt{}(f_entry->second, dest);
480+
state_encodingt{}(goto_model.goto_functions, f_entry->second, dest);
437481
}
438482
else
439483
{
@@ -445,7 +489,7 @@ void state_encoding(
445489
if(f->second.body_available())
446490
{
447491
dest.annotation("function " + id2string(f->first));
448-
state_encodingt{}(f->second, dest);
492+
state_encodingt{}(goto_model.goto_functions, f->second, dest);
449493
}
450494
}
451495
}

0 commit comments

Comments
 (0)