Skip to content

Commit 847216c

Browse files
committed
CONTRACTS: Unwind loops after loop contract transformation
1 parent 70b7cf7 commit 847216c

File tree

4 files changed

+34
-2
lines changed

4 files changed

+34
-2
lines changed

regression/contracts/invar_assigns_empty/test.desc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ main.c
33
--apply-loop-contracts
44
^EXIT=0$
55
^SIGNAL=0$
6-
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7-
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
6+
^\[main.\d+\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main.\d+\] .* Check that loop invariant is preserved: SUCCESS$
88
^VERIFICATION SUCCESSFUL$
99
--
1010
--
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--apply-loop-contracts --unwind 1 --unwinding-assertions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main\.\d+\] .* Check loop invariant before entry: SUCCESS$
7+
^\[main\.\d+\] .* Check that loop invariant is preserved: SUCCESS$
8+
^\[main.assigns.\d+\] .* Check that s is assignable: SUCCESS$
9+
^\[main.assigns.\d+\] .* Check that r is assignable: SUCCESS$
10+
^\[main\.assertion\.\d+\] .* assertion r == 0: SUCCESS$
11+
^\[main\.assertion\.\d+\] .* assertion s == 1: SUCCESS$
12+
^VERIFICATION SUCCESSFUL$
13+
--
14+
This test checks that there is no loop after contract transforamtion.

src/goto-instrument/contracts/contracts.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ Date: February 2016
3636
#include <ansi-c/c_expr.h>
3737
#include <goto-instrument/havoc_utils.h>
3838
#include <goto-instrument/nondet_static.h>
39+
#include <goto-instrument/unwind.h>
40+
#include <goto-instrument/unwindset.h>
3941
#include <langapi/language_util.h>
4042

4143
#include "cfg_info.h"
@@ -1016,6 +1018,13 @@ void code_contractst::apply_loop_contract(
10161018
goto_functions.update();
10171019
natural_loops_mutablet updated_loops(goto_function.body);
10181020

1021+
// We will unwind all transformed loops twice. Store the names of
1022+
// to-unwind-loops here and perform the unwinding after transformation done.
1023+
std::string to_unwind = id2string(function_name) + "." +
1024+
std::to_string(loop_node.end_target->loop_number) +
1025+
":2";
1026+
loop_names.push_back(to_unwind);
1027+
10191028
check_apply_loop_contracts(
10201029
function_name,
10211030
goto_function,
@@ -1459,6 +1468,12 @@ void code_contractst::apply_loop_contracts(
14591468
"of static/global variables."
14601469
<< messaget::eom;
14611470
nondet_static(goto_model, to_exclude_from_nondet_init);
1471+
1472+
// unwind all transformed loops twice.
1473+
unwindsett unwindset{goto_model};
1474+
unwindset.parse_unwindset(loop_names, log.get_message_handler());
1475+
goto_unwindt goto_unwind;
1476+
goto_unwind(goto_model, unwindset, goto_unwindt::unwind_strategyt::ASSUME);
14621477
}
14631478

14641479
void code_contractst::enforce_contracts(

src/goto-instrument/contracts/contracts.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,9 @@ class code_contractst
141141

142142
std::unordered_set<irep_idt> summarized;
143143

144+
/// Name of loops we are going to unwind.
145+
std::list<std::string> loop_names;
146+
144147
public:
145148
/// Translates a function_pointer_obeys_contract_exprt into an assertion
146149
/// ```

0 commit comments

Comments
 (0)