Skip to content

Commit 3ab3c5b

Browse files
tautschnigRemi Delmas
and
Remi Delmas
committed
CONTRACTS: store contracts in dedicated symbols
Contracts can now be placed on declarations or definitions, and result in a fresh symbol being generated. That new symbol has its name prefixed with "contracts::" to place them in a pseudo-namespace, and has "is_property" set (which was an otherwise unused symbolt flag). Co-authored-by: Remi Delmas <[email protected]>
1 parent 3a6341f commit 3ab3c5b

20 files changed

+525
-47
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
int foo(int *arr, int size);
2+
3+
int foo(int *arr, int size)
4+
// clang-format off
5+
__CPROVER_requires(size > 0 && __CPROVER_is_fresh(arr, size))
6+
__CPROVER_assigns(
7+
arr[0], arr[size-1];
8+
size >= 10: arr[5];
9+
)
10+
__CPROVER_ensures(arr[0] == 0 && arr[size-1] == 0)
11+
__CPROVER_ensures(size >= 10 ==> arr[5] == __CPROVER_return_value)
12+
// clang-format on
13+
;
14+
15+
int foo(int *arr, int size)
16+
{
17+
arr[0] = 0;
18+
arr[size - 1] = 0;
19+
return size < 10 ? 0 : arr[5];
20+
}
21+
22+
int main()
23+
{
24+
int arr[10];
25+
int retval = foo(arr, 10);
26+
__CPROVER_assert(retval == arr[5], "should succeed");
27+
return 0;
28+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
int foo(int *arr, int size)
2+
{
3+
arr[0] = 0;
4+
arr[size - 1] = 0;
5+
return size < 10 ? 0 : arr[5];
6+
}
7+
8+
int foo(int *arr, int size)
9+
// clang-format off
10+
__CPROVER_requires(size > 0 && __CPROVER_is_fresh(arr, size))
11+
__CPROVER_assigns(
12+
arr[0], arr[size-1];
13+
size >= 10: arr[5];
14+
)
15+
__CPROVER_ensures(arr[0] == 0 && arr[size-1] == 0)
16+
__CPROVER_ensures(size >= 10 ==> arr[5] == __CPROVER_return_value)
17+
// clang-format on
18+
;
19+
20+
int main()
21+
{
22+
int arr[10];
23+
int retval = foo(arr, 10);
24+
__CPROVER_assert(retval == arr[5], "should succeed");
25+
return 0;
26+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
int foo(int *arr, int size);
2+
3+
int foo()
4+
// clang-format off
5+
__CPROVER_ensures(__CPROVER_return_value != 0)
6+
// clang-format on
7+
;
8+
9+
int foo(int *arr, int size)
10+
{
11+
arr[0] = 0;
12+
arr[size - 1] = 0;
13+
return size < 10 ? 0 : arr[5];
14+
}
15+
16+
int main()
17+
{
18+
int arr[10];
19+
int retval = foo(arr, 10);
20+
__CPROVER_assert(retval == arr[5], "should succeed");
21+
return 0;
22+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
int foo(int *arr, int size);
2+
3+
#if 0
4+
int foo()
5+
// clang-format off
6+
__CPROVER_ensures(__CPROVER_return_value != 0)
7+
// clang-format on
8+
;
9+
#endif
10+
11+
void foo(int *arr, int size)
12+
// clang-format off
13+
__CPROVER_requires(size > 0)
14+
// clang-format on
15+
;
16+
17+
int foo(int *arr, int size)
18+
{
19+
arr[0] = 0;
20+
arr[size - 1] = 0;
21+
return size < 10 ? 0 : arr[5];
22+
}
23+
24+
int main()
25+
{
26+
int arr[10];
27+
int retval = foo(arr, 10);
28+
__CPROVER_assert(retval == arr[5], "should succeed");
29+
return 0;
30+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
int foo(int *arr, int size)
2+
// clang-format off
3+
__CPROVER_requires(size > 0 && __CPROVER_is_fresh(arr, size))
4+
__CPROVER_assigns(
5+
arr[0], arr[size-1];
6+
size >= 10: arr[5];
7+
)
8+
__CPROVER_ensures(arr[0] == 0 && arr[size-1] == 0)
9+
__CPROVER_ensures(size >= 10 ==> arr[5] == __CPROVER_return_value)
10+
// clang-format on
11+
;
12+
13+
int foo(int *arr, int size)
14+
{
15+
arr[0] = 0;
16+
arr[size - 1] = 0;
17+
return size < 10 ? 0 : arr[5];
18+
}
19+
20+
int main()
21+
{
22+
int arr[10];
23+
int retval = foo(arr, 10);
24+
__CPROVER_assert(retval == arr[5], "should succeed");
25+
return 0;
26+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
int foo(int *arr, int size)
2+
// clang-format off
3+
__CPROVER_requires(size > 0 && __CPROVER_is_fresh(arr, size))
4+
__CPROVER_assigns(
5+
arr[0], arr[size-1];
6+
size >= 10: arr[5];
7+
)
8+
__CPROVER_ensures(arr[0] == 0 && arr[size-1] == 0)
9+
__CPROVER_ensures(size >= 10 ==> arr[5] == __CPROVER_return_value)
10+
// clang-format on
11+
;
12+
13+
int main()
14+
{
15+
int arr[10] = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
16+
int retval = foo(arr, 10);
17+
assert(arr[0] == 0);
18+
assert(arr[1] == 9);
19+
assert(arr[2] == 8);
20+
assert(arr[3] == 7);
21+
assert(arr[4] == 6);
22+
assert(arr[5] == retval);
23+
assert(arr[6] == 4);
24+
assert(arr[7] == 3);
25+
assert(arr[8] == 2);
26+
assert(arr[9] == 0);
27+
return 0;
28+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main-contract-after-declaration.c
3+
--replace-call-with-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that we can have a function declaration with a contract after
10+
having seen an earlier declaration of that same function.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main-contract-after-definition.c
3+
--replace-call-with-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that we can have a function declaration with a contract after
10+
having seen that function's definition.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main-contract-incomplete.c
3+
4+
error: code contract on incomplete function re-declaration
5+
CONVERSION ERROR
6+
^EXIT=1$
7+
^SIGNAL=0$
8+
--
9+
--
10+
This test checks that contracts on incomplete re-declarations are rejected.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main-contract-signature-conflict.c
3+
--enforce-contract foo
4+
^Contract of 'foo' has different signature\.$
5+
^EXIT=6$
6+
^SIGNAL=0$
7+
--
8+
--
9+
This test checks that contracts on function declarations with a matching name
10+
but different type are rejected.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE
2+
main-definition-after-contract.c
3+
--replace-call-with-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that we can have a function declaration with a contract and
10+
without body, then the function definition, and successfully replace a call to
11+
the function by the contract.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
CORE
2+
main-no-definition.c
3+
--replace-call-with-contract foo
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
This test checks that we can have a function declaration with a contract and
10+
without body and replace a call to the function by the contract.

0 commit comments

Comments
 (0)