]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/gcov.c
Update copyright years.
[thirdparty/gcc.git] / gcc / gcov.c
index 1d576552a45dcb211340469142e83dbff754a185..1dca304977758b8c37d9d948f6a39f3a76744a78 100644 (file)
@@ -1,6 +1,6 @@
 /* Gcov.c: prepend line execution counts and branch probabilities to a
    source file.
-   Copyright (C) 1990-2019 Free Software Foundation, Inc.
+   Copyright (C) 1990-2020 Free Software Foundation, Inc.
    Contributed by James E. Wilson of Cygnus Support.
    Mangled by Bob Manson of Cygnus Support.
    Mangled further by Nathan Sidwell <nathan@codesourcery.com>
@@ -76,17 +76,17 @@ using namespace std;
 
 /* This is the size of the buffer used to read in source file lines.  */
 
-struct function_info;
-struct block_info;
-struct source_info;
+class function_info;
+class block_info;
+class source_info;
 
 /* Describes an arc between two basic blocks.  */
 
 struct arc_info
 {
   /* source and destination blocks.  */
-  struct block_info *src;
-  struct block_info *dst;
+  class block_info *src;
+  class block_info *dst;
 
   /* transition counts.  */
   gcov_type count;
@@ -121,8 +121,9 @@ struct arc_info
 /* Describes which locations (lines and files) are associated with
    a basic block.  */
 
-struct block_location_info
+class block_location_info
 {
+public:
   block_location_info (unsigned _source_file_idx):
     source_file_idx (_source_file_idx)
   {}
@@ -134,8 +135,9 @@ struct block_location_info
 /* Describes a basic block. Contains lists of arcs to successor and
    predecessor blocks.  */
 
-struct block_info
+class block_info
 {
+public:
   /* Constructor.  */
   block_info ();
 
@@ -176,7 +178,7 @@ struct block_info
 
   /* Temporary chain for solving graph, and for chaining blocks on one
      line.  */
-  struct block_info *chain;
+  class block_info *chain;
 
 };
 
@@ -191,8 +193,9 @@ block_info::block_info (): succ (NULL), pred (NULL), num_succ (0), num_pred (0),
 /* Describes a single line of source.  Contains a chain of basic blocks
    with code on it.  */
 
-struct line_info
+class line_info
 {
+public:
   /* Default constructor.  */
   line_info ();
 
@@ -230,8 +233,9 @@ static int flag_demangled_names = 0;
 
 /* Describes a single function. Contains an array of basic blocks.  */
 
-struct function_info
+class function_info
 {
+public:
   function_info ();
   ~function_info ();
 
@@ -293,7 +297,7 @@ struct function_info
   vector<line_info> lines;
 
   /* Next function.  */
-  struct function_info *next;
+  class function_info *next;
 
   /*  Get demangled name of a function.  The demangled name
       is converted when it is used for the first time.  */
@@ -356,8 +360,9 @@ struct coverage_info
 /* Describes a file mentioned in the block graph.  Contains an array
    of line info.  */
 
-struct source_info
+class source_info
 {
+public:
   /* Default constructor.  */
   source_info ();
 
@@ -676,27 +681,11 @@ bool function_info::group_line_p (unsigned n, unsigned src_idx)
 typedef vector<arc_info *> arc_vector_t;
 typedef vector<const block_info *> block_vector_t;
 
-/* Enum with types of loop in CFG.  */
-
-enum loop_type
-{
-  NO_LOOP = 0,
-  LOOP = 1,
-  NEGATIVE_LOOP = 3
-};
-
-/* Loop_type operator that merges two values: A and B.  */
-
-inline loop_type& operator |= (loop_type& a, loop_type b)
-{
-    return a = static_cast<loop_type> (a | b);
-}
-
 /* Handle cycle identified by EDGES, where the function finds minimum cs_count
    and subtract the value from all counts.  The subtracted value is added
    to COUNT.  Returns type of loop.  */
 
-static loop_type
+static void
 handle_cycle (const arc_vector_t &edges, int64_t &count)
 {
   /* Find the minimum edge of the cycle, and reduce all nodes in the cycle by
@@ -712,7 +701,7 @@ handle_cycle (const arc_vector_t &edges, int64_t &count)
   for (unsigned i = 0; i < edges.size (); i++)
     edges[i]->cs_count -= cycle_count;
 
-  return cycle_count < 0 ? NEGATIVE_LOOP : LOOP;
+  gcc_assert (cycle_count > 0);
 }
 
 /* Unblock a block U from BLOCKED.  Apart from that, iterate all blocks
@@ -738,17 +727,28 @@ unblock (const block_info *u, block_vector_t &blocked,
     unblock (*it, blocked, block_lists);
 }
 
+/* Return true when PATH contains a zero cycle arc count.  */
+
+static bool
+path_contains_zero_or_negative_cycle_arc (arc_vector_t &path)
+{
+  for (unsigned i = 0; i < path.size (); i++)
+    if (path[i]->cs_count <= 0)
+      return true;
+  return false;
+}
+
 /* Find circuit going to block V, PATH is provisional seen cycle.
    BLOCKED is vector of blocked vertices, BLOCK_LISTS contains vertices
    blocked by a block.  COUNT is accumulated count of the current LINE.
    Returns what type of loop it contains.  */
 
-static loop_type
+static bool
 circuit (block_info *v, arc_vector_t &path, block_info *start,
         block_vector_t &blocked, vector<block_vector_t> &block_lists,
         line_info &linfo, int64_t &count)
 {
-  loop_type result = NO_LOOP;
+  bool loop_found = false;
 
   /* Add v to the block list.  */
   gcc_assert (find (blocked.begin (), blocked.end (), v) == blocked.end ());
@@ -758,26 +758,35 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
   for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
     {
       block_info *w = arc->dst;
-      if (w < start || !linfo.has_block (w))
+      if (w < start
+         || arc->cs_count <= 0
+         || !linfo.has_block (w))
        continue;
 
       path.push_back (arc);
       if (w == start)
-       /* Cycle has been found.  */
-       result |= handle_cycle (path, count);
-      else if (find (blocked.begin (), blocked.end (), w) == blocked.end ())
-       result |= circuit (w, path, start, blocked, block_lists, linfo, count);
+       {
+         /* Cycle has been found.  */
+         handle_cycle (path, count);
+         loop_found = true;
+       }
+      else if (!path_contains_zero_or_negative_cycle_arc (path)
+              &&  find (blocked.begin (), blocked.end (), w) == blocked.end ())
+       loop_found |= circuit (w, path, start, blocked, block_lists, linfo,
+                              count);
 
       path.pop_back ();
     }
 
-  if (result != NO_LOOP)
+  if (loop_found)
     unblock (v, blocked, block_lists);
   else
     for (arc_info *arc = v->succ; arc; arc = arc->succ_next)
       {
        block_info *w = arc->dst;
-       if (w < start || !linfo.has_block (w))
+       if (w < start
+           || arc->cs_count <= 0
+           || !linfo.has_block (w))
          continue;
 
        size_t index
@@ -788,14 +797,13 @@ circuit (block_info *v, arc_vector_t &path, block_info *start,
          list.push_back (v);
       }
 
-  return result;
+  return loop_found;
 }
 
-/* Find cycles for a LINFO.  If HANDLE_NEGATIVE_CYCLES is set and the line
-   contains a negative loop, then perform the same function once again.  */
+/* Find cycles for a LINFO.  */
 
 static gcov_type
-get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
+get_cycles_count (line_info &linfo)
 {
   /* Note that this algorithm works even if blocks aren't in sorted order.
      Each iteration of the circuit detection is completely independent
@@ -803,7 +811,7 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
      Therefore, operating on a permuted order (i.e., non-sorted) only
      has the effect of permuting the output cycles.  */
 
-  loop_type result = NO_LOOP;
+  bool loop_found = false;
   gcov_type count = 0;
   for (vector<block_info *>::iterator it = linfo.blocks.begin ();
        it != linfo.blocks.end (); it++)
@@ -811,14 +819,10 @@ get_cycles_count (line_info &linfo, bool handle_negative_cycles = true)
       arc_vector_t path;
       block_vector_t blocked;
       vector<block_vector_t > block_lists;
-      result |= circuit (*it, path, *it, blocked, block_lists, linfo,
-                        count);
+      loop_found |= circuit (*it, path, *it, blocked, block_lists, linfo,
+                            count);
     }
 
-  /* If we have a negative cycle, repeat the find_cycles routine.  */
-  if (result == NEGATIVE_LOOP && handle_negative_cycles)
-    count += get_cycles_count (linfo, false);
-
   return count;
 }
 
@@ -919,7 +923,7 @@ static void
 print_version (void)
 {
   fnotice (stdout, "gcov %s%s\n", pkgversion_string, version_string);
-  fprintf (stdout, "Copyright %s 2019 Free Software Foundation, Inc.\n",
+  fprintf (stdout, "Copyright %s 2020 Free Software Foundation, Inc.\n",
           _("(C)"));
   fnotice (stdout,
           _("This is free software; see the source for copying conditions.\n"
@@ -1057,10 +1061,10 @@ output_intermediate_json_line (json::array *object,
     return;
 
   json::object *lineo = new json::object ();
-  lineo->set ("line_number", new json::number (line_num));
+  lineo->set ("line_number", new json::integer_number (line_num));
   if (function_name != NULL)
     lineo->set ("function_name", new json::string (function_name));
-  lineo->set ("count", new json::number (line->count));
+  lineo->set ("count", new json::integer_number (line->count));
   lineo->set ("unexecuted_block",
              new json::literal (line->has_unexecuted_block));
 
@@ -1075,7 +1079,7 @@ output_intermediate_json_line (json::array *object,
        if (!(*it)->is_unconditional && !(*it)->is_call_non_return)
          {
            json::object *branch = new json::object ();
-           branch->set ("count", new json::number ((*it)->count));
+           branch->set ("count", new json::integer_number ((*it)->count));
            branch->set ("throw", new json::literal ((*it)->is_throw));
            branch->set ("fallthrough",
                         new json::literal ((*it)->fall_through));
@@ -1134,16 +1138,19 @@ output_json_intermediate_file (json::array *json_files, source_info *src)
       function->set ("name", new json::string ((*it)->m_name));
       function->set ("demangled_name",
                     new json::string ((*it)->get_demangled_name ()));
-      function->set ("start_line", new json::number ((*it)->start_line));
-      function->set ("start_column", new json::number ((*it)->start_column));
-      function->set ("end_line", new json::number ((*it)->end_line));
-      function->set ("end_column", new json::number ((*it)->end_column));
+      function->set ("start_line",
+                    new json::integer_number ((*it)->start_line));
+      function->set ("start_column",
+                    new json::integer_number ((*it)->start_column));
+      function->set ("end_line", new json::integer_number ((*it)->end_line));
+      function->set ("end_column",
+                    new json::integer_number ((*it)->end_column));
       function->set ("blocks",
-                    new json::number ((*it)->get_block_count ()));
+                    new json::integer_number ((*it)->get_block_count ()));
       function->set ("blocks_executed",
-                    new json::number ((*it)->blocks_executed));
+                    new json::integer_number ((*it)->blocks_executed));
       function->set ("execution_count",
-                    new json::number ((*it)->blocks[0].count));
+                    new json::integer_number ((*it)->blocks[0].count));
 
       functions->append (function);
     }
@@ -1421,6 +1428,7 @@ generate_results (const char *file_name)
 
   if (bbg_cwd != NULL)
     root->set ("current_working_directory", new json::string (bbg_cwd));
+  root->set ("data_file", new json::string (file_name));
 
   json::array *json_files = new json::array ();
   root->set ("files", json_files);