Skip to content

Commit 89a0470

Browse files
authored
Merge pull request #8412 from tautschnig/library-is-compiled
Library functions: mark them as compiled
2 parents a395044 + b42ac11 commit 89a0470

File tree

9 files changed

+73
-46
lines changed

9 files changed

+73
-46
lines changed

regression/contracts-dfcc/chain.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,8 @@ elif echo $args_inst | grep -q -- "--dump-c" ; then
5858

5959
rm "${name}${dfcc_suffix}-mod.c"
6060
fi
61+
if ! echo "${args_cbmc}" | grep -q -- --function ; then
62+
$goto_instrument --drop-unused-functions "${name}${dfcc_suffix}-mod.gb" "${name}${dfcc_suffix}-mod.gb"
63+
fi
6164
$goto_instrument --show-goto-functions "${name}${dfcc_suffix}-mod.gb"
6265
$cbmc --sat-solver cadical "${name}${dfcc_suffix}-mod.gb" ${args_cbmc}

regression/contracts/assigns_enforce_03/main.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
void f2(int *, int *, int *);
2+
void f3(int *, int *, int *);
3+
14
void f1(int *x1, int *y1, int *z1) __CPROVER_assigns(*x1, *y1, *z1)
25
{
36
f2(x1, y1, z1);
@@ -22,6 +25,8 @@ int main()
2225
int q = 2;
2326
int r = 3;
2427
f1(&p, &q, &r);
28+
f2(&p, &q, &r);
29+
f3(&p, &q, &r);
2530

2631
return 0;
2732
}

regression/contracts/assigns_enforce_03/test.desc

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
CORE
22
main.c
33
--enforce-contract f1 --enforce-contract f2 --enforce-contract f3
4-
^\[f1.assigns.\d+\] line 1 Check that \*x1 is valid: SUCCESS$
5-
^\[f1.assigns.\d+\] line 1 Check that \*y1 is valid: SUCCESS$
6-
^\[f1.assigns.\d+\] line 1 Check that \*z1 is valid: SUCCESS$
7-
^\[f2.assigns.\d+\] line 6 Check that \*x2 is valid: SUCCESS$
8-
^\[f2.assigns.\d+\] line 6 Check that \*y2 is valid: SUCCESS$
9-
^\[f2.assigns.\d+\] line 6 Check that \*z2 is valid: SUCCESS$
10-
^\[f3.assigns.\d+\] line 11 Check that \*x3 is valid: SUCCESS$
11-
^\[f3.assigns.\d+\] line 11 Check that \*y3 is valid: SUCCESS$
12-
^\[f3.assigns.\d+\] line 12 Check that \*z3 is valid: SUCCESS$
13-
^\[f3.assigns.\d+\] line 14 Check that \*x3 is assignable: SUCCESS$
14-
^\[f3.assigns.\d+\] line 15 Check that \*y3 is assignable: SUCCESS$
15-
^\[f3.assigns.\d+\] line 16 Check that \*z3 is assignable: SUCCESS$
4+
^\[f1.assigns.\d+\] line 4 Check that \*x1 is valid: SUCCESS$
5+
^\[f1.assigns.\d+\] line 4 Check that \*y1 is valid: SUCCESS$
6+
^\[f1.assigns.\d+\] line 4 Check that \*z1 is valid: SUCCESS$
7+
^\[f2.assigns.\d+\] line 9 Check that \*x2 is valid: SUCCESS$
8+
^\[f2.assigns.\d+\] line 9 Check that \*y2 is valid: SUCCESS$
9+
^\[f2.assigns.\d+\] line 9 Check that \*z2 is valid: SUCCESS$
10+
^\[f3.assigns.\d+\] line 14 Check that \*x3 is valid: SUCCESS$
11+
^\[f3.assigns.\d+\] line 14 Check that \*y3 is valid: SUCCESS$
12+
^\[f3.assigns.\d+\] line 15 Check that \*z3 is valid: SUCCESS$
13+
^\[f3.assigns.\d+\] line 17 Check that \*x3 is assignable: SUCCESS$
14+
^\[f3.assigns.\d+\] line 18 Check that \*y3 is assignable: SUCCESS$
15+
^\[f3.assigns.\d+\] line 19 Check that \*z3 is assignable: SUCCESS$
1616
^VERIFICATION SUCCESSFUL$
1717
^EXIT=0$
1818
^SIGNAL=0$

regression/contracts/chain.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,5 +41,8 @@ elif echo $args_inst | grep -q -- "--dump-c" ; then
4141

4242
rm "${name}-mod.c"
4343
fi
44+
if ! echo "${args_cbmc}" | grep -q -- --function ; then
45+
$goto_instrument --drop-unused-functions "${name}-mod.gb" "${name}-mod.gb"
46+
fi
4447
$goto_instrument --show-goto-functions "${name}-mod.gb"
4548
$cbmc "${name}-mod.gb" ${args_cbmc}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CORE
2+
main.c
3+
--apply-loop-contracts
4+
^\[ackermann\.\d+\] line 21 Check loop invariant before entry: SUCCESS$
5+
^\[ackermann\.\d+\] line 21 Check that loop invariant is preserved: SUCCESS$
6+
^\[ackermann\.\d+\] line 21 Check decreases clause on loop iteration: SUCCESS$
7+
^\[ackermann.assigns.\d+\] line 29 Check that m is assignable: SUCCESS$
8+
^\[ackermann.assigns.\d+\] line 30 Check that n is assignable: SUCCESS$
9+
^\[ackermann.assigns.\d+\] line 35 Check that m is assignable: SUCCESS$
10+
^\[ackermann.overflow.\d+] line 39 arithmetic overflow on signed \+ in n \+ 1: FAILURE$
11+
^\*\* 1 of \d+ failed
12+
^VERIFICATION FAILED$
13+
^EXIT=10$
14+
^SIGNAL=0$
15+
--
16+
--
17+
It tests whether we can prove (only partially) the termination of the Ackermann
18+
function using a multidimensional decreases clause.
19+
20+
Note that this particular implementation of the Ackermann function contains
21+
both a while-loop and recursion. Therefore, to fully prove the termination of
22+
the Ackermann function, we must prove both
23+
(i) the termination of the while-loop and
24+
(ii) the termination of the recursion.
25+
Because CBMC does not support termination proofs of recursions (yet), we cannot
26+
prove the latter, but the former. Hence, the termination proof in the code is
27+
only "partial."
Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,18 @@
11
CORE
22
main.c
3-
--apply-loop-contracts --replace-call-with-contract ackermann
3+
--replace-call-with-contract ackermann
44
^\[ackermann.precondition\.\d+\] line \d+ Check requires clause of ackermann in main: SUCCESS$
5-
^\[ackermann.precondition\.\d+\] line \d+ Check requires clause of ackermann in ackermann: SUCCESS$
6-
^\[ackermann\.\d+\] line 21 Check loop invariant before entry: SUCCESS$
7-
^\[ackermann\.\d+\] line 21 Check that loop invariant is preserved: SUCCESS$
8-
^\[ackermann\.\d+\] line 21 Check decreases clause on loop iteration: SUCCESS$
9-
^\[ackermann.assigns.\d+\] line 29 Check that m is assignable: SUCCESS$
10-
^\[ackermann.assigns.\d+\] line 30 Check that n is assignable: SUCCESS$
11-
^\[ackermann.assigns.\d+\] line 34 Check that n is assignable: SUCCESS$
12-
^\[ackermann.assigns.\d+\] line 35 Check that m is assignable: SUCCESS$
135
^VERIFICATION SUCCESSFUL$
146
^EXIT=0$
157
^SIGNAL=0$
168
--
179
--
18-
It tests whether we can prove (only partially) the termination of the Ackermann
19-
function using a multidimensional decreases clause.
20-
21-
Note that this particular implementation of the Ackermann function contains
22-
both a while-loop and recursion. Therefore, to fully prove the termination of
23-
the Ackermann function, we must prove both
24-
(i) the termination of the while-loop and
25-
(ii) the termination of the recursion.
26-
Because CBMC does not support termination proofs of recursions (yet), we cannot
27-
prove the latter, but the former. Hence, the termination proof in the code is
28-
only "partial."
29-
30-
Furthermore, the Ackermann function has a function contract that the result
10+
The Ackermann function has a function contract that the result
3111
is always non-negative. This post-condition is necessary for establishing
3212
the loop invariant. However, in this test, we do not enforce the function
3313
contract. Instead, we assume that the function contract is correct and use it
34-
(i.e. replace a recursive call of the Ackermann function with its contract).
14+
(i.e. replace a recursive call of the Ackermann function with its contract).
3515

3616
We cannot verify/enforce the function contract of the Ackermann function, since
3717
CBMC does not support function contracts for recursively defined functions.
38-
As of now, CBMC only supports function contracts for non-recursive functions.
18+
As of now, CBMC only supports function contracts for non-recursive functions.

src/ansi-c/goto-conversion/link_to_library.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,36 @@ add_one_function(
4141
// convert to CFG
4242
if(
4343
library_model.symbol_table.symbols.find(missing_function) !=
44-
library_model.symbol_table.symbols.end())
44+
library_model.symbol_table.symbols.end() &&
45+
library_model.symbol_table.lookup_ref(missing_function).value.is_not_nil())
4546
{
4647
goto_convert(
4748
missing_function,
4849
library_model.symbol_table,
4950
library_model.goto_functions,
5051
message_handler);
52+
// this function is now included in goto_functions, no need to re-convert
53+
// should the goto binary be reloaded
54+
library_model.symbol_table.get_writeable_ref(missing_function)
55+
.set_compiled();
5156
}
5257
// We might need a function that's outside our own library, but brought in via
5358
// some header file included by the library. Those functions already exist in
5459
// goto_model.symbol_table, but haven't been converted just yet.
5560
else if(
5661
goto_model.symbol_table.symbols.find(missing_function) !=
57-
goto_model.symbol_table.symbols.end())
62+
goto_model.symbol_table.symbols.end() &&
63+
goto_model.symbol_table.lookup_ref(missing_function).value.is_not_nil() &&
64+
!goto_model.symbol_table.lookup_ref(missing_function).is_compiled())
5865
{
5966
goto_convert(
6067
missing_function,
6168
goto_model.symbol_table,
6269
library_model.goto_functions,
6370
message_handler);
71+
// this function is now included in goto_functions, no need to re-convert
72+
// should the goto binary be reloaded
73+
goto_model.symbol_table.get_writeable_ref(missing_function).set_compiled();
6474
}
6575

6676
// check whether additional initialization may be required

src/goto-instrument/contracts/dynamic-frames/dfcc_library.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ void dfcc_libraryt::load(std::set<irep_idt> &to_instrument)
326326
{
327327
goto_convert(
328328
id, goto_model.symbol_table, goto_model.goto_functions, message_handler);
329+
goto_model.symbol_table.get_writeable_ref(id).set_compiled();
329330
}
330331

331332
// check that all symbols have a goto_implementation

src/goto-synthesizer/cegis_verifier.cpp

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -546,12 +546,8 @@ cext cegis_verifiert::build_cex(
546546

547547
void cegis_verifiert::restore_functions()
548548
{
549-
for(const auto &fun_entry : goto_model.goto_functions.function_map)
550-
{
551-
irep_idt fun_name = fun_entry.first;
552-
goto_model.goto_functions.function_map[fun_name].body.swap(
553-
original_functions[fun_name]);
554-
}
549+
for(auto &[fun_name, orig_fun_body] : original_functions)
550+
goto_model.goto_functions.function_map[fun_name].body.swap(orig_fun_body);
555551
}
556552

557553
std::optional<cext> cegis_verifiert::verify()
@@ -569,10 +565,12 @@ std::optional<cext> cegis_verifiert::verify()
569565
// 3. construct the formatted counterexample from the violated property and
570566
// its trace.
571567

572-
// Store the original functions. We will restore them after the verification.
568+
// Store the original functions when they have a body (library functions might
569+
// not yet have one). We will restore them after the verification.
573570
for(const auto &fun_entry : goto_model.goto_functions.function_map)
574571
{
575-
original_functions[fun_entry.first].copy_from(fun_entry.second.body);
572+
if(fun_entry.second.body_available())
573+
original_functions[fun_entry.first].copy_from(fun_entry.second.body);
576574
}
577575

578576
// Annotate the candidates to the goto_model for checking.

0 commit comments

Comments
 (0)