Skip to content

goto instrumentation for decreases clauses on loops #6197

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 2, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions regression/contracts/invar_check_multiple_loops/test.desc
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ main.c
^SIGNAL=0$
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.3\] .* Check loop invariant before entry: SUCCESS$
^\[main.4\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.3\] .* Check decreases clause on loop iteration: SUCCESS$
^\[main.4\] .* Check loop invariant before entry: SUCCESS$
^\[main.5\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.6\] .* Check decreases clause on loop iteration: SUCCESS$
^\[main.assertion.1\] .* assertion x == y \+ 2 \* n: SUCCESS$
^VERIFICATION SUCCESSFUL$
--
Expand Down
2 changes: 1 addition & 1 deletion regression/contracts/invar_check_nested_loops/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ int main()

for(int i = 0; i < n; ++i)
// clang-format off
__CPROVER_loop_invariant(i <= n && s == i)
__CPROVER_loop_invariant(0 <= i && i <= n && s == i)
__CPROVER_decreases(n - i)
// clang-format on
{
Expand Down
4 changes: 3 additions & 1 deletion regression/contracts/invar_check_nested_loops/test.desc
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ main.c
^EXIT=0$
^SIGNAL=0$
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
^\[main.4\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.5\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.6\] .* Check decreases clause on loop iteration: SUCCESS$
^\[main.2\] .* Check loop invariant before entry: SUCCESS$
^\[main.3\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.4\] .* Check decreases clause on loop iteration: SUCCESS$
^\[main.assertion.1\] .* assertion s == n: SUCCESS$
^VERIFICATION SUCCESSFUL$
--
Expand Down
23 changes: 23 additions & 0 deletions regression/contracts/variant_function_call_fail/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#define N 10

int foo(int i);

int main()
{
int i = 0;
while(i != N)
// clang-format off
__CPROVER_loop_invariant(0 <= i && i <= N)
__CPROVER_decreases(foo(i))
// clang-format on
{
i++;
}

return 0;
}

int foo(int i)
{
return N - i;
}
14 changes: 14 additions & 0 deletions regression/contracts/variant_function_call_fail/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CORE
main.c
--apply-loop-contracts
^Decreases clause is not side-effect free. \(at: file main.c line .* function main\)$
^EXIT=70$
^SIGNAL=0$
--
--
This test fails because the decreases clause contains a function call. Decreases
clauses must not contain loops, since we want to ensure that the
calculation of decreases clauses will terminate. To enforce this requirement,
for now, we simply ban decreases clauses from containing function calls.
In the future, we may allow function calls (but definitely not loops) to appear
inside decreases clauses.
13 changes: 13 additions & 0 deletions regression/contracts/variant_missing_invariant_warning/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
int main()
{
unsigned i = 10;
while(i != 0)
// clang-format off
__CPROVER_decreases(i)
// clang-format on
{
i--;
}

return 0;
}
14 changes: 14 additions & 0 deletions regression/contracts/variant_missing_invariant_warning/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CORE
main.c
--apply-loop-contracts
activate-multi-line-match
^The loop at file main.c line 4 function main does not have a loop invariant, but has a decreases clause. Hence, a default loop invariant \('true'\) is being used.$
^\[main.1\].*Check loop invariant before entry: SUCCESS$
^\[main.2\].*Check that loop invariant is preserved: SUCCESS$
^\[main.3\].*Check decreases clause on loop iteration: SUCCESS$
^EXIT=0$
^SIGNAL=0$
--
--
This test succeeds, but it gives a warning that the user has not provided a loop
invariant. Hence, a default loop invariant (i.e. true) will be used.
16 changes: 16 additions & 0 deletions regression/contracts/variant_not_decreasing_fail/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

int main()
{
int i = 0;
int N = 10;
while(i != N)
// clang-format off
__CPROVER_loop_invariant(0 <= i && i <= N)
__CPROVER_decreases(i)
// clang-format on
{
i++;
}

return 0;
}
14 changes: 14 additions & 0 deletions regression/contracts/variant_not_decreasing_fail/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
CORE
main.c
--apply-loop-contracts
^main.c function main$
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.3\] .* Check decreases clause on loop iteration: FAILURE$
^.* 1 of 3 failed \(2 iterations\)$
^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
--
This test fails because the decreases clause is not monotinically decreasing.
4 changes: 2 additions & 2 deletions regression/contracts/variant_parsing_statement_fail/test.desc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
CORE
main.c
--enforce-all-contracts
--apply-loop-contracts
activate-multi-line-match
^main.c.*error: syntax error before 'int'\n.*__CPROVER_decreases\(int x = 0\)$
^PARSING ERROR$
^EXIT=(1|64)$
^SIGNAL=0$
--
--
This test fails because the loop variant is a statement (more precisely,
This test fails because the decreases clause is a statement (more precisely,
an assignment) rather than an expression (more precisely, an ACSL binding
expression).
8 changes: 4 additions & 4 deletions regression/contracts/variant_parsing_tuple_fail/test.desc
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
CORE
main.c
--enforce-all-contracts
--apply-loop-contracts
activate-multi-line-match
^main.c.*error: syntax error before ','\n.*__CPROVER_decreases\(N - i, 42\)$
^PARSING ERROR$
^EXIT=(1|64)$
^SIGNAL=0$
--
--
This test fails because the loop variant has two arguments instead of just one.
Currently, we only support loop variants of single arguments - we do not
support loop variants of tuples (yet).
This test fails because the decreases clause has two arguments instead of just one.
Currently, we only support decreases clauses of single arguments - we do not
support decreases clauses of tuples (yet).
15 changes: 15 additions & 0 deletions regression/contracts/variant_side_effects_fail/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
int main()
{
int i = 0;
int N = 10;
while(i != N)
// clang-format off
__CPROVER_loop_invariant(0 <= i && i <= N)
__CPROVER_decreases((N+=0) - i)
// clang-format on
{
i++;
}

return 0;
}
13 changes: 13 additions & 0 deletions regression/contracts/variant_side_effects_fail/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
CORE
main.c
--apply-loop-contracts
^Decreases clause is not side-effect free. \(at: file main.c line .* function main\)$
^EXIT=70$
^SIGNAL=0$
--
--
This test fails because the decreases clause contains a side effect, namely
incrementing variable N by zero. In this case, although the value of N
remains unchanged after the increment operation, we read from and write to N.
So this constitues a side effect. Decreases clauses are banned from containing
side effects, since decreases clauses should not modify program states.
16 changes: 16 additions & 0 deletions regression/contracts/variant_weak_invariant_fail/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@

int main()
{
int i = 0;
int N = 10;
while(i != N)
// clang-format off
__CPROVER_loop_invariant(i <= N)
__CPROVER_decreases(N - i)
// clang-format on
{
i++;
}

return 0;
}
15 changes: 15 additions & 0 deletions regression/contracts/variant_weak_invariant_fail/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
CORE
main.c
--apply-loop-contracts
^main.c function main$
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.3\] .* Check decreases clause on loop iteration: FAILURE$
^.* 1 of 3 failed \(2 iterations\)$
^VERIFICATION FAILED$
^EXIT=10$
^SIGNAL=0$
--
--
This test fails because the loop invariant is not strong enough for the
termination proof. We must add 0 <= i to the loop invariant.
20 changes: 20 additions & 0 deletions regression/contracts/variant_while_true_pass/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@

int main()
{
int i = 0;
int N = 10;
while(1 == 1)
// clang-format off
__CPROVER_loop_invariant(0 <= i && i <= N)
__CPROVER_decreases(N - i)
// clang-format on
{
if(i == 10)
{
break;
}
i++;
}

return 0;
}
16 changes: 16 additions & 0 deletions regression/contracts/variant_while_true_pass/test.desc
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
CORE
main.c
--apply-loop-contracts
^main.c function main$
^\[main.1\] .* Check loop invariant before entry: SUCCESS$
^\[main.2\] .* Check that loop invariant is preserved: SUCCESS$
^\[main.3\] .* Check decreases clause on loop iteration: SUCCESS$
^.*0 of 3 failed \(1 iterations\)$
^VERIFICATION SUCCESSFUL$
^EXIT=0$
^SIGNAL=0$
--
--
This test succeeds. The purpose of this test is to check whether a decreases
clause can successfully prove the termination of a loop (i) whose exit condition
is 1 == 1 (i.e. true) and (ii) that will eventually exit via a break statement.
Loading