It's possible to have a line of code that has a non-zero coverage. However, it can contain unexecuted blocks and I hope adding a notification can be usefull. LLVM also does that:
-: 0:Source:ternary.c -: 0:Graph:ternary.gcno -: 0:Data:ternary.gcda -: 0:Runs:1 -: 0:Programs:1 -: 1:int b, c, d, e; -: 2: 1: 3:int main() -: 4:{ 1*: 5: int a = b < 1 ? (c < 3 ? d : c) : e; 1: 6: return a; -: 7:} It's also implemented for intermediate format, as well as color output supports that. gcc/ChangeLog: 2017-10-23 Martin Liska <mli...@suse.cz> * doc/gcov.texi: Document that. * gcov.c (add_line_counts): Mark lines with a non-executed statement. (output_line_beginning): Handle such lines. (output_lines): Pass new argument. (output_intermediate_file): Print it in intermediate format. gcc/testsuite/ChangeLog: 2017-10-23 Martin Liska <mli...@suse.cz> * g++.dg/gcov/ternary.C: New test. * g++.dg/gcov/gcov-threads-1.C (main): Update expected line count. * lib/gcov.exp: Support new format for intermediate file format. --- gcc/doc/gcov.texi | 13 +++++--- gcc/gcov.c | 50 ++++++++++++++---------------- gcc/testsuite/g++.dg/gcov/gcov-threads-1.C | 4 +-- gcc/testsuite/g++.dg/gcov/ternary.C | 12 +++++++ gcc/testsuite/lib/gcov.exp | 2 +- 5 files changed, 46 insertions(+), 35 deletions(-) create mode 100644 gcc/testsuite/g++.dg/gcov/ternary.C diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index 2aa7166e35d..4029ccb0a93 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -189,7 +189,7 @@ one entry per line @smallexample file:@var{source_file_name} function:@var{line_number},@var{execution_count},@var{function_name} -lcount:@var{line number},@var{execution_count} +lcount:@var{line number},@var{execution_count},@var{has_unexecuted_statement} branch:@var{line_number},@var{branch_coverage_type} Where the @var{branch_coverage_type} is @@ -208,11 +208,11 @@ Here is a sample when @option{-i} is used in conjunction with @option{-b} option file:array.cc function:11,1,_Z3sumRKSt6vectorIPiSaIS0_EE function:22,1,main -lcount:11,1 -lcount:12,1 -lcount:14,1 +lcount:11,1,0 +lcount:12,1,0 +lcount:14,1,0 branch:14,taken -lcount:26,1 +lcount:26,1,0 branch:28,nottaken @end smallexample @@ -341,6 +341,9 @@ used in a compilation unit. Such functions are marked with @samp{-} even though they contain a code. Use @option{-fkeep-inline-functions} and @option{-fkeep-static-functions} in order to properly record @var{execution_count} of such functions. +Executed lines having a statement with zero @var{execution_count} end with +@samp{*} character and are colored with magenta color with @option{-k} +option. Some lines of information at the start have @var{line_number} of zero. These preamble lines are of the form diff --git a/gcc/gcov.c b/gcc/gcov.c index e53bcf0fd88..f9334f96eb3 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -256,6 +256,7 @@ typedef struct line_info Used in all-blocks mode. */ unsigned exists : 1; unsigned unexceptional : 1; + unsigned has_unexecuted_block : 1; } line_t; bool @@ -850,28 +851,7 @@ process_args (int argc, char **argv) /* Output the result in intermediate format used by 'lcov'. The intermediate format contains a single file named 'foo.cc.gcov', -with no source code included. A sample output is - -file:foo.cc -function:5,1,_Z3foov -function:13,1,main -function:19,1,_GLOBAL__sub_I__Z3foov -function:19,1,_Z41__static_initialization_and_destruction_0ii -lcount:5,1 -lcount:7,9 -lcount:9,8 -lcount:11,1 -file:/.../iostream -lcount:74,1 -file:/.../basic_ios.h -file:/.../ostream -file:/.../ios_base.h -function:157,0,_ZStorSt12_Ios_IostateS_ -lcount:157,0 -file:/.../char_traits.h -function:258,0,_ZNSt11char_traitsIcE6lengthEPKc -lcount:258,0 -... +with no source code included. The default gcov outputs multiple files: 'foo.cc.gcov', 'iostream.gcov', 'ios_base.h.gcov', etc. with source code @@ -901,8 +881,8 @@ output_intermediate_file (FILE *gcov_file, source_t *src) { arc_t *arc; if (line->exists) - fprintf (gcov_file, "lcount:%u,%s\n", line_num, - format_gcov (line->count, 0, -1)); + fprintf (gcov_file, "lcount:%u,%s,%d\n", line_num, + format_gcov (line->count, 0, -1), line->has_unexecuted_block); if (flag_branches) for (arc = line->branches; arc; arc = arc->line_next) { @@ -2289,7 +2269,11 @@ add_line_counts (coverage_t *coverage, function_t *fn) } line->exists = 1; if (!block->exceptional) - line->unexceptional = 1; + { + line->unexceptional = 1; + if (block->count == 0) + line->has_unexecuted_block = 1; + } line->count += block->count; } } @@ -2496,6 +2480,7 @@ pad_count_string (string &s) static void output_line_beginning (FILE *f, bool exists, bool unexceptional, + bool has_unexecuted_block, gcov_type count, unsigned line_num, const char *exceptional_string, const char *unexceptional_string) @@ -2506,6 +2491,17 @@ output_line_beginning (FILE *f, bool exists, bool unexceptional, if (count > 0) { s = format_gcov (count, 0, -1); + if (has_unexecuted_block) + { + if (flag_use_colors) + { + pad_count_string (s); + s = SGR_SEQ (COLOR_BG_MAGENTA COLOR_SEPARATOR COLOR_FG_WHITE); + s += SGR_RESET; + } + else + s += "*"; + } pad_count_string (s); } else @@ -2610,7 +2606,7 @@ output_lines (FILE *gcov_file, const source_t *src) There are 16 spaces of indentation added before the source line so that tabs won't be messed up. */ output_line_beginning (gcov_file, line->exists, line->unexceptional, - line->count, line_num, + line->has_unexecuted_block, line->count, line_num, "=====", "#####"); fprintf (gcov_file, ":%s\n", retval ? retval : "/*EOF*/"); @@ -2626,7 +2622,7 @@ output_lines (FILE *gcov_file, const source_t *src) if (!block->is_call_return) { output_line_beginning (gcov_file, line->exists, - block->exceptional, + block->exceptional, false, block->count, line_num, "%%%%%", "$$$$$"); fprintf (gcov_file, "-block %2d", ix++); diff --git a/gcc/testsuite/g++.dg/gcov/gcov-threads-1.C b/gcc/testsuite/g++.dg/gcov/gcov-threads-1.C index cc9266ab8ea..cc912f9ddf4 100644 --- a/gcc/testsuite/g++.dg/gcov/gcov-threads-1.C +++ b/gcc/testsuite/g++.dg/gcov/gcov-threads-1.C @@ -31,14 +31,14 @@ int main(int argc, char **argv) { { ids[i] = i; int r = pthread_create (&t[i], NULL, ContentionNoDeadlock_thread, &ids[i]); - assert (r == 0); /* count(5) */ + assert (r == 0); /* count(5*) */ } int ret; for (int i = 0; i < NR; i++) { int r = pthread_join (t[i], (void**)&ret); - assert (r == 0); /* count(5) */ + assert (r == 0); /* count(5*) */ } return 0; /* count(1) */ diff --git a/gcc/testsuite/g++.dg/gcov/ternary.C b/gcc/testsuite/g++.dg/gcov/ternary.C new file mode 100644 index 00000000000..d055928c295 --- /dev/null +++ b/gcc/testsuite/g++.dg/gcov/ternary.C @@ -0,0 +1,12 @@ +// { dg-options "-fprofile-arcs -ftest-coverage" } +// { dg-do run { target native } } + +int b, c, d, e; + +int main() +{ + int a = b < 1 ? (c < 3 ? d : c) : e; /* count(1*) */ + return a; +} + +// { dg-final { run-gcov remove-gcda ternary.C } } diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp index 632d50667a7..18adc71351a 100644 --- a/gcc/testsuite/lib/gcov.exp +++ b/gcc/testsuite/lib/gcov.exp @@ -108,7 +108,7 @@ proc verify-intermediate { testname testcase file } { if [regexp "^function:(\[0-9\]+),(\[0-9\]+),.*" $line] { incr function } - if [regexp "^lcount:(\[0-9\]+),(\[0-9\]+)" $line] { + if [regexp "^lcount:(\[0-9\]+),(\[0-9\]+),(\[01\])" $line] { incr lcount } if [regexp "^branch:(\[0-9\]+),(taken|nottaken|notexec)" $line] { -- 2.14.2