@@ -38,15 +38,46 @@ Date: February 2016
3838// This is used in the implementation of multidimensional decreases clauses.
3939static exprt create_lexicographic_less_than (
4040 const std::vector<symbol_exprt> &lhs,
41- const std::vector<symbol_exprt> &rhs);
42-
43- exprt get_size (const typet &type, const namespacet &ns, messaget &log)
41+ const std::vector<symbol_exprt> &rhs)
4442{
45- auto size_of_opt = size_of_expr (type, ns);
46- CHECK_RETURN (size_of_opt.has_value ());
47- exprt result = size_of_opt.value ();
48- result.add (ID_C_c_sizeof_type) = type;
49- return result;
43+ PRECONDITION (lhs.size () == rhs.size ());
44+
45+ if (lhs.empty ())
46+ {
47+ return false_exprt ();
48+ }
49+
50+ // Store conjunctions of equalities.
51+ // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
52+ // l2, l3>.
53+ // Then this vector stores <s1 == l1, s1 == l1 && s2 == l2,
54+ // s1 == l1 && s2 == l2 && s3 == l3>.
55+ // In fact, the last element is unnecessary, so we do not create it.
56+ exprt::operandst equality_conjunctions (lhs.size ());
57+ equality_conjunctions[0 ] = binary_relation_exprt (lhs[0 ], ID_equal, rhs[0 ]);
58+ for (unsigned int i = 1 ; i < equality_conjunctions.size () - 1 ; i++)
59+ {
60+ binary_relation_exprt component_i_equality{lhs[i], ID_equal, rhs[i]};
61+ equality_conjunctions[i] =
62+ and_exprt (equality_conjunctions[i - 1 ], component_i_equality);
63+ }
64+
65+ // Store inequalities between the i-th components of the input vectors
66+ // (i.e. lhs and rhs).
67+ // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
68+ // l2, l3>.
69+ // Then this vector stores <s1 < l1, s1 == l1 && s2 < l2, s1 == l1 &&
70+ // s2 == l2 && s3 < l3>.
71+ exprt::operandst lexicographic_individual_comparisons (lhs.size ());
72+ lexicographic_individual_comparisons[0 ] =
73+ binary_relation_exprt (lhs[0 ], ID_lt, rhs[0 ]);
74+ for (unsigned int i = 1 ; i < lexicographic_individual_comparisons.size (); i++)
75+ {
76+ binary_relation_exprt component_i_less_than{lhs[i], ID_lt, rhs[i]};
77+ lexicographic_individual_comparisons[i] =
78+ and_exprt (equality_conjunctions[i - 1 ], component_i_less_than);
79+ }
80+ return disjunction (lexicographic_individual_comparisons);
5081}
5182
5283void code_contractst::check_apply_loop_contracts (
@@ -67,10 +98,11 @@ void code_contractst::check_apply_loop_contracts(
6798 loop_end = t;
6899
69100 // see whether we have an invariant and a decreases clause
70- exprt invariant = static_cast <const exprt &>(
101+ auto invariant = static_cast <const exprt &>(
71102 loop_end->get_condition ().find (ID_C_spec_loop_invariant));
72- exprt decreases_clause = static_cast <const exprt &>(
103+ auto decreases_clause = static_cast <const exprt &>(
73104 loop_end->get_condition ().find (ID_C_spec_decreases));
105+
74106 if (invariant.is_nil ())
75107 {
76108 if (decreases_clause.is_nil ())
@@ -92,12 +124,12 @@ void code_contractst::check_apply_loop_contracts(
92124 }
93125
94126 // Vector representing a (possibly multidimensional) decreases clause
95- const auto decreases_clause_vector = decreases_clause.operands ();
127+ const auto &decreases_clause_exprs = decreases_clause.operands ();
96128
97129 // Temporary variables for storing the multidimensional decreases clause
98130 // at the start of and end of a loop body
99- std::vector<symbol_exprt> old_temporary_variables ;
100- std::vector<symbol_exprt> new_temporary_variables ;
131+ std::vector<symbol_exprt> old_decreases_vars ;
132+ std::vector<symbol_exprt> new_decreases_vars ;
101133
102134 // change
103135 // H: loop;
@@ -159,10 +191,10 @@ void code_contractst::check_apply_loop_contracts(
159191 // decreases clause's value before and after the loop
160192 for (const auto &clause : decreases_clause.operands ())
161193 {
162- old_temporary_variables .push_back (
194+ old_decreases_vars .push_back (
163195 new_tmp_symbol (clause.type (), loop_head->source_location , mode)
164196 .symbol_expr ());
165- new_temporary_variables .push_back (
197+ new_decreases_vars .push_back (
166198 new_tmp_symbol (clause.type (), loop_head->source_location , mode)
167199 .symbol_expr ());
168200 }
@@ -171,18 +203,18 @@ void code_contractst::check_apply_loop_contracts(
171203 {
172204 // Generate: declarations of the temporary variables that stores the
173205 // multidimensional decreases clause's value before the loop
174- for (const auto &old_temp_var : old_temporary_variables )
206+ for (const auto &old_temp_var : old_decreases_vars )
175207 {
176208 havoc_code.add (
177209 goto_programt::make_decl (old_temp_var, loop_head->source_location ));
178210 }
179211
180212 // Generate: assignments to store the multidimensional decreases clause's
181213 // value before the loop
182- for (size_t i = 0 ; i < old_temporary_variables .size (); i++)
214+ for (size_t i = 0 ; i < old_decreases_vars .size (); i++)
183215 {
184- code_assignt old_decreases_assignment{old_temporary_variables [i],
185- decreases_clause_vector [i]};
216+ code_assignt old_decreases_assignment{old_decreases_vars [i],
217+ decreases_clause_exprs [i]};
186218 old_decreases_assignment.add_source_location () =
187219 loop_head->source_location ;
188220 converter.goto_convert (old_decreases_assignment, havoc_code, mode);
@@ -217,18 +249,18 @@ void code_contractst::check_apply_loop_contracts(
217249 // Generate: declarations of temporary variables that stores the
218250 // multidimensional decreases clause's value after one arbitrary iteration
219251 // of the loop
220- for (const auto &new_temp_var : new_temporary_variables )
252+ for (const auto &new_temp_var : new_decreases_vars )
221253 {
222254 havoc_code.add (
223255 goto_programt::make_decl (new_temp_var, loop_head->source_location ));
224256 }
225257
226258 // Generate: assignments to store the multidimensional decreases clause's
227259 // value after one iteration of the loop
228- for (size_t i = 0 ; i < new_temporary_variables .size (); i++)
260+ for (size_t i = 0 ; i < new_decreases_vars .size (); i++)
229261 {
230- code_assignt new_decreases_assignment{new_temporary_variables [i],
231- decreases_clause_vector [i]};
262+ code_assignt new_decreases_assignment{new_decreases_vars [i],
263+ decreases_clause_exprs [i]};
232264 new_decreases_assignment.add_source_location () =
233265 loop_head->source_location ;
234266 converter.goto_convert (new_decreases_assignment, havoc_code, mode);
@@ -238,20 +270,20 @@ void code_contractst::check_apply_loop_contracts(
238270 // after the loop is smaller than the value before the loop.
239271 // Here, we use the lexicographic order.
240272 code_assertt monotonic_decreasing_assertion{create_lexicographic_less_than (
241- new_temporary_variables, old_temporary_variables )};
273+ new_decreases_vars, old_decreases_vars )};
242274 monotonic_decreasing_assertion.add_source_location () =
243275 loop_head->source_location ;
244276 converter.goto_convert (monotonic_decreasing_assertion, havoc_code, mode);
245277 havoc_code.instructions .back ().source_location .set_comment (
246278 " Check decreases clause on loop iteration" );
247279
248280 // Discard the temporary variables that store decreases clause's value
249- for (size_t i = 0 ; i < old_temporary_variables .size (); i++)
281+ for (size_t i = 0 ; i < old_decreases_vars .size (); i++)
250282 {
251283 havoc_code.add (goto_programt::make_dead (
252- old_temporary_variables [i], loop_head->source_location ));
284+ old_decreases_vars [i], loop_head->source_location ));
253285 havoc_code.add (goto_programt::make_dead (
254- new_temporary_variables [i], loop_head->source_location ));
286+ new_decreases_vars [i], loop_head->source_location ));
255287 }
256288 }
257289
@@ -268,52 +300,6 @@ void code_contractst::check_apply_loop_contracts(
268300 loop_end->set_condition (boolean_negate (loop_end->get_condition ()));
269301}
270302
271- // Create a lexicographic less-than relation between two tuples of variables.
272- // This is used in the implementation of multidimensional decreases clauses.
273- static exprt create_lexicographic_less_than (
274- const std::vector<symbol_exprt> &lhs,
275- const std::vector<symbol_exprt> &rhs)
276- {
277- PRECONDITION (lhs.size () == rhs.size ());
278-
279- if (lhs.empty ())
280- {
281- return false_exprt ();
282- }
283-
284- // Store conjunctions of equalities.
285- // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
286- // l2, l3>.
287- // Then this vector stores <s1 == l1, s1 == l1 && s2 == l2,
288- // s1 == l1 && s2 == l2 && s3 == l3>.
289- // In fact, the last element is unnecessary, so we do not create it.
290- exprt::operandst equality_conjunctions (lhs.size ());
291- equality_conjunctions[0 ] = binary_relation_exprt (lhs[0 ], ID_equal, rhs[0 ]);
292- for (unsigned int i = 1 ; i < equality_conjunctions.size () - 1 ; i++)
293- {
294- binary_relation_exprt component_i_equality{lhs[i], ID_equal, rhs[i]};
295- equality_conjunctions[i] =
296- and_exprt (equality_conjunctions[i - 1 ], component_i_equality);
297- }
298-
299- // Store inequalities between the i-th components of the input vectors
300- // (i.e. lhs and rhs).
301- // For example, suppose that the two input vectors are <s1, s2, s3> and <l1,
302- // l2, l3>.
303- // Then this vector stores <s1 < l1, s1 == l1 && s2 < l2, s1 == l1 &&
304- // s2 == l2 && s3 < l3>.
305- exprt::operandst lexicographic_individual_comparisons (lhs.size ());
306- lexicographic_individual_comparisons[0 ] =
307- binary_relation_exprt (lhs[0 ], ID_lt, rhs[0 ]);
308- for (unsigned int i = 1 ; i < lexicographic_individual_comparisons.size (); i++)
309- {
310- binary_relation_exprt component_i_less_than{lhs[i], ID_lt, rhs[i]};
311- lexicographic_individual_comparisons[i] =
312- and_exprt (equality_conjunctions[i - 1 ], component_i_less_than);
313- }
314- return disjunction (lexicographic_individual_comparisons);
315- }
316-
317303bool code_contractst::has_contract (const irep_idt fun_name)
318304{
319305 const symbolt &function_symbol = ns.lookup (fun_name);
0 commit comments