File tree Expand file tree Collapse file tree 9 files changed +95
-2
lines changed
loop_assigns_inference-01
loop_assigns_inference-02
loop_assigns_inference-03
src/goto-instrument/contracts Expand file tree Collapse file tree 9 files changed +95
-2
lines changed File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change 1+ #include <stdlib.h>
2+
3+ #define SIZE 8
4+
5+ void main ()
6+ {
7+ int * b = malloc (SIZE * sizeof (int ));
8+ for (unsigned i = 0 ; i < SIZE ; i ++ )
9+ // clang-format off
10+ __CPROVER_loop_invariant (i <= SIZE )
11+ // clang-format on
12+ {
13+ b [i ] = 1 ;
14+ }
15+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --apply-loop-contracts
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.\d+\] .* Check loop invariant before entry: SUCCESS$
7+ ^\[main.\d+\] .* Check that loop invariant is preserved: SUCCESS$
8+ ^\[main.assigns.\d+\] .* Check that i is assignable: SUCCESS$
9+ ^\[main.assigns.\d+\] .* Check that b\[(.*)i\] is assignable: SUCCESS$
10+ ^VERIFICATION SUCCESSFUL$
11+ --
12+ --
13+ This test checks assigns clauses (i, __CPROVER_POINTER_OBJECT(b)) is inferred,
14+ and widened correctly.
Original file line number Diff line number Diff line change 1+ #include <stdlib.h>
2+
3+ #define SIZE 8
4+
5+ void main ()
6+ {
7+ int b [SIZE ];
8+ for (unsigned i = 0 ; i < SIZE ; i ++ )
9+ // clang-format off
10+ __CPROVER_loop_invariant (i <= SIZE )
11+ // clang-format on
12+ {
13+ b [i ] = 1 ;
14+ }
15+ }
Original file line number Diff line number Diff line change 1+ CORE
2+ main.c
3+ --apply-loop-contracts
4+ ^EXIT=0$
5+ ^SIGNAL=0$
6+ ^\[main.\d+\] .* Check loop invariant before entry: SUCCESS$
7+ ^\[main.\d+\] .* Check that loop invariant is preserved: SUCCESS$
8+ ^\[main.assigns.\d+\] .* Check that i is assignable: SUCCESS$
9+ ^\[main.assigns.\d+\] .* Check that b\[(.*)i\] is assignable: SUCCESS$
10+ ^VERIFICATION SUCCESSFUL$
11+ --
12+ --
13+ This test checks assigns clauses (i, __CPROVER_POINTER_OBJECT(b)) is inferred,
14+ and widened correctly.
Original file line number Diff line number Diff line change @@ -208,12 +208,14 @@ void code_contractst::check_apply_loop_contracts(
208208 try
209209 {
210210 get_assigns (local_may_alias, loop, to_havoc);
211- // TODO: if the set contains pairs (i, a[i]),
212- // we must at least widen them to (i, pointer_object(a))
213211
214212 // remove loop-local symbols from the inferred set
215213 cfg_info.erase_locals (to_havoc);
216214
215+ // If the set contains pairs (i, a[i]),
216+ // we widen them to (i, __CPROVER_POINTER_OBJECT(a))
217+ widen_assigns (to_havoc);
218+
217219 log.debug () << " No loop assigns clause provided. Inferred targets: {" ;
218220 // Add inferred targets to the loop assigns clause.
219221 bool ran_once = false ;
Original file line number Diff line number Diff line change @@ -242,3 +242,29 @@ bool is_assigns_clause_replacement_tracking_comment(const irep_idt &comment)
242242 return id2string (comment).find (ASSIGNS_CLAUSE_REPLACEMENT_TRACKING) !=
243243 std::string::npos;
244244}
245+
246+ void widen_assigns (assignst &assigns)
247+ {
248+ assignst result;
249+
250+ havoc_utils_is_constantt is_constant (assigns);
251+
252+ for (const auto &e : assigns)
253+ {
254+ if (e.id () == ID_index || e.id () == ID_dereference)
255+ {
256+ address_of_exprt address_of_expr (e);
257+
258+ // index or offset is non-constant.
259+ if (!is_constant (address_of_expr))
260+ {
261+ result.emplace (pointer_object (address_of_expr));
262+ }
263+ else
264+ result.emplace (e);
265+ }
266+ else
267+ result.emplace (e);
268+ }
269+ assigns = result;
270+ }
Original file line number Diff line number Diff line change @@ -180,4 +180,11 @@ irep_idt make_assigns_clause_replacement_tracking_comment(
180180// / \ref make_assigns_clause_replacement_tracking_comment.
181181bool is_assigns_clause_replacement_tracking_comment (const irep_idt &comment);
182182
183+ // / Widen expressions in \p assigns with the following strategy.
184+ // / If an expression is an array index or object dereference expression,
185+ // / with a non-constant offset, e.g. a[i] or *(b+i) with a non-constant `i`,
186+ // / then replace it by the entire underlying object. Otherwise, e.g. for a[i] or
187+ // / *(b+i) when `i` is a known constant, keep the expression in the result.
188+ void widen_assigns (assignst &assigns);
189+
183190#endif // CPROVER_GOTO_INSTRUMENT_CONTRACTS_UTILS_H
You can’t perform that action at this time.
0 commit comments