@@ -24,73 +24,21 @@ Date: February 2016
24
24
25
25
#include < goto-programs/remove_skip.h>
26
26
27
+ #include < langapi/language_util.h>
28
+
27
29
#include < util/c_types.h>
28
30
#include < util/expr_util.h>
29
31
#include < util/fresh_symbol.h>
30
32
#include < util/mathematical_expr.h>
31
33
#include < util/mathematical_types.h>
32
34
#include < util/message.h>
33
35
#include < util/pointer_offset_size.h>
36
+ #include < util/pointer_predicates.h>
34
37
#include < util/replace_symbol.h>
35
38
36
39
#include " assigns.h"
37
40
#include " memory_predicates.h"
38
-
39
- // Create a lexicographic less-than relation between two tuples of variables.
40
- // This is used in the implementation of multidimensional decreases clauses.
41
- static exprt create_lexicographic_less_than (
42
- const std::vector<symbol_exprt> &lhs,
43
- const std::vector<symbol_exprt> &rhs)
44
- {
45
- PRECONDITION (lhs.size () == rhs.size ());
46
-
47
- if (lhs.empty ())
48
- {
49
- return false_exprt ();
50
- }
51
-
52
- // Store conjunctions of equalities.
53
- // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
54
- // l2, l3>.
55
- // Then this vector stores <s1 == l1, s1 == l1 && s2 == l2,
56
- // s1 == l1 && s2 == l2 && s3 == l3>.
57
- // In fact, the last element is unnecessary, so we do not create it.
58
- exprt::operandst equality_conjunctions (lhs.size ());
59
- equality_conjunctions[0 ] = binary_relation_exprt (lhs[0 ], ID_equal, rhs[0 ]);
60
- for (size_t i = 1 ; i < equality_conjunctions.size () - 1 ; i++)
61
- {
62
- binary_relation_exprt component_i_equality{lhs[i], ID_equal, rhs[i]};
63
- equality_conjunctions[i] =
64
- and_exprt (equality_conjunctions[i - 1 ], component_i_equality);
65
- }
66
-
67
- // Store inequalities between the i-th components of the input vectors
68
- // (i.e. lhs and rhs).
69
- // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
70
- // l2, l3>.
71
- // Then this vector stores <s1 < l1, s1 == l1 && s2 < l2, s1 == l1 &&
72
- // s2 == l2 && s3 < l3>.
73
- exprt::operandst lexicographic_individual_comparisons (lhs.size ());
74
- lexicographic_individual_comparisons[0 ] =
75
- binary_relation_exprt (lhs[0 ], ID_lt, rhs[0 ]);
76
- for (size_t i = 1 ; i < lexicographic_individual_comparisons.size (); i++)
77
- {
78
- binary_relation_exprt component_i_less_than{lhs[i], ID_lt, rhs[i]};
79
- lexicographic_individual_comparisons[i] =
80
- and_exprt (equality_conjunctions[i - 1 ], component_i_less_than);
81
- }
82
- return disjunction (lexicographic_individual_comparisons);
83
- }
84
-
85
- static void insert_before_swap_and_advance (
86
- goto_programt &program,
87
- goto_programt::targett &target,
88
- goto_programt &payload)
89
- {
90
- const auto offset = payload.instructions .size ();
91
- program.insert_before_swap (target, payload);
92
- std::advance (target, offset);
93
- }
41
+ #include " utils.h"
94
42
95
43
void code_contractst::check_apply_loop_contracts (
96
44
goto_functionst::goto_functiont &goto_function,
@@ -203,7 +151,8 @@ void code_contractst::check_apply_loop_contracts(
203
151
}
204
152
205
153
// havoc the variables that may be modified
206
- append_havoc_code (loop_head->source_location , modifies, havoc_code);
154
+ havoc_if_validt havoc_gen (modifies, ns);
155
+ havoc_gen.append_full_havoc_code (loop_head->source_location , havoc_code);
207
156
208
157
// Generate: assume(invariant) just after havocing
209
158
// We use a block scope to create a temporary assumption,
@@ -289,7 +238,8 @@ void code_contractst::check_apply_loop_contracts(
289
238
// after the loop is smaller than the value before the loop.
290
239
// Here, we use the lexicographic order.
291
240
code_assertt monotonic_decreasing_assertion{
292
- create_lexicographic_less_than (new_decreases_vars, old_decreases_vars)};
241
+ generate_lexicographic_less_than_check (
242
+ new_decreases_vars, old_decreases_vars)};
293
243
monotonic_decreasing_assertion.add_source_location () =
294
244
loop_head->source_location ;
295
245
converter.goto_convert (monotonic_decreasing_assertion, havoc_code, mode);
@@ -418,6 +368,11 @@ void code_contractst::replace_history_parameter(
418
368
419
369
if (it == parameter2history.end ())
420
370
{
371
+ // 0. Create a skip target to jump to, if the parameter is invalid
372
+ goto_programt skip_program;
373
+ const auto skip_target =
374
+ skip_program.add (goto_programt::make_skip (location));
375
+
421
376
// 1. Create a temporary symbol expression that represents the
422
377
// history variable
423
378
symbol_exprt tmp_symbol =
@@ -428,14 +383,23 @@ void code_contractst::replace_history_parameter(
428
383
parameter2history[parameter] = tmp_symbol;
429
384
430
385
// 3. Add the required instructions to the instructions list
431
- // 3.1 Declare the newly created temporary variable
386
+ // 3.1. Declare the newly created temporary variable
432
387
history.add (goto_programt::make_decl (tmp_symbol, location));
433
388
434
- // 3.2 Add an assignment such that the value pointed to by the new
389
+ // 3.2. Skip storing the history if the expression is invalid
390
+ history.add (goto_programt::make_goto (
391
+ skip_target,
392
+ not_exprt{all_dereferences_are_valid (parameter, ns)},
393
+ location));
394
+
395
+ // 3.3. Add an assignment such that the value pointed to by the new
435
396
// temporary variable is equal to the value of the corresponding
436
397
// parameter
437
398
history.add (
438
399
goto_programt::make_assignment (tmp_symbol, parameter, location));
400
+
401
+ // 3.4. Add a skip target
402
+ history.destructive_append (skip_program);
439
403
}
440
404
441
405
expr = parameter2history[parameter];
0 commit comments