From 1a9075e2897aed199f8f52b7a212672d1f86a1b4 Mon Sep 17 00:00:00 2001 From: Tristan Gingold Date: Tue, 12 Jun 2007 15:39:15 +0000 Subject: [PATCH] gcov.c: Comments updated. * gcov.c: Comments updated. (source_info): Add file_time field. (source_index): New variable. (mutiple_files): New variable. (generate_results): New function extracted from process_file. (process_file): Save and restore chain of functions, generate results and free structures only if not merging results. (release_structures): File names are now freed in create_file_names (create_file_names): Free previous file names. (find_source): File date is now read here and modifications in source files is checked here. (read_graph_file): Only reverse order of functions for the current object file. (make_gcov_file_name): Do not generate long names if input_name is NULL. (output_lines): If merging results do not display graph, data and runs informations. Checking source file modification is done in find_source. * doc/gcov.texi: Append an s to sourcefile. From-SVN: r125649 --- gcc/ChangeLog | 23 +++++++ gcc/doc/gcov.texi | 4 +- gcc/gcov.c | 160 +++++++++++++++++++++++++++++++--------------- 3 files changed, 132 insertions(+), 55 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8d476fd81ad..06501a81bde 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,26 @@ +2007-06-12 Tristan Gingold + + * gcov.c: Comments updated. + (source_info): Add file_time field. + (source_index): New variable. + (mutiple_files): New variable. + (generate_results): New function extracted from process_file. + (process_file): Save and restore chain of functions, generate + results and free structures only if not merging results. + (release_structures): File names are now freed in create_file_names + (create_file_names): Free previous file names. + (find_source): File date is now read here and modifications in + source files is checked here. + (read_graph_file): Only reverse order of functions for the current + object file. + (make_gcov_file_name): Do not generate long names if input_name is + NULL. + (output_lines): If merging results do not display graph, data and + runs informations. + Checking source file modification is done in find_source. + + * doc/gcov.texi: Append an s to sourcefile. + 2007-06-12 Bernd Schmidt * config/bfin/bfin.md (UNSPEC_NOP): New constant. diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index 55c903c7630..1f9f5e80122 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -113,7 +113,7 @@ compatible with any other profiling or test coverage mechanism. @section Invoking @command{gcov} @smallexample -gcov @r{[}@var{options}@r{]} @var{sourcefile} +gcov @r{[}@var{options}@r{]} @var{sourcefiles} @end smallexample @command{gcov} accepts the following options: @@ -128,7 +128,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] [@option{-l}|@option{--long-file-names}] [@option{-p}|@option{--preserve-paths}] [@option{-f}|@option{--function-summaries}] - [@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefile} + [@option{-o}|@option{--object-directory} @var{directory|file}] @var{sourcefiles} [@option{-u}|@option{--unconditional-branches}] @c man end @c man begin SEEALSO diff --git a/gcc/gcov.c b/gcc/gcov.c index 3b249c7055b..b177b53cf0f 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -29,15 +29,6 @@ Boston, MA 02110-1301, USA. */ /* ??? Should have an option to print the number of basic blocks, and the percent of them that are covered. */ -/* ??? Does not correctly handle the case where two .bb files refer to - the same included source file. For example, if one has a short - file containing only inline functions, which is then included in - two other files, then there will be two .bb files which refer to - the include file, but there is no way to get the total execution - counts for the included file, can only get execution counts for one - or the other of the including files. this can be fixed by --ratios - --long-file-names --preserve-paths and perl. */ - /* Need an option to show individual block counts, and show probabilities of fall through arcs. */ @@ -54,7 +45,7 @@ Boston, MA 02110-1301, USA. */ #include "gcov-io.h" #include "gcov-io.c" -/* The bbg file is generated by -ftest-coverage option. The da file is +/* The gcno file is generated by -ftest-coverage option. The gcda file is generated by a program compiled with -fprofile-arcs. Their formats are documented in gcov-io.h. */ @@ -234,6 +225,7 @@ typedef struct source_info /* Name of source file. */ char *name; unsigned index; + time_t file_time; /* Array of line information. */ line_t *lines; @@ -253,10 +245,15 @@ typedef struct source_info static function_t *functions; -/* This points to the head of the sourcefile structure list. */ +/* This points to the head of the sourcefile structure list. New elements + are always prepended. */ static source_t *sources; +/* Next index for a source file. */ + +static unsigned source_index; + /* This holds data summary information. */ static struct gcov_summary object_summary; @@ -281,6 +278,13 @@ static char *da_file_name; static int no_data_file; +/* If there is several input files, compute and display results after + reading all data files. This way if two or more gcda file refer to + the same source file (eg inline subprograms in a .h file), the + counts are added. */ + +static int multiple_files = 0; + /* Output branch probabilities. */ static int flag_branches = 0; @@ -330,6 +334,7 @@ static int process_args (int, char **); static void print_usage (int) ATTRIBUTE_NORETURN; static void print_version (void) ATTRIBUTE_NORETURN; static void process_file (const char *); +static void generate_results (const char *); static void create_file_names (const char *); static source_t *find_source (const char *); static int read_graph_file (void); @@ -360,12 +365,15 @@ main (int argc, char **argv) if (optind == argc) print_usage (true); + if (argc - argno > 1) + multiple_files = 1; + for (; argno != argc; argno++) - { - release_structures (); + process_file (argv[argno]); - process_file (argv[argno]); - } + generate_results (multiple_files ? NULL : argv[argc - 1]); + + release_structures (); return 0; } @@ -389,7 +397,7 @@ print_usage (int error_p) FILE *file = error_p ? stderr : stdout; int status = error_p ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE; - fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE\n\n"); + fnotice (file, "Usage: gcov [OPTION]... SOURCEFILE...\n\n"); fnotice (file, "Print code coverage information.\n\n"); fnotice (file, " -h, --help Print this help, then exit\n"); fnotice (file, " -v, --version Print version number, then exit\n"); @@ -499,8 +507,14 @@ process_args (int argc, char **argv) static void process_file (const char *file_name) { - source_t *src; function_t *fn; + function_t *fn_p; + function_t *old_functions; + + /* Save and clear the list of current functions. They will be appended + later. */ + old_functions = functions; + functions = NULL; create_file_names (file_name); if (read_graph_file ()) @@ -515,8 +529,19 @@ process_file (const char *file_name) if (read_count_file ()) return; - for (fn = functions; fn; fn = fn->next) + for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn->next) solve_flow_graph (fn); + + if (fn_p) + fn_p->next = old_functions; +} + +static void +generate_results (const char *file_name) +{ + source_t *src; + function_t *fn; + for (src = sources; src; src = src->next) src->lines = XCNEWVEC (line_t, src->num_lines); for (fn = functions; fn; fn = fn->next) @@ -569,12 +594,6 @@ release_structures (void) function_t *fn; source_t *src; - free (bbg_file_name); - free (da_file_name); - da_file_name = bbg_file_name = NULL; - bbg_file_time = 0; - bbg_stamp = 0; - while ((src = sources)) { sources = src->next; @@ -620,6 +639,15 @@ create_file_names (const char *file_name) int length = strlen (file_name); int base; + /* Free previous file names. */ + if (bbg_file_name) + free (bbg_file_name); + if (da_file_name) + free (da_file_name); + da_file_name = bbg_file_name = NULL; + bbg_file_time = 0; + bbg_stamp = 0; + if (object_directory && object_directory[0]) { struct stat status; @@ -673,20 +701,42 @@ static source_t * find_source (const char *file_name) { source_t *src; + struct stat status; if (!file_name) file_name = ""; for (src = sources; src; src = src->next) if (!strcmp (file_name, src->name)) - return src; + break; - src = XCNEW (source_t); - src->name = xstrdup (file_name); - src->coverage.name = src->name; - src->index = sources ? sources->index + 1 : 1; - src->next = sources; - sources = src; + if (!src) + { + src = XCNEW (source_t); + src->name = xstrdup (file_name); + src->coverage.name = src->name; + src->index = source_index++; + src->next = sources; + sources = src; + + if (!stat (file_name, &status)) + src->file_time = status.st_mtime; + } + + if (src->file_time > bbg_file_time) + { + static int info_emitted; + + fnotice (stderr, "%s:source file is newer than graph file '%s'\n", + src->name, bbg_file_name); + if (!info_emitted) + { + fnotice (stderr, + "(the message is only displayed one per source file)\n"); + info_emitted = 1; + } + src->file_time = 0; + } return src; } @@ -699,6 +749,7 @@ read_graph_file (void) unsigned version; unsigned current_tag = 0; struct function_info *fn = NULL; + function_t *old_functions_head = functions; source_t *src = NULL; unsigned ix; unsigned tag; @@ -920,7 +971,9 @@ read_graph_file (void) { function_t *fn, *fn_p, *fn_n; - for (fn_p = NULL, fn = functions; fn; fn_p = fn, fn = fn_n) + for (fn_p = old_functions_head, fn = functions; + fn != old_functions_head; + fn_p = fn, fn = fn_n) { unsigned ix; @@ -1012,6 +1065,9 @@ read_count_file (void) unsigned ident = gcov_read_unsigned (); struct function_info *fn_n = functions; + /* Try to find the function in the list. + To speed up the search, first start from the last function + found. */ for (fn = fn ? fn->next : NULL; ; fn = fn->next) { if (fn) @@ -1424,16 +1480,22 @@ static char * make_gcov_file_name (const char *input_name, const char *src_name) { char *cptr; - char *name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10); + char *name; - name[0] = 0; - if (flag_long_names && strcmp (src_name, input_name)) + if (flag_long_names && input_name && strcmp (src_name, input_name)) { + name = XNEWVEC (char, strlen (src_name) + strlen (input_name) + 10); + name[0] = 0; /* Generate the input filename part. */ cptr = flag_preserve_paths ? NULL : strrchr (input_name, '/'); strcat (name, cptr ? cptr + 1 : input_name); strcat (name, "##"); } + else + { + name = XNEWVEC (char, strlen (src_name) + 10); + name[0] = 0; + } /* Generate the source filename part. */ cptr = flag_preserve_paths ? NULL : strrchr (src_name, '/'); @@ -1787,11 +1849,14 @@ output_lines (FILE *gcov_file, const source_t *src) function_t *fn = NULL; fprintf (gcov_file, "%9s:%5d:Source:%s\n", "-", 0, src->name); - fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name); - fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, - no_data_file ? "-" : da_file_name); - fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, - object_summary.ctrs[GCOV_COUNTER_ARCS].runs); + if (!multiple_files) + { + fprintf (gcov_file, "%9s:%5d:Graph:%s\n", "-", 0, bbg_file_name); + fprintf (gcov_file, "%9s:%5d:Data:%s\n", "-", 0, + no_data_file ? "-" : da_file_name); + fprintf (gcov_file, "%9s:%5d:Runs:%u\n", "-", 0, + object_summary.ctrs[GCOV_COUNTER_ARCS].runs); + } fprintf (gcov_file, "%9s:%5d:Programs:%u\n", "-", 0, program_count); source_file = fopen (src->name, "r"); @@ -1800,19 +1865,8 @@ output_lines (FILE *gcov_file, const source_t *src) fnotice (stderr, "%s:cannot open source file\n", src->name); retval = NULL; } - else - { - struct stat status; - - if (!fstat (fileno (source_file), &status) - && status.st_mtime > bbg_file_time) - { - fnotice (stderr, "%s:source file is newer than graph file '%s'\n", - src->name, bbg_file_name); - fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", - "-", 0); - } - } + else if (src->file_time == 0) + fprintf (gcov_file, "%9s:%5d:Source is newer than graph\n", "-", 0); if (flag_branches) fn = src->functions; -- 2.30.2