Skip to content

Commit

Permalink
Maintain loop invariant annotation when converting do .. while
Browse files Browse the repository at this point in the history
With the changes in bbd9de4 we newly made do .. while converted
instructions subject to `optimize_guarded_gotos`, which previously
rewrote conditions without retaining annotations related to loop
invariants.

The included tests now show that the annotations are preserved, but
still fail for an unrelated bug in how do .. while loops are
instrumented.
  • Loading branch information
tautschnig committed Aug 19, 2024
1 parent b87d38a commit bfd5e66
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 2 deletions.
19 changes: 19 additions & 0 deletions regression/contracts-dfcc/loop_contracts_do_while/assigns.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
int global;

int harness(int argc)
{
global = 0;
argc = 1;
if(argc > 1)
{
do
__CPROVER_assigns(global)
{
global = 1;
}
while(0);
}
__CPROVER_assert(global == 0, "should be zero");

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
KNOWNBUG
assigns.c
--dfcc harness --apply-loop-contracts
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
--
This test checks that loop contracts work correctly on do/while loops.
24 changes: 24 additions & 0 deletions regression/contracts-dfcc/loop_contracts_do_while/side_effect.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
int global;

int foo()
{
return 0;
}

int harness(int argc)
{
global = 0;
argc = 1;
if(argc > 1)
{
do
__CPROVER_assigns(global)
{
global = 1;
}
while(foo());
}
__CPROVER_assert(global == 0, "should be zero");

return 0;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
KNOWNBUG
side_effect.c
--dfcc harness --apply-loop-contracts
^EXIT=0$
^SIGNAL=0$
^VERIFICATION SUCCESSFUL$
--
--
This test checks that loop contracts work correctly on do/while loops.
21 changes: 19 additions & 2 deletions src/ansi-c/goto-conversion/goto_convert.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,8 +432,25 @@ void goto_convertt::optimize_guarded_gotos(goto_programt &dest)
// cannot compare iterators, so compare target number instead
if(it->get_target()->target_number == it_z->target_number)
{
DATA_INVARIANT(
it->condition().find(ID_C_spec_assigns).is_nil() &&
it->condition().find(ID_C_spec_loop_invariant).is_nil() &&
it->condition().find(ID_C_spec_decreases).is_nil(),
"no loop invariant expected");
irept y_assigns = it_goto_y->condition().find(ID_C_spec_assigns);
irept y_loop_invariant =
it_goto_y->condition().find(ID_C_spec_loop_invariant);
irept y_decreases = it_goto_y->condition().find(ID_C_spec_decreases);

it->set_target(it_goto_y->get_target());
it->condition_nonconst() = boolean_negate(it->condition());
exprt updated_condition = boolean_negate(it->condition());
if(y_assigns.is_not_nil())
updated_condition.add(ID_C_spec_assigns).swap(y_assigns);
if(y_loop_invariant.is_not_nil())
updated_condition.add(ID_C_spec_loop_invariant).swap(y_loop_invariant);
if(y_decreases.is_not_nil())
updated_condition.add(ID_C_spec_decreases).swap(y_decreases);
it->condition_nonconst() = updated_condition;
it_goto_y->turn_into_skip();
}
}
Expand Down Expand Up @@ -1301,7 +1318,7 @@ void goto_convertt::convert_dowhile(
W->complete_goto(w);

// assigns_clause, loop invariant and decreases clause
convert_loop_contracts(code, y);
convert_loop_contracts(code, W);

dest.destructive_append(tmp_w);
dest.destructive_append(side_effects.side_effects);
Expand Down

0 comments on commit bfd5e66

Please sign in to comment.