Skip to content

Commit 3af4718

Browse files
committed
Invoke goto_functions.update() after inlining
Inlining will alter location (instruction) numbers, which need to be updated to once again be globally unique. With this change, invar_check_large requires an assigns clause for the loop as the local may alias analysis returns "UNKNOWN." The previous result was actually unsound, because the automatically computed assigns set did not include arr0, arr1, arr2, arr3, arr4. This also demonstrated that the implementation in the test was incorrect: it would not terminate when: *(arr[h]) == pivot && *(arr[l]) == pivot && h != r && l != r.
1 parent 7eceeb5 commit 3af4718

File tree

3 files changed

+21
-5
lines changed

3 files changed

+21
-5
lines changed

regression/contracts/invar_check_large/main.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ int main()
2323
int r = 1;
2424
while(h > l)
2525
// clang-format off
26+
__CPROVER_assigns(arr0, arr1, arr2, arr3, arr4, h, l, r)
2627
__CPROVER_loop_invariant(
2728
// Turn off `clang-format` because it breaks the `==>` operator.
2829
h >= l &&
@@ -61,6 +62,11 @@ int main()
6162
r = h;
6263
l++;
6364
}
65+
else
66+
{
67+
h--;
68+
l++;
69+
}
6470
}
6571
else if(*(arr[h]) <= pivot)
6672
{

regression/contracts/invar_check_large/test.desc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
7-
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
7+
^\[main.\d+\] .* Check that loop invariant is preserved: SUCCESS$
88
^\[main.assertion.1\] .* assertion 0 <= r && r < 5: SUCCESS$
99
^\[main.assertion.2\] .* assertion \*\(arr\[r\]\) == pivot: SUCCESS$
1010
^\[main.assertion.3\] .* assertion 0 < r ==> arr0 <= pivot: SUCCESS$

src/goto-instrument/contracts/contracts.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -773,10 +773,14 @@ void code_contractst::apply_loop_contract(
773773
const irep_idt &function_name,
774774
goto_functionst::goto_functiont &goto_function)
775775
{
776-
local_may_aliast local_may_alias(goto_function);
777-
natural_loops_mutablet natural_loops(goto_function.body);
778-
779-
if(!natural_loops.loop_map.size())
776+
const bool may_have_loops = std::any_of(
777+
goto_function.body.instructions.begin(),
778+
goto_function.body.instructions.end(),
779+
[](const goto_programt::instructiont &instruction) {
780+
return instruction.is_backwards_goto();
781+
});
782+
783+
if(!may_have_loops)
780784
return;
781785

782786
inlining_decoratort decorated(log.get_message_handler());
@@ -787,6 +791,12 @@ void code_contractst::apply_loop_contract(
787791
decorated.get_recursive_function_warnings_count() == 0,
788792
"Recursive functions found during inlining");
789793

794+
// restore internal invariants
795+
goto_functions.update();
796+
797+
local_may_aliast local_may_alias(goto_function);
798+
natural_loops_mutablet natural_loops(goto_function.body);
799+
790800
// A graph node type that stores information about a loop.
791801
// We create a DAG representing nesting of various loops in goto_function,
792802
// sort them topologically, and instrument them in the top-sorted order.

0 commit comments

Comments
 (0)