Skip to content

Commit 0b54050

Browse files
committed
Properly convert conditions into assertions and assumptions
Signed-off-by: Felipe R. Monteiro <felisous@amazon.com>
1 parent 8a117bc commit 0b54050

File tree

2 files changed

+41
-25
lines changed

2 files changed

+41
-25
lines changed

src/goto-instrument/code_contracts.cpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ Date: February 2016
1717

1818
#include <analyses/local_may_alias.h>
1919

20+
#include <goto-programs/goto_convert_class.h>
2021
#include <goto-programs/remove_skip.h>
2122

2223
#include <linking/static_lifetime_init.h>
@@ -157,6 +158,15 @@ static void check_apply_invariants(
157158
loop_end->set_condition(boolean_negate(loop_end->get_condition()));
158159
}
159160

161+
void code_contractst::convert_to_goto(
162+
const codet &code,
163+
const irep_idt &mode,
164+
goto_programt &program)
165+
{
166+
goto_convertt converter(symbol_table, log.get_message_handler());
167+
converter.goto_convert(code, program, mode);
168+
}
169+
160170
bool code_contractst::has_contract(const irep_idt fun_name)
161171
{
162172
const symbolt &function_symbol = ns.lookup(fun_name);
@@ -327,11 +337,14 @@ bool code_contractst::apply_function_contract(
327337
// Insert assertion of the precondition immediately before the call site.
328338
if(requires.is_not_nil())
329339
{
330-
goto_programt::instructiont a =
331-
goto_programt::make_assertion(requires, target->source_location);
332-
333-
goto_program.insert_before_swap(target, a);
334-
++target;
340+
goto_programt assertion;
341+
convert_to_goto(
342+
code_assertt(requires),
343+
symbol_table.lookup_ref(function).mode,
344+
assertion);
345+
auto lines_to_iterate = assertion.instructions.size();
346+
goto_program.insert_before_swap(target, assertion);
347+
std::advance(target, lines_to_iterate);
335348
}
336349

337350
// Create a series of non-deterministic assignments to havoc the variables
@@ -353,12 +366,16 @@ bool code_contractst::apply_function_contract(
353366
// function call with a SKIP statement.
354367
if(ensures.is_not_nil())
355368
{
356-
*target = goto_programt::make_assumption(ensures, target->source_location);
357-
}
358-
else
359-
{
360-
*target = goto_programt::make_skip();
369+
goto_programt assumption;
370+
convert_to_goto(
371+
code_assumet(ensures),
372+
symbol_table.lookup_ref(function).mode,
373+
assumption);
374+
auto lines_to_iterate = assumption.instructions.size();
375+
goto_program.insert_before_swap(target, assumption);
376+
std::advance(target, lines_to_iterate);
361377
}
378+
*target = goto_programt::make_skip();
362379

363380
// Add this function to the set of replaced functions.
364381
summarized.insert(function);
@@ -419,14 +436,6 @@ void code_contractst::instrument_assign_statement(
419436

420437
const exprt &lhs = instruction_iterator->get_assign().lhs();
421438

422-
if(
423-
lhs.id() == ID_symbol &&
424-
freely_assignable_symbols.find(to_symbol_expr(lhs).get_identifier()) !=
425-
freely_assignable_symbols.end())
426-
{
427-
return;
428-
}
429-
430439
goto_programt alias_assertion;
431440
alias_assertion.add(goto_programt::make_assertion(
432441
assigns_clause.alias_expression(lhs),
@@ -838,7 +847,6 @@ void code_contractst::add_contract_check(
838847
{
839848
PRECONDITION(!parameter.empty());
840849
const symbolt &parameter_symbol = ns.lookup(parameter);
841-
842850
symbol_exprt p = new_tmp_symbol(
843851
parameter_symbol.type,
844852
skip->source_location,
@@ -867,8 +875,10 @@ void code_contractst::add_contract_check(
867875
exprt requires_cond = requires;
868876
replace(requires_cond);
869877

870-
check.add(goto_programt::make_assumption(
871-
requires_cond, requires.source_location()));
878+
goto_programt assumption;
879+
convert_to_goto(
880+
code_assumet(requires_cond), function_symbol.mode, assumption);
881+
check.destructive_append(assumption);
872882
}
873883

874884
// ret=mangled_fun(parameter1, ...)
@@ -881,8 +891,10 @@ void code_contractst::add_contract_check(
881891
// assert(ensures)
882892
if(ensures.is_not_nil())
883893
{
884-
check.add(
885-
goto_programt::make_assertion(ensures_cond, ensures.source_location()));
894+
goto_programt assertion;
895+
convert_to_goto(
896+
code_assertt(ensures_cond), function_symbol.mode, assertion);
897+
check.destructive_append(assertion);
886898
}
887899

888900
if(code_type.return_type() != empty_typet())
@@ -921,8 +933,6 @@ bool code_contractst::replace_calls(
921933
{
922934
const code_function_callt &call = ins->get_function_call();
923935

924-
PRECONDITION(call.function().id() != ID_dereference);
925-
926936
if(call.function().id() != ID_symbol)
927937
continue;
928938

src/goto-instrument/code_contracts.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ class code_contractst
104104
/// \brief Enforce contract of a single function
105105
bool enforce_contract(const std::string &);
106106

107+
/// \brief Create goto instructions based on code and add them to program.
108+
void convert_to_goto(
109+
const codet &code,
110+
const irep_idt &mode,
111+
goto_programt &program);
112+
107113
/// Insert assertion statements into the goto program to ensure that
108114
/// assigned memory is within the assignable memory frame.
109115
bool add_pointer_checks(const std::string &);

0 commit comments

Comments
 (0)