Skip to content

Commit 5cdfb0b

Browse files
committed
Fix: Handle quantifiers with statement expressions in CBMC
This commit addresses the issue of handling quantifiers that contain statement expressions in CBMC. Previously, quantifiers without side effects were not supported. Changes include: - Added logic to handle quantifiers with statement expressions in `goto_clean_expr.cpp`. - Updated `c_typecheck_expr.cpp` to allow quantifiers with statement expressions. - Introduced new tests to verify the correct handling of quantifiers with statement expressions.
1 parent f55f636 commit 5cdfb0b

File tree

16 files changed

+440
-14
lines changed

16 files changed

+440
-14
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
int main()
2+
{
3+
// clang-format off
4+
// no side effects!
5+
int j = 0;
6+
//assert(j++);
7+
//assert(({int i = 0; while(i <3) i++; i <3;}));
8+
int a[5] = {0 , 0, 0, 0, 0};
9+
assert(__CPROVER_forall { int i; ({ int j = i; i=i; if(i < 0 || i >4) i = 1; ( a[i] < 5); }) });
10+
// clang-format on
11+
12+
return 0;
13+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
main.c
3+
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
^warning: ignoring
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
int main()
2+
{
3+
int b[2];
4+
int c[2];
5+
6+
// clang-format off
7+
// clang-format would rewrite the "==>" as "== >"
8+
__CPROVER_assume( __CPROVER_forall { char i; ({ _Bool flag = (i>=0 && i<2); flag ==> b[i]>=10 && b[i]<=10; }) } );
9+
__CPROVER_assume( __CPROVER_forall { unsigned i; ({ _Bool flag = (i>=0 && i<2); flag ==> c[i]>=10 && c[i]<=10; }) } );
10+
// clang-format on
11+
12+
assert(b[0] == 10 && b[1] == 10);
13+
assert(c[0] == 10 && c[1] == 10);
14+
15+
return 0;
16+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
CORE no-new-smt
2+
main.c
3+
4+
^\*\* Results:$
5+
^\[main.assertion.1\] line 12 assertion b\[.*0\] == 10 && b\[.*1\] == 10: SUCCESS$
6+
^\[main.assertion.2\] line 13 assertion c\[.*0\] == 10 && c\[.*1\] == 10: SUCCESS$
7+
^VERIFICATION SUCCESSFUL$
8+
^EXIT=0$
9+
^SIGNAL=0$
10+
--
11+
^warning: ignoring
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
int func()
2+
{
3+
return 1;
4+
}
5+
6+
int main()
7+
{
8+
// clang-format off
9+
// no side effects!
10+
assert(__CPROVER_forall { int i; func() });
11+
// clang-format on
12+
13+
return 0;
14+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CORE
2+
quantifier-with-function-call.c
3+
4+
^EXIT=6$
5+
^SIGNAL=0$
6+
quantifier must not contain function calls
7+
--
8+
^warning: ignoring

regression/cbmc/Quantifiers1/quantifier-with-side-effect.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
1-
int func()
2-
{
3-
return 1;
4-
}
5-
61
int main()
72
{
3+
int j = 0;
84
// clang-format off
95
// no side effects!
10-
assert(__CPROVER_forall { int i; func() });
6+
assert(__CPROVER_forall { int i; ({ j = 1; j; }) });
117
// clang-format on
128

139
return 0;
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
CORE
22
quantifier-with-side-effect.c
33

4-
^EXIT=6$
4+
^EXIT=(127|134)$
55
^SIGNAL=0$
6-
^file .* line 10 function main: quantifier must not contain side effects$
6+
^Invariant check failed
7+
^Reason: quantifier must not contain side effects
78
--
8-
^warning: ignoring
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// clang-format off
2+
int f1(int *arr)
3+
__CPROVER_requires(__CPROVER_exists {
4+
int i;
5+
({(0 <= i && i < 8) && arr[i] == 0;})
6+
})
7+
__CPROVER_ensures(__CPROVER_exists {
8+
int i;
9+
({(0 <= i && i < 8) && arr[i] == 0;})
10+
})
11+
// clang-format on
12+
{
13+
return 0;
14+
}
15+
16+
int main()
17+
{
18+
int arr[8];
19+
f1(arr);
20+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
CORE
2+
with_statement_expression.c
3+
--dfcc main --enforce-contract f1
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[f1.postcondition.\d+\] line \d+ Check ensures clause( of contract contract::f1 for function f1)?: SUCCESS$
7+
^VERIFICATION SUCCESSFUL$
8+
--
9+
^warning: ignoring
10+
--
11+
The purpose of this test is to ensure that we can safely use __CPROVER_exists within both
12+
positive and negative contexts (ENSURES and REQUIRES clauses).
13+
14+
With the SAT backend existential quantifiers in a positive context,
15+
e.g., the ENSURES clause being enforced in this case,
16+
are supported only if the quantifier is bound to a constant range.

0 commit comments

Comments
 (0)