@@ -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)
@@ -158,15 +164,6 @@ static void check_apply_invariants(
158
164
loop_end->set_condition (boolean_negate (loop_end->get_condition ()));
159
165
}
160
166
161
- void code_contractst::convert_to_goto (
162
- const codet &code,
163
- const irep_idt &mode,
164
- goto_programt &program)
165
- {
166
- goto_convertt converter (symbol_table, log .get_message_handler ());
167
- converter.goto_convert (code, program, mode);
168
- }
169
-
170
167
bool code_contractst::has_contract (const irep_idt fun_name)
171
168
{
172
169
const symbolt &function_symbol = ns.lookup (fun_name);
@@ -322,7 +319,7 @@ code_contractst::create_ensures_instruction(
322
319
323
320
// Create instructions corresponding to the ensures clause
324
321
goto_programt ensures_program;
325
- convert_to_goto (expression, mode, ensures_program );
322
+ converter. goto_convert (expression, ensures_program, mode );
326
323
327
324
// return a pair containing:
328
325
// 1. instructions corresponding to the ensures clause
@@ -424,10 +421,10 @@ bool code_contractst::apply_function_contract(
424
421
if (requires.is_not_nil ())
425
422
{
426
423
goto_programt assertion;
427
- convert_to_goto (
424
+ converter. goto_convert (
428
425
code_assertt (requires),
429
- symbol_table. lookup_ref (function). mode ,
430
- assertion );
426
+ assertion ,
427
+ symbol_table. lookup_ref (function). mode );
431
428
auto lines_to_iterate = assertion.instructions .size ();
432
429
goto_program.insert_before_swap (target, assertion);
433
430
std::advance (target, lines_to_iterate);
@@ -483,15 +480,21 @@ bool code_contractst::apply_function_contract(
483
480
}
484
481
485
482
void code_contractst::apply_loop_contract (
483
+ const irep_idt &function_name,
486
484
goto_functionst::goto_functiont &goto_function)
487
485
{
488
486
local_may_aliast local_may_alias (goto_function);
489
487
natural_loops_mutablet natural_loops (goto_function.body );
490
488
491
- // 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.
492
491
for (const auto &loop : natural_loops.loop_map )
493
492
check_apply_invariants (
494
- 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 );
495
498
}
496
499
497
500
const symbolt &code_contractst::new_tmp_symbol (
@@ -966,8 +969,8 @@ void code_contractst::add_contract_check(
966
969
replace (requires_cond);
967
970
968
971
goto_programt assumption;
969
- convert_to_goto (
970
- code_assumet (requires_cond), function_symbol.mode , assumption );
972
+ converter. goto_convert (
973
+ code_assumet (requires_cond), assumption, function_symbol.mode );
971
974
check.destructive_append (assumption);
972
975
}
973
976
@@ -1078,7 +1081,7 @@ bool code_contractst::enforce_contracts()
1078
1081
if (has_contract (goto_function.first ))
1079
1082
funs_to_enforce.insert (id2string (goto_function.first ));
1080
1083
else
1081
- apply_loop_contract (goto_function.second );
1084
+ apply_loop_contract (goto_function.first , goto_function. second );
1082
1085
}
1083
1086
return enforce_contracts (funs_to_enforce);
1084
1087
}
@@ -1098,7 +1101,7 @@ bool code_contractst::enforce_contracts(
1098
1101
<< messaget::eom;
1099
1102
continue ;
1100
1103
}
1101
- apply_loop_contract (goto_function->second );
1104
+ apply_loop_contract (goto_function->first , goto_function-> second );
1102
1105
1103
1106
if (!has_contract (fun))
1104
1107
{
0 commit comments