summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/doc/gcov.texi9
-rw-r--r--gcc/gcov-dump.c12
-rw-r--r--gcc/gcov.c87
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/gcov/gcov-13.C39
-rw-r--r--gcc/testsuite/lib/gcov.exp2
7 files changed, 152 insertions, 18 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d3549485dc8..7e7ebe0c7ce 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,19 @@
+2011-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * 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 <aesok@post.ru>
* config/ia64/ia64.h (PRINT_OPERAND, PRINT_OPERAND_ADDRESS,
diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi
index 640d52e1284..e771f72e402 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 a6c5b33c622..4c2913b4d96 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 29907a311e3..d3cb4d09585 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 dcf2343d637..d09f65229d7 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-12-02 Nathan Sidwell <nathan@acm.org>
+
+ * lib/gcov.exp (verify-lines): Allow = as a count char.
+ * g++.dg/gcov/gcov-13.C: New.
+
2011-12-02 Michael Zolotukhin <michael.v.zolotukhin@intel.com>
* 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 00000000000..c262a71f536
--- /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 081b3ceb14c..fcd92616c05 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] {