Skip to content

Commit 2bef701

Browse files
authored
Merge pull request #8417 from tautschnig/fix-do-while-loop-invariant
Maintain loop invariant annotation when converting do .. while
2 parents 89a0470 + 6009066 commit 2bef701

File tree

9 files changed

+85
-6
lines changed

9 files changed

+85
-6
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+
CORE dfcc-only
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+
CORE dfcc-only
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);

src/goto-instrument/contracts/utils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ void insert_before_and_update_jumps(
250250
const auto new_target = destination.insert_before(target, i);
251251
for(auto it : target->incoming_edges)
252252
{
253-
if(it->is_goto())
253+
if(it->is_goto() && it->get_target() == target)
254254
it->set_target(new_target);
255255
}
256256
}

0 commit comments

Comments
 (0)