Skip to content

Commit 2d691ea

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 d460e1c commit 2d691ea

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-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: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,14 +682,22 @@ void code_contractst::apply_loop_contract(
682682
const irep_idt &function_name,
683683
goto_functionst::goto_functiont &goto_function)
684684
{
685-
local_may_aliast local_may_alias(goto_function);
686-
natural_loops_mutablet natural_loops(goto_function.body);
687-
688-
if(!natural_loops.loop_map.size())
685+
const bool may_have_loops = std::any_of(
686+
goto_function.body.instructions.begin(),
687+
goto_function.body.instructions.end(),
688+
[](const goto_programt::instructiont &instruction) {
689+
return instruction.is_backwards_goto();
690+
});
691+
692+
if(!may_have_loops)
689693
return;
690694

691695
goto_function_inline(
692696
goto_functions, function_name, ns, log.get_message_handler());
697+
goto_functions.update();
698+
699+
local_may_aliast local_may_alias(goto_function);
700+
natural_loops_mutablet natural_loops(goto_function.body);
693701

694702
// A graph node type that stores information about a loop.
695703
// We create a DAG representing nesting of various loops in goto_function,
@@ -1008,6 +1016,7 @@ bool code_contractst::check_frame_conditions_function(const irep_idt &function)
10081016
// Inline all function calls.
10091017
goto_function_inline(
10101018
goto_functions, function_obj->first, ns, log.get_message_handler());
1019+
goto_functions.update();
10111020

10121021
// Insert write set inclusion checks.
10131022
check_frame_conditions(

0 commit comments

Comments
 (0)