diff mbox series

GCOV: create one intermediate file per a gcno file (PR gcov-profile/82702).

Message ID 7c344dc6-2fa3-ba9a-cad9-d0d716e09c0d@suse.cz
State New
Headers show
Series GCOV: create one intermediate file per a gcno file (PR gcov-profile/82702). | expand

Commit Message

Martin Liška Oct. 31, 2017, 3:50 p.m. UTC
Hi.

This is partial revert of r246804 where I accidentally changed behavior so that each
intermediate file is written to a source file. That's not intended for example for header files.
As mentioned in documentation: "The output is a single ‘.gcov’ file per ‘.gcda’ file".
Outer loop in main function must be changed and intermediate files should be processed one by one
(process_file + generate_results). On the contrary, for normal mode, we first process all files
and then print gcov file for all seen source files.

Patch survives gcov.exp test suite.

Ready for trunk?
Thanks,
Martin

gcc/ChangeLog:

2017-10-31  Martin Liska  <mliska@suse.cz>

	PR gcov-profile/82702
	* gcov.c (main): Handle intermediate files in a different
	way.
	(get_gcov_intermediate_filename): New function.
	(output_gcov_file): Remove support of intermediate files.
	(generate_results): Allocate intermediate file.
	(release_structures): Clean-up properly fn_end.
---
  gcc/gcov.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++-------------
  1 file changed, 91 insertions(+), 23 deletions(-)
diff mbox series

Patch

diff --git a/gcc/gcov.c b/gcc/gcov.c
index f1e7777cf94..979ca183d7e 100644
--- a/gcc/gcov.c
+++ b/gcc/gcov.c
@@ -708,17 +708,31 @@  main (int argc, char **argv)
 
   first_arg = argno;
 
-  for (; argno != argc; argno++)
+  if (flag_intermediate_format)
     {
-      if (flag_display_progress)
-	printf ("Processing file %d out of %d\n", argno - first_arg + 1,
-		argc - first_arg);
-      process_file (argv[argno]);
+      for (; argno != argc; argno++)
+	{
+	  if (flag_display_progress)
+	    printf ("Processing file %d out of %d\n", argno - first_arg + 1,
+		    argc - first_arg);
+	  process_file (argv[argno]);
+	  generate_results (argv[argno]);
+	  release_structures ();
+	}
     }
+  else
+    {
+      for (; argno != argc; argno++)
+	{
+	  if (flag_display_progress)
+	    printf ("Processing file %d out of %d\n", argno - first_arg + 1,
+		    argc - first_arg);
+	  process_file (argv[argno]);
+	}
 
-  generate_results (multiple_files ? NULL : argv[argc - 1]);
-
-  release_structures ();
+      generate_results (multiple_files ? NULL : argv[argc - 1]);
+      release_structures ();
+    }
 
   return 0;
 }
@@ -880,6 +894,31 @@  process_args (int argc, char **argv)
   return optind;
 }
 
+/* Get the name of the gcov file.  The return value must be free'd.
+
+   It appends the '.gcov' extension to the *basename* of the file.
+   The resulting file name will be in PWD.
+
+   e.g.,
+   input: foo.da,       output: foo.da.gcov
+   input: a/b/foo.cc,   output: foo.cc.gcov  */
+
+static char *
+get_gcov_intermediate_filename (const char *file_name)
+{
+  const char *gcov = ".gcov";
+  char *result;
+  const char *cptr;
+
+  /* Find the 'basename'.  */
+  cptr = lbasename (file_name);
+
+  result = XNEWVEC (char, strlen (cptr) + strlen (gcov) + 1);
+  sprintf (result, "%s%s", cptr, gcov);
+
+  return result;
+}
+
 /* Output the result in intermediate format used by 'lcov'.
 
 The intermediate format contains a single file named 'foo.cc.gcov',
@@ -1018,19 +1057,16 @@  output_gcov_file (const char *file_name, source_info *src)
     {
       FILE *gcov_file = fopen (gcov_file_name, "w");
       if (gcov_file)
-        {
-          fnotice (stdout, "Creating '%s'\n", gcov_file_name);
-
-	  if (flag_intermediate_format)
-	    output_intermediate_file (gcov_file, src);
-	  else
-	    output_lines (gcov_file, src);
-          if (ferror (gcov_file))
-            fnotice (stderr, "Error writing output file '%s'\n", gcov_file_name);
-          fclose (gcov_file);
-        }
+	{
+	  fnotice (stdout, "Creating '%s'\n", gcov_file_name);
+	  output_lines (gcov_file, src);
+	  if (ferror (gcov_file))
+	    fnotice (stderr, "Error writing output file '%s'\n",
+		     gcov_file_name);
+	  fclose (gcov_file);
+	}
       else
-        fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
+	fnotice (stderr, "Could not open output file '%s'\n", gcov_file_name);
     }
   else
     {
@@ -1044,6 +1080,8 @@  static void
 generate_results (const char *file_name)
 {
   function_t *fn;
+  FILE *gcov_intermediate_file = NULL;
+  char *gcov_intermediate_filename = NULL;
 
   for (fn = functions; fn; fn = fn->next)
     {
@@ -1072,6 +1110,19 @@  generate_results (const char *file_name)
 	file_name = canonicalize_name (file_name);
     }
 
+  if (flag_gcov_file && flag_intermediate_format)
+    {
+      /* Open the intermediate file.  */
+      gcov_intermediate_filename = get_gcov_intermediate_filename (file_name);
+      gcov_intermediate_file = fopen (gcov_intermediate_filename, "w");
+      if (!gcov_intermediate_file)
+	{
+	  fnotice (stderr, "Cannot open intermediate output file %s\n",
+		   gcov_intermediate_filename);
+	  return;
+	}
+    }
+
   for (vector<source_info>::iterator it = sources.begin ();
        it != sources.end (); it++)
     {
@@ -1096,9 +1147,21 @@  generate_results (const char *file_name)
       total_executed += src->coverage.lines_executed;
       if (flag_gcov_file)
 	{
-	  output_gcov_file (file_name, src);
-          fnotice (stdout, "\n");
-        }
+	  if (flag_intermediate_format)
+	    /* Output the intermediate format without requiring source
+	       files.  This outputs a section to a *single* file.  */
+	    output_intermediate_file (gcov_intermediate_file, src);
+	  else
+	    output_gcov_file (file_name, src);
+	  fnotice (stdout, "\n");
+	}
+    }
+
+  if (flag_gcov_file && flag_intermediate_format)
+    {
+      /* Now we've finished writing the intermediate file.  */
+      fclose (gcov_intermediate_file);
+      XDELETEVEC (gcov_intermediate_filename);
     }
 
   if (!file_name)
@@ -1112,11 +1175,16 @@  release_structures (void)
 {
   function_t *fn;
 
+  sources.resize (0);
+  names.resize (0);
+
   while ((fn = functions))
     {
       functions = fn->next;
       delete fn;
     }
+
+  fn_end = &functions;
 }
 
 /* Generate the names of the graph and data files.  If OBJECT_DIRECTORY