@@ -20,7 +20,6 @@ Date: February 2016
20
20
21
21
#include < ansi-c/c_expr.h>
22
22
23
- #include < goto-programs/goto_convert_class.h>
24
23
#include < goto-programs/remove_skip.h>
25
24
26
25
#include < util/arith_tools.h>
@@ -34,8 +33,6 @@ Date: February 2016
34
33
#include < util/pointer_predicates.h>
35
34
#include < util/replace_symbol.h>
36
35
37
- #include " loop_utils.h"
38
-
39
36
// / Predicate to be used with the exprt::visit() function. The function
40
37
// / found_return_value() will return `true` iff this predicate is called on an
41
38
// / expr that contains `__CPROVER_return_value`.
@@ -74,11 +71,12 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
74
71
return result;
75
72
}
76
73
77
- static void check_apply_invariants (
74
+ void code_contractst:: check_apply_invariants (
78
75
goto_functionst::goto_functiont &goto_function,
79
76
const local_may_aliast &local_may_alias,
80
77
const goto_programt::targett loop_head,
81
- const loopt &loop)
78
+ const loopt &loop,
79
+ const irep_idt &mode)
82
80
{
83
81
PRECONDITION (!loop.empty ());
84
82
@@ -96,16 +94,18 @@ static void check_apply_invariants(
96
94
if (invariant.is_nil ())
97
95
return ;
98
96
99
- // change H: loop; E: ...
97
+ // change
98
+ // H: loop;
99
+ // E: ...
100
100
// to
101
- // H: assert(invariant);
102
- // havoc;
103
- // assume(invariant);
104
- // if(guard) goto E:
105
- // loop;
106
- // assert(invariant);
107
- // assume(false);
108
- // E: ...
101
+ // H: assert(invariant);
102
+ // havoc;
103
+ // assume(invariant);
104
+ // if(guard) goto E:
105
+ // loop;
106
+ // assert(invariant);
107
+ // assume(false);
108
+ // E: ...
109
109
110
110
// find out what can get changed in the loop
111
111
modifiest modifies;
@@ -116,17 +116,20 @@ static void check_apply_invariants(
116
116
117
117
// assert the invariant
118
118
{
119
- goto_programt::targett a = havoc_code.add (
120
- goto_programt::make_assertion (invariant, loop_head->source_location ));
121
- a->source_location .set_comment (" Check loop invariant before entry" );
119
+ code_assertt assertion{invariant};
120
+ assertion.add_source_location () = loop_head->source_location ;
121
+ converter.goto_convert (assertion, havoc_code, mode);
122
+ havoc_code.instructions .back ().source_location .set_comment (
123
+ " Check loop invariant before entry" );
122
124
}
123
125
124
126
// havoc variables being written to
125
127
build_havoc_code (loop_head, modifies, havoc_code);
126
128
127
129
// assume the invariant
128
- havoc_code.add (
129
- goto_programt::make_assumption (invariant, loop_head->source_location ));
130
+ code_assumet assumption{invariant};
131
+ assumption.add_source_location () = loop_head->source_location ;
132
+ converter.goto_convert (assumption, havoc_code, mode);
130
133
131
134
// non-deterministically skip the loop if it is a do-while loop
132
135
if (!loop_head->is_goto ())
@@ -142,11 +145,14 @@ static void check_apply_invariants(
142
145
143
146
// assert the invariant at the end of the loop body
144
147
{
145
- goto_programt::instructiont a =
146
- goto_programt::make_assertion (invariant, loop_end->source_location );
147
- a.source_location .set_comment (" Check that loop invariant is preserved" );
148
- goto_function.body .insert_before_swap (loop_end, a);
149
- ++loop_end;
148
+ code_assertt assertion{invariant};
149
+ assertion.add_source_location () = loop_end->source_location ;
150
+ converter.goto_convert (assertion, havoc_code, mode);
151
+ havoc_code.instructions .back ().source_location .set_comment (
152
+ " Check that loop invariant is preserved" );
153
+ auto offset = havoc_code.instructions .size ();
154
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
155
+ std::advance (loop_end, offset);
150
156
}
151
157
152
158
// change the back edge into assume(false) or assume(guard)
@@ -474,15 +480,21 @@ bool code_contractst::apply_function_contract(
474
480
}
475
481
476
482
void code_contractst::apply_loop_contract (
483
+ const irep_idt &function_name,
477
484
goto_functionst::goto_functiont &goto_function)
478
485
{
479
486
local_may_aliast local_may_alias (goto_function);
480
487
natural_loops_mutablet natural_loops (goto_function.body );
481
488
482
- // iterate over the (natural) loops in the function
489
+ // Iterate over the (natural) loops in the function,
490
+ // and apply any invariant annotations that we find.
483
491
for (const auto &loop : natural_loops.loop_map )
484
492
check_apply_invariants (
485
- goto_function, local_may_alias, loop.first , loop.second );
493
+ goto_function,
494
+ local_may_alias,
495
+ loop.first ,
496
+ loop.second ,
497
+ symbol_table.lookup_ref (function_name).mode );
486
498
}
487
499
488
500
const symbolt &code_contractst::new_tmp_symbol (
@@ -1069,7 +1081,7 @@ bool code_contractst::enforce_contracts()
1069
1081
if (has_contract (goto_function.first ))
1070
1082
funs_to_enforce.insert (id2string (goto_function.first ));
1071
1083
else
1072
- apply_loop_contract (goto_function.second );
1084
+ apply_loop_contract (goto_function.first , goto_function. second );
1073
1085
}
1074
1086
return enforce_contracts (funs_to_enforce);
1075
1087
}
@@ -1089,7 +1101,7 @@ bool code_contractst::enforce_contracts(
1089
1101
<< messaget::eom;
1090
1102
continue ;
1091
1103
}
1092
- apply_loop_contract (goto_function->second );
1104
+ apply_loop_contract (goto_function->first , goto_function-> second );
1093
1105
1094
1106
if (!has_contract (fun))
1095
1107
{
0 commit comments