Skip to content

Commit 2bc9b22

Browse files
committed
Maintain loop invariant annotation when converting do .. while
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.
1 parent 89a0470 commit 2bc9b22

File tree

8 files changed

+84
-5
lines changed

8 files changed

+84
-5
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
int global;
2+
3+
int main()
4+
{
5+
global = 0;
6+
int argc = 1;
7+
if(argc > 1)
8+
{
9+
do
10+
__CPROVER_assigns(global)
11+
{
12+
global = 1;
13+
}
14+
while(0);
15+
}
16+
__CPROVER_assert(global == 0, "should be zero");
17+
18+
return 0;
19+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
KNOWNBUG
2+
assigns.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that loop contracts work correctly on do/while loops.

regression/contracts-dfcc/loop_contracts_do_while/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ int main()
55
int x = 0;
66

77
do
8-
__CPROVER_loop_invariant(0 <= x && x <= 10)
8+
__CPROVER_loop_invariant(0 <= x && x < 10)
99
{
1010
x++;
1111
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
int global;
2+
3+
int foo()
4+
{
5+
return 0;
6+
}
7+
8+
int main()
9+
{
10+
global = 0;
11+
int argc = 1;
12+
if(argc > 1)
13+
{
14+
do
15+
__CPROVER_assigns(global)
16+
{
17+
global = 1;
18+
}
19+
while(foo());
20+
}
21+
__CPROVER_assert(global == 0, "should be zero");
22+
23+
return 0;
24+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
KNOWNBUG
2+
side_effect.c
3+
--dfcc main --apply-loop-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that loop contracts work correctly on do/while loops.

regression/contracts-dfcc/loop_contracts_do_while/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
KNOWNBUG
1+
CORE dfcc-only
22
main.c
33
--dfcc main --apply-loop-contracts
44
^EXIT=0$
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
CORE
1+
KNOWNBUG
22
main.c
33
--apply-loop-contracts
44
^EXIT=0$
@@ -7,3 +7,4 @@ main.c
77
--
88
--
99
This test checks that loop contracts work correctly on do/while loops.
10+
Fails because contracts are not yet supported on do while loops.

src/ansi-c/goto-conversion/goto_convert.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -432,8 +432,25 @@ void goto_convertt::optimize_guarded_gotos(goto_programt &dest)
432432
// cannot compare iterators, so compare target number instead
433433
if(it->get_target()->target_number == it_z->target_number)
434434
{
435+
DATA_INVARIANT(
436+
it->condition().find(ID_C_spec_assigns).is_nil() &&
437+
it->condition().find(ID_C_spec_loop_invariant).is_nil() &&
438+
it->condition().find(ID_C_spec_decreases).is_nil(),
439+
"no loop invariant expected");
440+
irept y_assigns = it_goto_y->condition().find(ID_C_spec_assigns);
441+
irept y_loop_invariant =
442+
it_goto_y->condition().find(ID_C_spec_loop_invariant);
443+
irept y_decreases = it_goto_y->condition().find(ID_C_spec_decreases);
444+
435445
it->set_target(it_goto_y->get_target());
436-
it->condition_nonconst() = boolean_negate(it->condition());
446+
exprt updated_condition = boolean_negate(it->condition());
447+
if(y_assigns.is_not_nil())
448+
updated_condition.add(ID_C_spec_assigns).swap(y_assigns);
449+
if(y_loop_invariant.is_not_nil())
450+
updated_condition.add(ID_C_spec_loop_invariant).swap(y_loop_invariant);
451+
if(y_decreases.is_not_nil())
452+
updated_condition.add(ID_C_spec_decreases).swap(y_decreases);
453+
it->condition_nonconst() = updated_condition;
437454
it_goto_y->turn_into_skip();
438455
}
439456
}
@@ -1301,7 +1318,7 @@ void goto_convertt::convert_dowhile(
13011318
W->complete_goto(w);
13021319

13031320
// assigns_clause, loop invariant and decreases clause
1304-
convert_loop_contracts(code, y);
1321+
convert_loop_contracts(code, W);
13051322

13061323
dest.destructive_append(tmp_w);
13071324
dest.destructive_append(side_effects.side_effects);

0 commit comments

Comments
 (0)