From: Nathan Sidwell Date: Fri, 2 Dec 2011 20:32:40 +0000 (+0000) Subject: gcov.c (struct arc_info): Add is_throw field. X-Git-Tag: releases/gcc-4.7.0~1803 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=8919c0d984f1d98b612268e938668f177d5f835f;p=gcc.git gcov.c (struct arc_info): Add is_throw field. * gcov.c (struct arc_info): Add is_throw field. (struct (block_info): Add exceptional field, reduce flags size to account for it. (struct function_info): Add has_catch field. (struct line_info): Add unexceptional field. (process_file): Call find_exception_blocks if necessary. (read_graph_file): Adjust. Note if an exceptional edge is seen. (find_exception_blocks): New. (add_line_counts): Set line's unexceptional flag if not exceptional. (output_branch_count): Note exceptional arcs, lines and blocks. * gcov-dump.c (tag_arcs): Decode arc flags. * doc/gcov.texi: Document '=====' lines. testsuite/ * lib/gcov.exp (verify-lines): Allow = as a count char. * g++.dg/gcov/gcov-13.C: New. From-SVN: r181949 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d3549485dc8c..7e7ebe0c7ce6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2011-12-02 Nathan Sidwell + + * gcov.c (struct arc_info): Add is_throw field. + (struct (block_info): Add exceptional field, reduce flags size to + account for it. + (struct function_info): Add has_catch field. + (struct line_info): Add unexceptional field. + (process_file): Call find_exception_blocks if necessary. + (read_graph_file): Adjust. Note if an exceptional edge is seen. + (find_exception_blocks): New. + (add_line_counts): Set line's unexceptional flag if not + exceptional. + (output_branch_count): Note exceptional arcs, lines and blocks. + * gcov-dump.c (tag_arcs): Decode arc flags. + * doc/gcov.texi: Document '=====' lines. + 2011-12-02 Anatoly Sokolov * config/ia64/ia64.h (PRINT_OPERAND, PRINT_OPERAND_ADDRESS, diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index 640d52e12846..e771f72e4027 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -261,10 +261,13 @@ program source code. The format is Additional block information may succeed each line, when requested by command line option. The @var{execution_count} is @samp{-} for lines -containing no code and @samp{#####} for lines which were never executed. -Some lines of information at the start have @var{line_number} of zero. +containing no code. Unexecuted lines are marked @samp{#####} or +@samp{====}, depending on whether they are reachable by +non-exceptional paths or only exceptional paths such as C++ exception +handlers, respectively. -The preamble lines are of the form +Some lines of information at the start have @var{line_number} of zero. +These preamble lines are of the form @smallexample -:0:@var{tag}:@var{value} diff --git a/gcc/gcov-dump.c b/gcc/gcov-dump.c index a6c5b33c6220..4c2913b4d965 100644 --- a/gcc/gcov-dump.c +++ b/gcc/gcov-dump.c @@ -351,6 +351,18 @@ tag_arcs (const char *filename ATTRIBUTE_UNUSED, dst = gcov_read_unsigned (); flags = gcov_read_unsigned (); printf (" %u:%04x", dst, flags); + if (flags) + { + char c = '('; + + if (flags & GCOV_ARC_ON_TREE) + printf ("%ctree", c), c = ','; + if (flags & GCOV_ARC_FAKE) + printf ("%cfake", c), c = ','; + if (flags & GCOV_ARC_FALLTHROUGH) + printf ("%cfall", c), c = ','; + printf (")"); + } } } } diff --git a/gcc/gcov.c b/gcc/gcov.c index 29907a311e37..d3cb4d095855 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -88,6 +88,9 @@ typedef struct arc_info unsigned int fake : 1; unsigned int fall_through : 1; + /* Arc to a catch handler. */ + unsigned int is_throw : 1; + /* Arc is for a function that abnormally returns. */ unsigned int is_call_non_return : 1; @@ -123,10 +126,11 @@ typedef struct block_info /* Block execution count. */ gcov_type count; - unsigned flags : 13; + unsigned flags : 12; unsigned count_valid : 1; unsigned valid_chain : 1; unsigned invalid_chain : 1; + unsigned exceptional : 1; /* Block is a call instrumenting site. */ unsigned is_call_site : 1; /* Does the call. */ @@ -172,6 +176,9 @@ typedef struct function_info unsigned lineno_checksum; unsigned cfg_checksum; + /* The graph contains at least one fake incoming edge. */ + unsigned has_catch : 1; + /* Array of basic blocks. */ block_t *blocks; unsigned num_blocks; @@ -224,6 +231,7 @@ typedef struct line_info in all-blocks mode. */ } u; unsigned exists : 1; + unsigned unexceptional : 1; } line_t; /* Describes a file mentioned in the block graph. Contains an array @@ -369,6 +377,7 @@ static unsigned find_source (const char *); static function_t *read_graph_file (void); static int read_count_file (function_t *); static void solve_flow_graph (function_t *); +static void find_exception_blocks (function_t *); static void add_branch_counts (coverage_t *, const arc_t *); static void add_line_counts (coverage_t *, function_t *); static void function_summary (const coverage_t *, const char *); @@ -628,6 +637,8 @@ process_file (const char *file_name) sources[src].num_lines = line + 1; solve_flow_graph (fn); + if (fn->has_catch) + find_exception_blocks (fn); *fn_end = fn; fn_end = &fn->next; } @@ -1051,13 +1062,15 @@ read_graph_file (void) { unsigned src = gcov_read_unsigned (); unsigned num_dests = GCOV_TAG_ARCS_NUM (length); + block_t *src_blk = &fn->blocks[src]; + unsigned mark_catches = 0; + struct arc_info *arc; if (src >= fn->num_blocks || fn->blocks[src].succ) goto corrupt; while (num_dests--) { - struct arc_info *arc; unsigned dest = gcov_read_unsigned (); unsigned flags = gcov_read_unsigned (); @@ -1066,7 +1079,7 @@ read_graph_file (void) arc = XCNEW (arc_t); arc->dst = &fn->blocks[dest]; - arc->src = &fn->blocks[src]; + arc->src = src_blk; arc->count = 0; arc->count_valid = 0; @@ -1074,9 +1087,9 @@ read_graph_file (void) arc->fake = !!(flags & GCOV_ARC_FAKE); arc->fall_through = !!(flags & GCOV_ARC_FALLTHROUGH); - arc->succ_next = fn->blocks[src].succ; - fn->blocks[src].succ = arc; - fn->blocks[src].num_succ++; + arc->succ_next = src_blk->succ; + src_blk->succ = arc; + src_blk->num_succ++; arc->pred_next = fn->blocks[dest].pred; fn->blocks[dest].pred = arc; @@ -1090,12 +1103,12 @@ read_graph_file (void) source block must be a call. */ fn->blocks[src].is_call_site = 1; arc->is_call_non_return = 1; + mark_catches = 1; } else { /* Non-local return from a callee of this - function. The destination block is a catch or - setjmp. */ + function. The destination block is a setjmp. */ arc->is_nonlocal_return = 1; fn->blocks[dest].is_nonlocal_return = 1; } @@ -1104,6 +1117,20 @@ read_graph_file (void) if (!arc->on_tree) fn->num_counts++; } + + if (mark_catches) + { + /* We have a fake exit from this block. The other + non-fall through exits must be to catch handlers. + Mark them as catch arcs. */ + + for (arc = src_blk->succ; arc; arc = arc->succ_next) + if (!arc->fake && !arc->fall_through) + { + arc->is_throw = 1; + fn->has_catch = 1; + } + } } else if (fn && tag == GCOV_TAG_LINES) { @@ -1543,6 +1570,34 @@ solve_flow_graph (function_t *fn) } } +/* Mark all the blocks only reachable via an incoming catch. */ + +static void +find_exception_blocks (function_t *fn) +{ + unsigned ix; + block_t **queue = XALLOCAVEC (block_t *, fn->num_blocks); + + /* First mark all blocks as exceptional. */ + for (ix = fn->num_blocks; ix--;) + fn->blocks[ix].exceptional = 1; + + /* Now mark all the blocks reachable via non-fake edges */ + queue[0] = fn->blocks; + queue[0]->exceptional = 0; + for (ix = 1; ix;) + { + block_t *block = queue[--ix]; + const arc_t *arc; + + for (arc = block->succ; arc; arc = arc->succ_next) + if (!arc->fake && !arc->is_throw && arc->dst->exceptional) + { + arc->dst->exceptional = 0; + queue[ix++] = arc->dst; + } + } +} /* Increment totals in COVERAGE according to arc ARC. */ @@ -1860,6 +1915,8 @@ add_line_counts (coverage_t *coverage, function_t *fn) coverage->lines_executed++; } line->exists = 1; + if (!block->exceptional) + line->unexceptional = 1; line->count += block->count; } free (block->u.line.encoding); @@ -2082,7 +2139,6 @@ accumulate_line_counts (source_t *src) static int output_branch_count (FILE *gcov_file, int ix, const arc_t *arc) { - if (arc->is_call_non_return) { if (arc->src->count) @@ -2099,7 +2155,8 @@ output_branch_count (FILE *gcov_file, int ix, const arc_t *arc) if (arc->src->count) fnotice (gcov_file, "branch %2d taken %s%s\n", ix, format_gcov (arc->count, arc->src->count, -flag_counts), - arc->fall_through ? " (fallthrough)" : ""); + arc->fall_through ? " (fallthrough)" + : arc->is_throw ? " (throw)" : ""); else fnotice (gcov_file, "branch %2d never executed\n", ix); } @@ -2182,8 +2239,9 @@ output_lines (FILE *gcov_file, const source_t *src) 16 spaces of indentation added before the source line so that tabs won't be messed up. */ fprintf (gcov_file, "%9s:%5u:", - !line->exists ? "-" : !line->count ? "#####" - : format_gcov (line->count, 0, -1), line_num); + !line->exists ? "-" : line->count + ? format_gcov (line->count, 0, -1) + : line->unexceptional ? "#####" : "=====", line_num); if (retval) { @@ -2211,8 +2269,9 @@ output_lines (FILE *gcov_file, const source_t *src) { if (!block->is_call_return) fprintf (gcov_file, "%9s:%5u-block %2d\n", - !line->exists ? "-" : !block->count ? "$$$$$" - : format_gcov (block->count, 0, -1), + !line->exists ? "-" : block->count + ? format_gcov (block->count, 0, -1) + : block->exceptional ? "%%%%%" : "$$$$$", line_num, ix++); if (flag_branches) for (arc = block->succ; arc; arc = arc->succ_next) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index dcf2343d6378..d09f65229d76 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2011-12-02 Nathan Sidwell + + * lib/gcov.exp (verify-lines): Allow = as a count char. + * g++.dg/gcov/gcov-13.C: New. + 2011-12-02 Michael Zolotukhin * gcc.dg/vect/slp-13.c: Increase array size, add initialization. diff --git a/gcc/testsuite/g++.dg/gcov/gcov-13.C b/gcc/testsuite/g++.dg/gcov/gcov-13.C new file mode 100644 index 000000000000..c262a71f5364 --- /dev/null +++ b/gcc/testsuite/g++.dg/gcov/gcov-13.C @@ -0,0 +1,39 @@ +/* { dg-options "-fprofile-arcs -ftest-coverage" } */ +/* { dg-do run { target native } } */ + +void Baz (int i) +{ + if (i) + throw 1; +} + +void Boz () throw () +{ +} + +int main () +{ + try + { + Baz (0); /* count(1) */ + Baz (0); /* count(1) */ + } + catch (...) + { + Boz (); /* count(=====) */ + } + + try + { + Baz (1); /* count(1) */ + Baz (0); /* count(#####) */ + } + catch (...) + { + Boz (); /* count(1) */ + } + + return 0; /* count(1) */ +} + +/* { dg-final { run-gcov gcov-13.C } } */ diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp index 081b3ceb14c2..fcd92616c055 100644 --- a/gcc/testsuite/lib/gcov.exp +++ b/gcc/testsuite/lib/gcov.exp @@ -45,7 +45,7 @@ proc verify-lines { testcase file } { while { [gets $fd line] >= 0 } { # We want to match both "-" and "#####" as count as well as numbers, # since we want to detect lines that shouldn't be marked as covered. - if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#]+)\\)(.*)" \ + if [regexp "^ *(\[^:]*): *(\[0-9\\-#]+):.*count\\((\[0-9\\-#=]+)\\)(.*)" \ "$line" all is n shouldbe rest] { if [regexp "^ *{(.*)}" $rest all xfailed] { switch [dg-process-target $xfailed] {