OSDN Git Service

PR c++/50811
[pf3gnuchains/gcc-fork.git] / gcc / gcov.c
index bb27913..94a1c35 100644 (file)
@@ -37,6 +37,7 @@ along with Gcov; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "intl.h"
+#include "diagnostic.h"
 #include "version.h"
 
 #include <getopt.h>
@@ -54,6 +55,13 @@ along with Gcov; see the file COPYING3.  If not see
    some places we make use of the knowledge of how profile.c works to
    select particular algorithms here.  */
 
+/* The code validates that the profile information read in corresponds
+   to the code currently being compiled.  Rather than checking for
+   identical files, the code below computes a checksum on the CFG
+   (based on the order of basic blocks and the arcs in the CFG).  If
+   the CFG checksum in the gcda file match the CFG checksum for the
+   code currently being compiled, the profile data will be used.  */
+
 /* This is the size of the buffer used to read in source file lines.  */
 
 #define STRING_SIZE 200
@@ -161,7 +169,8 @@ typedef struct function_info
   /* Name of function.  */
   char *name;
   unsigned ident;
-  unsigned checksum;
+  unsigned lineno_checksum;
+  unsigned cfg_checksum;
 
   /* Array of basic blocks.  */
   block_t *blocks;
@@ -334,7 +343,6 @@ static int flag_preserve_paths = 0;
 static int flag_counts = 0;
 
 /* Forward declarations.  */
-static void fnotice (FILE *, const char *, ...) ATTRIBUTE_PRINTF_2;
 static int process_args (int, char **);
 static void print_usage (int) ATTRIBUTE_NORETURN;
 static void print_version (void) ATTRIBUTE_NORETURN;
@@ -361,12 +369,22 @@ main (int argc, char **argv)
 {
   int argno;
   int first_arg;
+  const char *p;
+
+  p = argv[0] + strlen (argv[0]);
+  while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
+    --p;
+  progname = p;
+
+  xmalloc_set_program_name (progname);
 
   /* Unlock the stdio streams.  */
   unlock_std_streams ();
 
   gcc_init_libintl ();
 
+  diagnostic_initialize (global_dc, 0);
+
   /* Handle response files.  */
   expandargv (&argc, &argv);
 
@@ -393,16 +411,6 @@ main (int argc, char **argv)
 
   return 0;
 }
-
-static void
-fnotice (FILE *file, const char *cmsgid, ...)
-{
-  va_list ap;
-
-  va_start (ap, cmsgid);
-  vfprintf (file, _(cmsgid), ap);
-  va_end (ap);
-}
 \f
 /* Print a usage message and exit.  If ERROR_P is nonzero, this is an error,
    otherwise the output of --help.  */
@@ -644,13 +652,12 @@ release_structures (void)
     }
 }
 
-/* Generate the names of the graph and data files. If OBJECT_DIRECTORY
-   is not specified, these are looked for in the current directory,
-   and named from the basename of the FILE_NAME sans extension. If
-   OBJECT_DIRECTORY is specified and is a directory, the files are in
-   that directory, but named from the basename of the FILE_NAME, sans
-   extension. Otherwise OBJECT_DIRECTORY is taken to be the name of
-   the object *file*, and the data files are named from that.  */
+/* Generate the names of the graph and data files.  If OBJECT_DIRECTORY
+   is not specified, these are named from FILE_NAME sans extension.  If
+   OBJECT_DIRECTORY is specified and is a directory, the files are in that
+   directory, but named from the basename of the FILE_NAME, sans extension.
+   Otherwise OBJECT_DIRECTORY is taken to be the name of the object *file*
+   and the data files are named from that.  */
 
 static void
 create_file_names (const char *file_name)
@@ -683,8 +690,8 @@ create_file_names (const char *file_name)
   else
     {
       name = XNEWVEC (char, length + 1);
-      name[0] = 0;
-      base = 1;
+      strcpy (name, file_name);
+      base = 0;
     }
 
   if (base)
@@ -807,12 +814,14 @@ read_graph_file (void)
       if (tag == GCOV_TAG_FUNCTION)
        {
          char *function_name;
-         unsigned ident, checksum, lineno;
+         unsigned ident, lineno;
+         unsigned lineno_checksum, cfg_checksum;
          source_t *src;
          function_t *probe, *prev;
 
          ident = gcov_read_unsigned ();
-         checksum = gcov_read_unsigned ();
+         lineno_checksum = gcov_read_unsigned ();
+         cfg_checksum = gcov_read_unsigned ();
          function_name = xstrdup (gcov_read_string ());
          src = find_source (gcov_read_string ());
          lineno = gcov_read_unsigned ();
@@ -820,7 +829,8 @@ read_graph_file (void)
          fn = XCNEW (function_t);
          fn->name = function_name;
          fn->ident = ident;
-         fn->checksum = checksum;
+         fn->lineno_checksum = lineno_checksum;
+         fn->cfg_checksum = cfg_checksum;
          fn->src = src;
          fn->line = lineno;
 
@@ -1107,7 +1117,8 @@ read_count_file (void)
 
          if (!fn)
            ;
-         else if (gcov_read_unsigned () != fn->checksum)
+         else if (gcov_read_unsigned () != fn->lineno_checksum
+                  || gcov_read_unsigned () != fn->cfg_checksum)
            {
            mismatch:;
              fnotice (stderr, "%s:profile mismatch for '%s'\n",