Skip to content

Commit 343121c

Browse files
committed
Define coverage blocks so as to be terminated by assumptions
If a coverage block has an assumption in the middle then then an assertion at the end of the block could be reported as covered but actually be unreachable due to the preceding the assumption. Therefore coverage blocks should be terminated by assumptions in order to ensure than coverage reporting is accurate.
1 parent 45fa2ca commit 343121c

File tree

7 files changed

+37
-19
lines changed

7 files changed

+37
-19
lines changed

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 new-smt-backend
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)