Skip to content

Commit 6930101

Browse files
Merge pull request #7810 from thomasspriggs/tas/cover_assume_blocks
Define coverage blocks so as to be terminated by assumptions
2 parents 3bf78f7 + ac26185 commit 6930101

File tree

11 files changed

+86
-19
lines changed

11 files changed

+86
-19
lines changed

Diff for: regression/cbmc-cover/location-assume/end.c

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#include <assert.h>
2+
3+
void main()
4+
{
5+
int i;
6+
int *p = &i;
7+
int j;
8+
__CPROVER_assume(j == 1 / (*p));
9+
}

Diff for: regression/cbmc-cover/location-assume/end.desc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CORE
2+
end.c
3+
--pointer-check --div-by-zero-check --cover location
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.coverage.1\] file end.c line 5 function main block 1 \(lines end\.c:main:5-8\): SATISFIED$
7+
^\[main.coverage.2\] file end.c line 9 function main block 2 \(lines end\.c:main:9\): SATISFIED$
8+
^\*\* 2 of 2 covered \(100.0%\)
9+
--
10+
^warning: ignoring
11+
--
12+
Test that in the case where multiple assertions are added on the same line of
13+
code due to the addition of instrumentation checks, these do not result in
14+
further splitting blocks.

Diff for: regression/cbmc-cover/location-assume/middle.c

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <assert.h>
2+
3+
int main()
4+
{
5+
int i;
6+
int j;
7+
j = i;
8+
__CPROVER_assume(0);
9+
j = i + 2;
10+
return 0;
11+
}

Diff for: regression/cbmc-cover/location-assume/middle.desc

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
CORE
2+
middle.c
3+
--cover location
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^\[main.coverage.1\] file middle.c line 5 function main block 1 \(lines middle\.c:main:5-8\): SATISFIED$
7+
^\[main.coverage.2\] file middle.c line 9 function main block 2 \(lines middle\.c:main:9-11\): FAILED$
8+
^\*\* 1 of 2 covered \(50.0%\)
9+
--
10+
^warning: ignoring
11+
--
12+
This test confirms that assumptions in the middle of what would otherwise be a
13+
single blocks without control flow will cause the code to be split into 2
14+
coverage blocks. This is required as an unsatisfiable assumption can result in
15+
the following statements being unreachable.

Diff for: regression/cbmc-cover/location12/test.desc

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ main.c
77
^\[main.coverage.2\] file main.c line 10 function main block 2.*: SATISFIED$
88
^\[foo.coverage.1\] file main.c line 3 function foo block 1.*: SATISFIED$
99
^\[foo.coverage.2\] file main.c line 4 function foo block 2.*: FAILED$
10-
^\[foo.coverage.3\] file main.c line 5 function foo block 3.*: SATISFIED$
11-
^\*\* 4 of 5 covered \(80.0%\)
10+
^\[foo.coverage.3\] file main.c line 5 function foo block 3.*: FAILED$
11+
^\[foo.coverage.4\] file main.c line 5 function foo block 4.*: SATISFIED$
12+
^\*\* 4 of 6 covered \(66.7%\)
1213
--
1314
^warning: ignoring

Diff for: regression/cbmc-cover/location15/test.desc

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ main.c
66
^\[main.coverage.1\] file main.c line 10 function main block 1.*: SATISFIED$
77
^\[main.coverage.2\] file main.c line 10 function main block 2.*: SATISFIED$
88
^\[main.coverage.3\] file main.c line 13 function main block 3.*: FAILED$
9-
^\[main.coverage.4\] file main.c line 16 function main block 4.*: SATISFIED$
9+
^\[main.coverage.4\] file main.c line 14 function main block 4.*: FAILED$
10+
^\[main.coverage.5\] file main.c line 16 function main block 5.*: SATISFIED$
1011
^\[foo.coverage.1\] file main.c line 5 function foo block 1.*: FAILED$
1112
^\*\* 3 of \d+ covered
1213
--

Diff for: regression/cbmc-cover/location16/test.desc

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ main.c
99
^\[func.coverage.2\] file main.c line 6 function func block 2.*: FAILED$
1010
^\[func.coverage.3\] file main.c line 8 function func block 3.*: FAILED$
1111
^\[func.coverage.4\] file main.c line 12 function func block 4.*: FAILED$
12-
^\[func.coverage.5\] file main.c line 15 function func block 5.*: SATISFIED$
13-
^\*\* 4 of 7 covered \(57.1%\)
12+
^\[func.coverage.5\] file main.c line 14 function func block 5.*: FAILED$
13+
^\[func.coverage.6\] file main.c line 15 function func block 6.*: SATISFIED$
14+
^\*\* 4 of 8 covered \(50.0%\)
1415
--
1516
^warning: ignoring

Diff for: regression/cbmc-cover/location2/test.desc

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[main.coverage.1\] file main.c line 9 function main block 1 \(lines main.c:main:9,10\): SATISFIED$
7-
^\[main.coverage.2\] file main.c line 11 function main block 2 \(lines main.c:main:11\): SATISFIED$
8-
^\*\* 2 of 2 covered \(100.0%\)
7+
^\[main.coverage.3\] file main.c line 11 function main block 3 \(lines main.c:main:11\): SATISFIED$
8+
^\*\* 3 of 3 covered \(100.0%\)
99
--
1010
^warning: ignoring
1111
main.c::5

Diff for: regression/cbmc-cover/simple_assert/test.desc

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ main.c
44
^EXIT=0$
55
^SIGNAL=0$
66
^\[main\.coverage\.1\] .* function main block 1.*: SATISFIED$
7-
(1 of 1|3 of 3) covered \(100\.0%\)$
7+
(1 of 1|2 of 2|3 of 3) covered \(100\.0%\)$
88
--
99
^warning: ignoring
1010
^CONVERSION ERROR$

Diff for: regression/cbmc/cover-failed-assertions/test-no-failed-assertions.desc

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
CORE paths-lifo-expected-failure
22
test.c
33
--cover location --pointer-check --malloc-may-fail --malloc-fail-null
4-
\[main\.coverage\.4\] file test\.c line \d+ function main block 4 \(lines test\.c:main:17,18\): SATISFIED
5-
\[main\.coverage\.3\] file test\.c line \d+ function main block 3 \(lines test\.c:main:15\): FAILED
6-
\[main\.coverage\.2\] file test\.c line \d+ function main block 2 \(lines test\.c:main:5,6,12,14\): SATISFIED
4+
\[main\.coverage\.5\] file test\.c line \d+ function main block 5 \(lines test\.c:main:17,18\): SATISFIED
5+
\[main\.coverage\.4\] file test\.c line \d+ function main block 4 \(lines test\.c:main:15\): FAILED
6+
\[main\.coverage\.3\] file test\.c line \d+ function main block 3 \(lines test\.c:main:12,14\): SATISFIED
7+
\[main\.coverage\.2\] file test\.c line \d+ function main block 2 \(lines test\.c:main:5,6,12\): SATISFIED
78
\[main\.coverage\.1\] file test\.c line \d+ function main block 1 \(lines test\.c:main:5\): SATISFIED
89
^EXIT=0$
910
^SIGNAL=0$

Diff for: src/goto-instrument/cover_basic_blocks.cpp

+22-8
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,34 @@ optionalt<std::size_t> cover_basic_blockst::continuation_of_block(
2929
return {};
3030
}
3131

32+
static bool
33+
same_source_line(const source_locationt &a, const source_locationt &b)
34+
{
35+
return a.get_file() == b.get_file() && a.get_line() == b.get_line();
36+
}
37+
3238
cover_basic_blockst::cover_basic_blockst(const goto_programt &goto_program)
3339
{
3440
bool next_is_target = true;
41+
const goto_programt::instructiont *preceding_assume = nullptr;
3542
std::size_t current_block = 0;
3643

3744
forall_goto_program_instructions(it, goto_program)
3845
{
46+
// For the purposes of coverage blocks, multiple consecutive assume
47+
// instructions with the same source location are considered to be part of
48+
// the same block. Assumptions should terminate a block, as subsequent
49+
// instructions may be unreachable. However check instrumentation passes
50+
// may insert multiple assertions in the same program location. Therefore
51+
// these are combined for reasons of readability of the coverage output.
52+
bool end_of_assume_group =
53+
preceding_assume &&
54+
!(it->is_assume() &&
55+
same_source_line(
56+
preceding_assume->source_location(), it->source_location()));
57+
3958
// Is it a potential beginning of a block?
40-
if(next_is_target || it->is_target())
59+
if(next_is_target || it->is_target() || end_of_assume_group)
4160
{
4261
if(auto block_number = continuation_of_block(it, block_map))
4362
{
@@ -72,13 +91,8 @@ cover_basic_blockst::cover_basic_blockst(const goto_programt &goto_program)
7291
block_info.source_location = it->source_location();
7392
}
7493

75-
next_is_target =
76-
#if 0
77-
// Disabled for being too messy
78-
it->is_goto() || it->is_function_call() || it->is_assume();
79-
#else
80-
it->is_goto() || it->is_function_call();
81-
#endif
94+
next_is_target = it->is_goto() || it->is_function_call();
95+
preceding_assume = it->is_assume() ? &*it : nullptr;
8296
}
8397
}
8498

0 commit comments

Comments
 (0)