@@ -17,6 +17,7 @@ Date: February 2016
17
17
18
18
#include < analyses/local_may_alias.h>
19
19
20
+ #include < goto-programs/goto_convert_class.h>
20
21
#include < goto-programs/remove_skip.h>
21
22
22
23
#include < linking/static_lifetime_init.h>
@@ -74,9 +75,11 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
74
75
75
76
static void check_apply_invariants (
76
77
goto_functionst::goto_functiont &goto_function,
78
+ goto_convertt &converter,
77
79
const local_may_aliast &local_may_alias,
78
80
const goto_programt::targett loop_head,
79
- const loopt &loop)
81
+ const loopt &loop,
82
+ const irep_idt &mode)
80
83
{
81
84
PRECONDITION (!loop.empty ());
82
85
@@ -94,16 +97,18 @@ static void check_apply_invariants(
94
97
if (invariant.is_nil ())
95
98
return ;
96
99
97
- // change H: loop; E: ...
100
+ // change
101
+ // H: loop;
102
+ // E: ...
98
103
// to
99
- // H: assert(invariant);
100
- // havoc;
101
- // assume(invariant);
102
- // if(guard) goto E:
103
- // loop;
104
- // assert(invariant);
105
- // assume(false);
106
- // E: ...
104
+ // H: assert(invariant);
105
+ // havoc;
106
+ // assume(invariant);
107
+ // if(guard) goto E:
108
+ // loop;
109
+ // assert(invariant);
110
+ // assume(false);
111
+ // E: ...
107
112
108
113
// find out what can get changed in the loop
109
114
modifiest modifies;
@@ -114,17 +119,20 @@ static void check_apply_invariants(
114
119
115
120
// assert the invariant
116
121
{
117
- goto_programt::targett a = havoc_code.add (
118
- goto_programt::make_assertion (invariant, loop_head->source_location ));
119
- a->source_location .set_comment (" Check loop invariant before entry" );
122
+ auto assertion = code_assertt (invariant);
123
+ assertion.add_source_location ().swap (loop_head->source_location );
124
+ converter.goto_convert (assertion, havoc_code, mode);
125
+ havoc_code.instructions .back ().source_location .set_comment (
126
+ " Check loop invariant before entry" );
120
127
}
121
128
122
129
// havoc variables being written to
123
130
build_havoc_code (loop_head, modifies, havoc_code);
124
131
125
132
// assume the invariant
126
- havoc_code.add (
127
- goto_programt::make_assumption (invariant, loop_head->source_location ));
133
+ auto assumption = code_assumet (invariant);
134
+ assumption.add_source_location ().swap (loop_head->source_location );
135
+ converter.goto_convert (assumption, havoc_code, mode);
128
136
129
137
// non-deterministically skip the loop if it is a do-while loop
130
138
if (!loop_head->is_goto ())
@@ -140,11 +148,14 @@ static void check_apply_invariants(
140
148
141
149
// assert the invariant at the end of the loop body
142
150
{
143
- goto_programt::instructiont a =
144
- goto_programt::make_assertion (invariant, loop_end->source_location );
145
- a.source_location .set_comment (" Check that loop invariant is preserved" );
146
- goto_function.body .insert_before_swap (loop_end, a);
147
- ++loop_end;
151
+ auto assertion = code_assertt (invariant);
152
+ assertion.add_source_location ().swap (loop_end->source_location );
153
+ converter.goto_convert (assertion, havoc_code, mode);
154
+ havoc_code.instructions .back ().source_location .set_comment (
155
+ " Check that loop invariant is preserved" );
156
+ auto offset = havoc_code.instructions .size ();
157
+ goto_function.body .insert_before_swap (loop_end, havoc_code);
158
+ std::advance (loop_end, offset);
148
159
}
149
160
150
161
// change the back edge into assume(false) or assume(guard)
@@ -359,15 +370,24 @@ bool code_contractst::apply_function_contract(
359
370
}
360
371
361
372
void code_contractst::apply_loop_contract (
373
+ const irep_idt &function_name,
362
374
goto_functionst::goto_functiont &goto_function)
363
375
{
364
376
local_may_aliast local_may_alias (goto_function);
365
377
natural_loops_mutablet natural_loops (goto_function.body );
366
378
379
+ // setup goto_convertt to convert C expressions to logic
380
+ goto_convertt converter (symbol_table, log.get_message_handler ());
381
+
367
382
// iterate over the (natural) loops in the function
368
383
for (const auto &loop : natural_loops.loop_map )
369
384
check_apply_invariants (
370
- goto_function, local_may_alias, loop.first , loop.second );
385
+ goto_function,
386
+ converter,
387
+ local_may_alias,
388
+ loop.first ,
389
+ loop.second ,
390
+ symbol_table.lookup_ref (function_name).mode );
371
391
}
372
392
373
393
const symbolt &code_contractst::new_tmp_symbol (
@@ -964,7 +984,7 @@ bool code_contractst::enforce_contracts()
964
984
if (has_contract (goto_function.first ))
965
985
funs_to_enforce.insert (id2string (goto_function.first ));
966
986
else
967
- apply_loop_contract (goto_function.second );
987
+ apply_loop_contract (goto_function.first , goto_function. second );
968
988
}
969
989
return enforce_contracts (funs_to_enforce);
970
990
}
@@ -984,7 +1004,7 @@ bool code_contractst::enforce_contracts(
984
1004
<< messaget::eom;
985
1005
continue ;
986
1006
}
987
- apply_loop_contract (goto_function->second );
1007
+ apply_loop_contract (goto_function->first , goto_function-> second );
988
1008
989
1009
if (!has_contract (fun))
990
1010
{
0 commit comments