]> gcc.gnu.org Git - gcc.git/commitdiff
gcov.c (struct arc_info): Add is_throw field.
authorNathan Sidwell <nathan@acm.org>
Fri, 2 Dec 2011 20:32:40 +0000 (20:32 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 2 Dec 2011 20:32:40 +0000 (20:32 +0000)
* 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

gcc/ChangeLog
gcc/doc/gcov.texi
gcc/gcov-dump.c
gcc/gcov.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/gcov/gcov-13.C [new file with mode: 0644]
gcc/testsuite/lib/gcov.exp

index d3549485dc8c2fc2349966a8b7ebdb90d928bde9..7e7ebe0c7ce69e2dbdc406164b0ae3af2f427429 100644 (file)
@@ -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,
index 640d52e128467e7d77bc929d7d346d5f159c8be9..e771f72e4027dbcb05a3f2942235105bd6b44872 100644 (file)
@@ -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}
index a6c5b33c62208fc5f4acb00a4c1545802b45df0e..4c2913b4d96509212f7615f8031c053a730509b4 100644 (file)
@@ -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 (")");
+           }
        }
     }
 }
index 29907a311e37907449942b5b268a6d183b53414f..d3cb4d095855d75e47e55c2613669b92409e3661 100644 (file)
@@ -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;
+         }
+    }
+}
 \f
 
 /* 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)
index dcf2343d6378952f102d11d4aa8e5dbf9ad22f14..d09f65229d76af9f6df46751bbadbaac760a9740 100644 (file)
@@ -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 (file)
index 0000000..c262a71
--- /dev/null
@@ -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 } } */
index 081b3ceb14c2be5ec613dcda61bbd53cb5c0c974..fcd92616c0559c47e205f7b37365610c3b7f87a5 100644 (file)
@@ -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] {
This page took 0.109405 seconds and 5 git commands to generate.