Skip to content

Commit b53821a

Browse files
committed
Add support for quantifiers in loop contracts
This adds support for quantifiers in loop contracts. To do so, we call the add_quantified_variable function (introduced in a previous PR) when handling loop invariants.
1 parent 7163b6f commit b53821a

File tree

8 files changed

+129
-2
lines changed

8 files changed

+129
-2
lines changed
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#include <assert.h>
2+
void main()
3+
{
4+
int N = 64, a[64];
5+
for(int i = 0; i < N; ++i)
6+
// clang-format off
7+
__CPROVER_loop_invariant((0 <= i) && (i <= N) && __CPROVER_forall {
8+
int k;
9+
(0 <= k && k < N) ==> 1 == 1
10+
})
11+
// clang-format on
12+
{
13+
a[i] = 1;
14+
}
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Verification:
10+
This test case checks the handling of a forall expression within
11+
a loop invariant.
12+
This test case does not check correctness of the for loop.
13+
Instead, it is a trivial quantified expression to ensure that
14+
quantifiers can be handled in loop invariants.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <assert.h>
2+
void main()
3+
{
4+
int N = 64, a[64];
5+
for(int i = 0; i < N; ++i)
6+
// clang-format off
7+
__CPROVER_loop_invariant((0 <= i) && (i <= N) && __CPROVER_forall {
8+
int k;
9+
(0 <= k && k < i) ==> a[k] == 1
10+
})
11+
// clang-format on
12+
{
13+
a[i] = 1;
14+
}
15+
// clang-format off
16+
assert(__CPROVER_forall {
17+
int k;
18+
(0 <= k && k < N) ==> a[k] == 1
19+
});
20+
// clang-format on
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
KNOWNBUG
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Verification:
10+
This test case checks the handling of a forall expression within
11+
a loop invariant.
12+
In this test, the quantified variable has a symbolic upper limit.
13+
14+
Known Bug:
15+
Currently, cbmc (using the SAT back-end) does not support quantified
16+
expressions where the quantified variable has a symbolic range.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <assert.h>
2+
void main()
3+
{
4+
int N, a[64];
5+
__CPROVER_assume(0 <= N && N < 64);
6+
for(int i = 0; i < N; ++i)
7+
// clang-format off
8+
__CPROVER_loop_invariant((0 <= i) && (i <= N) && __CPROVER_forall {
9+
int k;
10+
(0 <= k && k < i) ==> a[k] == 1
11+
})
12+
// clang-format on
13+
{
14+
a[i] = 1;
15+
}
16+
// clang-format off
17+
assert(__CPROVER_forall {
18+
int k;
19+
(0 <= k && k < N) ==> a[k] == 1
20+
});
21+
// clang-format on
22+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
KNOWNBUG
2+
main.c
3+
--enforce-all-contracts
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
8+
--
9+
Verification:
10+
This test case checks the handling of a forall expression within
11+
a loop invariant.
12+
In this test, the quantified variable has a symbolic upper limit.
13+
Additionally, the number of loop iterations is also defined by a
14+
symbolic value.
15+
16+
Known Bug:
17+
Currently, cbmc (using the SAT back-end) does not support quantified
18+
expressions where the quantified variable has a symbolic range.

src/goto-instrument/code_contracts.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ exprt get_size(const typet &type, const namespacet &ns, messaget &log)
7373
return result;
7474
}
7575

76-
static void check_apply_invariants(
76+
void code_contractst::check_apply_invariants(
7777
goto_functionst::goto_functiont &goto_function,
7878
goto_convertt &converter,
7979
const local_may_aliast &local_may_alias,
@@ -97,6 +97,14 @@ static void check_apply_invariants(
9797
if(invariant.is_nil())
9898
return;
9999

100+
// Add quantified variables in contracts to the symbol map
101+
// TODO improve the structure below wrt the replace_symbolt object
102+
// In the current implementation, the add_quantified_variable
103+
// function requires a replace_symbolt object as input, which is
104+
// irrelevant in the context of loop contracts.
105+
replace_symbolt replace;
106+
code_contractst::add_quantified_variable(invariant, replace, mode);
107+
100108
// change
101109
// H: loop;
102110
// E: ...
@@ -221,8 +229,8 @@ void code_contractst::add_quantified_variable(
221229
// 2. create fresh symbol
222230
symbolt new_symbol = get_fresh_aux_symbol(
223231
quantified_symbol.type(),
232+
"",
224233
id2string(quantified_symbol.get_identifier()),
225-
"tmp",
226234
quantified_symbol.source_location(),
227235
mode,
228236
symbol_table);

src/goto-instrument/code_contracts.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,20 @@ Date: February 2016
1818
#include <string>
1919
#include <unordered_set>
2020

21+
#include <goto-programs/goto_convert_class.h>
2122
#include <goto-programs/goto_functions.h>
2223
#include <goto-programs/goto_model.h>
2324

25+
#include <goto-instrument/loop_utils.h>
26+
2427
#include <util/c_types.h>
2528
#include <util/message.h>
2629
#include <util/namespace.h>
2730
#include <util/pointer_expr.h>
2831
#include <util/replace_symbol.h>
2932

33+
#include <analyses/local_may_alias.h>
34+
3035
class messaget;
3136
class assigns_clauset;
3237

@@ -178,6 +183,14 @@ class code_contractst
178183
exprt expression,
179184
replace_symbolt &replace,
180185
irep_idt mode);
186+
187+
void check_apply_invariants(
188+
goto_functionst::goto_functiont &goto_function,
189+
goto_convertt &converter,
190+
const local_may_aliast &local_may_alias,
191+
const goto_programt::targett loop_head,
192+
const loopt &loop,
193+
const irep_idt &mode);
181194
};
182195

183196
#define FLAG_REPLACE_CALL "replace-call-with-contract"

0 commit comments

Comments
 (0)