@@ -24,73 +24,21 @@ Date: February 2016
2424
2525#include < goto-programs/remove_skip.h>
2626
27+ #include < langapi/language_util.h>
28+
2729#include < util/c_types.h>
2830#include < util/expr_util.h>
2931#include < util/fresh_symbol.h>
3032#include < util/mathematical_expr.h>
3133#include < util/mathematical_types.h>
3234#include < util/message.h>
3335#include < util/pointer_offset_size.h>
36+ #include < util/pointer_predicates.h>
3437#include < util/replace_symbol.h>
3538
3639#include " assigns.h"
3740#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"
9442
9543void code_contractst::check_apply_loop_contracts (
9644 goto_functionst::goto_functiont &goto_function,
@@ -203,7 +151,8 @@ void code_contractst::check_apply_loop_contracts(
203151 }
204152
205153 // 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);
207156
208157 // Generate: assume(invariant) just after havocing
209158 // We use a block scope to create a temporary assumption,
@@ -289,7 +238,8 @@ void code_contractst::check_apply_loop_contracts(
289238 // after the loop is smaller than the value before the loop.
290239 // Here, we use the lexicographic order.
291240 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)};
293243 monotonic_decreasing_assertion.add_source_location () =
294244 loop_head->source_location ;
295245 converter.goto_convert (monotonic_decreasing_assertion, havoc_code, mode);
@@ -418,6 +368,11 @@ void code_contractst::replace_history_parameter(
418368
419369 if (it == parameter2history.end ())
420370 {
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+
421376 // 1. Create a temporary symbol expression that represents the
422377 // history variable
423378 symbol_exprt tmp_symbol =
@@ -428,14 +383,23 @@ void code_contractst::replace_history_parameter(
428383 parameter2history[parameter] = tmp_symbol;
429384
430385 // 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
432387 history.add (goto_programt::make_decl (tmp_symbol, location));
433388
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
435396 // temporary variable is equal to the value of the corresponding
436397 // parameter
437398 history.add (
438399 goto_programt::make_assignment (tmp_symbol, parameter, location));
400+
401+ // 3.4. Add a skip target
402+ history.destructive_append (skip_program);
439403 }
440404
441405 expr = parameter2history[parameter];
0 commit comments