This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [patch] gcov intermediate format
- From: Sharad Singhai <singhai at google dot com>
- To: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Cc: Jan Hubicka <hubicka at ucw dot cz>
- Date: Mon, 17 Jun 2013 11:45:02 -0700
- Subject: Re: [patch] gcov intermediate format
- References: <CAKxPW67AHdhcF3c+XMXmMkOuKYoAL7LEFCyeiH7pF+p5Oig4OQ at mail dot gmail dot com> <CAKxPW6526=7G9BJRq3+dMPrf2CjHkmN_s2bNovLBqVejbu4pUw at mail dot gmail dot com> <CAKxPW65CLa7kYEkbqRwUtat+nfAqHbKY=8LN2=WBOMUirNk9UA at mail dot gmail dot com>
Ping.
Thanks,
Sharad
On Wed, Jun 5, 2013 at 11:18 AM, Sharad Singhai <singhai@google.com> wrote:
> Ping.
>
> Thanks,
> Sharad
>
>
> On Tue, May 28, 2013 at 11:35 AM, Sharad Singhai <singhai@google.com> wrote:
>> Sorry, my patch had bad formatting in one of the functions
>> (output_gcov_file). Here is the corrected version.
>>
>> Thanks,
>> Sharad
>>
>> (2013-05-28 <singhai@google.com>
>>
>> * gcov.c (print_usage): Handle new option.
>> (process_args): Ditto.
>> (get_gcov_intermediate_filename): New function.
>> (output_intermediate_file): New function.
>> (output_gcov_file): New function
>> (generate_results): Handle new option.
>> (release_function): Relase demangled name.
>> (read_graph_file): Handle demangled name.
>> (output_lines): Ditto.
>> * doc/gcov.texi: Document gcov intermediate format.
>>
>> testsuite/ChangeLog:
>>
>> 2013-05-28 Sharad Singhai <singhai@google.com>
>>
>> * g++.dg/gcov/gcov-8.C: New testcase.
>> * lib/gcov.exp: Handle intermediate format.
>>
>> Index: doc/gcov.texi
>> ===================================================================
>> --- doc/gcov.texi (revision 199273)
>> +++ doc/gcov.texi (working copy)
>> @@ -122,15 +122,17 @@ gcov [@option{-v}|@option{--version}] [@option{-h}
>> [@option{-a}|@option{--all-blocks}]
>> [@option{-b}|@option{--branch-probabilities}]
>> [@option{-c}|@option{--branch-counts}]
>> - [@option{-u}|@option{--unconditional-branches}]
>> + [@option{-d}|@option{--display-progress}]
>> + [@option{-f}|@option{--function-summaries}]
>> + [@option{-i}|@option{--intermediate-format}]
>> + [@option{-l}|@option{--long-file-names}]
>> + [@option{-m}|@option{--demangled-names}]
>> [@option{-n}|@option{--no-output}]
>> - [@option{-l}|@option{--long-file-names}]
>> + [@option{-o}|@option{--object-directory} @var{directory|file}]
>> [@option{-p}|@option{--preserve-paths}]
>> [@option{-r}|@option{--relative-only}]
>> - [@option{-f}|@option{--function-summaries}]
>> - [@option{-o}|@option{--object-directory} @var{directory|file}]
>> [@option{-s}|@option{--source-prefix} @var{directory}]
>> - [@option{-d}|@option{--display-progress}]
>> + [@option{-u}|@option{--unconditional-branches}]
>> @var{files}
>> @c man end
>> @c man begin SEEALSO
>> @@ -232,6 +234,50 @@ Unconditional branches are normally not interestin
>> @itemx --display-progress
>> Display the progress on the standard output.
>>
>> +@item -i
>> +@itemx --intermediate-format
>> +Output gcov file in an easy-to-parse intermediate text format that can
>> +be used by @command{lcov} or other tools. The output is a single
>> +@file{.gcov} file per @file{.gcda} file. No source code is required.
>> +
>> +The format of the intermediate @file{.gcov} file is plain text with
>> +one entry per line
>> +
>> +@smallexample
>> +file:@var{source_file_name}
>> +function:@var{line_number},@var{execution_count},@var{function_name}
>> +lcount:@var{line number},@var{execution_count}
>> +branch:@var{line_number},@var{branch_coverage_type}
>> +
>> +Where the @var{branch_coverage_type} is
>> + notexec (Branch not executed)
>> + taken (Branch executed and taken)
>> + nottaken (Branch executed, but not taken)
>> +
>> +There can be multiple @var{file} entries in an intermediate gcov
>> +file. All entries following a @var{file} pertain to that source file
>> +until the next @var{file} entry.
>> +@end smallexample
>> +
>> +Here is a sample when @option{-i} is used in conjuction with
>> @option{-b} option:
>> +
>> +@smallexample
>> +file:array.cc
>> +function:11,1,_Z3sumRKSt6vectorIPiSaIS0_EE
>> +function:22,1,main
>> +lcount:11,1
>> +lcount:12,1
>> +lcount:14,1
>> +branch:14,taken
>> +lcount:26,1
>> +branch:28,nottaken
>> +@end smallexample
>> +
>> +@item -m
>> +@itemx --demangled-names
>> +Display demangled function names in output. The default is to show
>> +mangled function names.
>> +
>> @end table
>>
>> @command{gcov} should be run with the current directory the same as that
>> Index: gcov.c
>> ===================================================================
>> --- gcov.c (revision 199273)
>> +++ gcov.c (working copy)
>> @@ -37,6 +37,7 @@ along with Gcov; see the file COPYING3. If not se
>> #include "intl.h"
>> #include "diagnostic.h"
>> #include "version.h"
>> +#include "demangle.h"
>>
>> #include <getopt.h>
>>
>> @@ -168,6 +169,7 @@ typedef struct function_info
>> {
>> /* Name of function. */
>> char *name;
>> + char *demangled_name;
>> unsigned ident;
>> unsigned lineno_checksum;
>> unsigned cfg_checksum;
>> @@ -325,6 +327,14 @@ static int flag_gcov_file = 1;
>>
>> static int flag_display_progress = 0;
>>
>> +/* Output *.gcov file in intermediate format used by 'lcov'. */
>> +
>> +static int flag_intermediate_format = 0;
>> +
>> +/* Output demangled function names. */
>> +
>> +static int flag_demangled_names = 0;
>> +
>> /* For included files, make the gcov output file name include the name
>> of the input source file. For example, if x.h is included in a.c,
>> then the output file name is a.c##x.h.gcov instead of x.h.gcov. */
>> @@ -388,6 +398,7 @@ static void executed_summary (unsigned, unsigned);
>> static void function_summary (const coverage_t *, const char *);
>> static const char *format_gcov (gcov_type, gcov_type, int);
>> static void accumulate_line_counts (source_t *);
>> +static void output_gcov_file(const char *, source_t *);
>> static int output_branch_count (FILE *, int, const arc_t *);
>> static void output_lines (FILE *, const source_t *);
>> static char *make_gcov_file_name (const char *, const char *);
>> @@ -461,21 +472,23 @@ print_usage (int error_p)
>> fnotice (file, "Usage: gcov [OPTION]... SOURCE|OBJ...\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");
>> fnotice (file, " -a, --all-blocks Show information
>> for every basic block\n");
>> fnotice (file, " -b, --branch-probabilities Include branch
>> probabilities in output\n");
>> - fnotice (file, " -c, --branch-counts Given counts of
>> branches taken\n\
>> + fnotice (file, " -c, --branch-counts Output counts of
>> branches taken\n\
>> rather than percentages\n");
>> - fnotice (file, " -n, --no-output Do not create an
>> output file\n");
>> + fnotice (file, " -d, --display-progress Display progress
>> information\n");
>> + fnotice (file, " -f, --function-summaries Output summaries
>> for each function\n");
>> + fnotice (file, " -i, --intermediate-format Output .gcov file
>> in intermediate text format\n");
>> fnotice (file, " -l, --long-file-names Use long output
>> file names for included\n\
>> source files\n");
>> - fnotice (file, " -f, --function-summaries Output summaries
>> for each function\n");
>> + fnotice (file, " -m, --demangled-names Output demangled
>> function names\n");
>> + fnotice (file, " -n, --no-output Do not create an
>> output file\n");
>> fnotice (file, " -o, --object-directory DIR|FILE Search for object
>> files in DIR or called FILE\n");
>> + fnotice (file, " -p, --preserve-paths Preserve all
>> pathname components\n");
>> + fnotice (file, " -r, --relative-only Only show data
>> for relative sources\n");
>> fnotice (file, " -s, --source-prefix DIR Source prefix to elide\n");
>> - fnotice (file, " -r, --relative-only Only show data
>> for relative sources\n");
>> - fnotice (file, " -p, --preserve-paths Preserve all
>> pathname components\n");
>> fnotice (file, " -u, --unconditional-branches Show
>> unconditional branch counts too\n");
>> - fnotice (file, " -d, --display-progress Display progress
>> information\n");
>> + fnotice (file, " -v, --version Print version
>> number, then exit\n");
>> fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n",
>> bug_report_url);
>> exit (status);
>> @@ -503,9 +516,11 @@ static const struct option options[] =
>> { "all-blocks", no_argument, NULL, 'a' },
>> { "branch-probabilities", no_argument, NULL, 'b' },
>> { "branch-counts", no_argument, NULL, 'c' },
>> + { "intermediate-format", no_argument, NULL, 'i' },
>> { "no-output", no_argument, NULL, 'n' },
>> { "long-file-names", no_argument, NULL, 'l' },
>> { "function-summaries", no_argument, NULL, 'f' },
>> + { "demangled-names", no_argument, NULL, 'm' },
>> { "preserve-paths", no_argument, NULL, 'p' },
>> { "relative-only", no_argument, NULL, 'r' },
>> { "object-directory", required_argument, NULL, 'o' },
>> @@ -523,7 +538,8 @@ process_args (int argc, char **argv)
>> {
>> int opt;
>>
>> - while ((opt = getopt_long (argc, argv, "abcdfhlno:s:pruv", options,
>> NULL)) != -1)
>> + while ((opt = getopt_long (argc, argv, "abcdfhilmno:s:pruv",
>> options, NULL)) !=
>> + -1)
>> {
>> switch (opt)
>> {
>> @@ -545,6 +561,9 @@ process_args (int argc, char **argv)
>> case 'l':
>> flag_long_names = 1;
>> break;
>> + case 'm':
>> + flag_demangled_names = 1;
>> + break;
>> case 'n':
>> flag_gcov_file = 0;
>> break;
>> @@ -564,6 +583,10 @@ process_args (int argc, char **argv)
>> case 'u':
>> flag_unconditional = 1;
>> break;
>> + case 'i':
>> + flag_intermediate_format = 1;
>> + flag_gcov_file = 1;
>> + break;
>> case 'd':
>> flag_display_progress = 1;
>> break;
>> @@ -579,6 +602,110 @@ 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',
>> +with no source code included. A sample output is
>> +
>> +file:foo.cc
>> +function:5,1,_Z3foov
>> +function:13,1,main
>> +function:19,1,_GLOBAL__sub_I__Z3foov
>> +function:19,1,_Z41__static_initialization_and_destruction_0ii
>> +lcount:5,1
>> +lcount:7,9
>> +lcount:9,8
>> +lcount:11,1
>> +file:/.../iostream
>> +lcount:74,1
>> +file:/.../basic_ios.h
>> +file:/.../ostream
>> +file:/.../ios_base.h
>> +function:157,0,_ZStorSt12_Ios_IostateS_
>> +lcount:157,0
>> +file:/.../char_traits.h
>> +function:258,0,_ZNSt11char_traitsIcE6lengthEPKc
>> +lcount:258,0
>> +...
>> +
>> +The default gcov outputs multiple files: 'foo.cc.gcov',
>> +'iostream.gcov', 'ios_base.h.gcov', etc. with source code
>> +included. Instead the intermediate format here outputs only a single
>> +file 'foo.cc.gcov' similar to the above example. */
>> +
>> +static void
>> +output_intermediate_file (FILE *gcov_file, source_t *src)
>> +{
>> + unsigned line_num; /* current line number. */
>> + const line_t *line; /* current line info ptr. */
>> + function_t *fn; /* current function info ptr. */
>> +
>> + fprintf (gcov_file, "file:%s\n", src->name); /* source file name */
>> +
>> + for (fn = src->functions; fn; fn = fn->line_next)
>> + {
>> + /* function:<name>,<line_number>,<execution_count> */
>> + fprintf (gcov_file, "function:%d,%s,%s\n", fn->line,
>> + format_gcov (fn->blocks[0].count, 0, -1),
>> + flag_demangled_names ? fn->demangled_name : fn->name);
>> + }
>> +
>> + for (line_num = 1, line = &src->lines[line_num];
>> + line_num < src->num_lines;
>> + line_num++, line++)
>> + {
>> + arc_t *arc;
>> + if (line->exists)
>> + fprintf (gcov_file, "lcount:%u,%s\n", line_num,
>> + format_gcov (line->count, 0, -1));
>> + if (flag_branches)
>> + for (arc = line->u.branches; arc; arc = arc->line_next)
>> + {
>> + if (!arc->is_unconditional && !arc->is_call_non_return)
>> + {
>> + const char *branch_type;
>> + /* branch:<line_num>,<branch_coverage_type>
>> + branch_coverage_type
>> + : notexec (Branch not executed)
>> + : taken (Branch executed and taken)
>> + : nottaken (Branch executed, but not taken)
>> + */
>> + if (arc->src->count)
>> + branch_type = (arc->count > 0) ? "taken" : "nottaken";
>> + else
>> + branch_type = "notexec";
>> + fprintf(gcov_file, "branch:%d,%s\n", line_num, branch_type);
>> + }
>> + }
>> + }
>> +}
>> +
>> +
>> /* Process a single input file. */
>>
>> static void
>> @@ -655,11 +782,40 @@ process_file (const char *file_name)
>> }
>>
>> static void
>> +output_gcov_file(const char *file_name, source_t *src)
>> +{
>> + char *gcov_file_name = make_gcov_file_name (file_name, src->coverage.name);
>> +
>> + if (src->coverage.lines)
>> + {
>> + FILE *gcov_file = fopen (gcov_file_name, "w");
>> + if (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);
>> + }
>> + else
>> + {
>> + unlink (gcov_file_name);
>> + fnotice (stdout, "Removing '%s'\n", gcov_file_name);
>> + }
>> + free (gcov_file_name);
>> +}
>> +
>> +static void
>> generate_results (const char *file_name)
>> {
>> unsigned ix;
>> source_t *src;
>> function_t *fn;
>> + FILE *gcov_intermediate_file = NULL;
>> + char *gcov_intermediate_filename = NULL;
>>
>> for (ix = n_sources, src = sources; ix--; src++)
>> if (src->num_lines)
>> @@ -670,7 +826,7 @@ generate_results (const char *file_name)
>> coverage_t coverage;
>>
>> memset (&coverage, 0, sizeof (coverage));
>> - coverage.name = fn->name;
>> + coverage.name = flag_demangled_names ? fn->demangled_name : fn->name;
>> add_line_counts (flag_function_summary ? &coverage : NULL, fn);
>> if (flag_function_summary)
>> {
>> @@ -688,7 +844,21 @@ generate_results (const char *file_name)
>> else
>> 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 (ix = n_sources, src = sources; ix--; src++)
>> {
>> if (flag_relative_only)
>> @@ -711,34 +881,21 @@ generate_results (const char *file_name)
>> total_executed += src->coverage.lines_executed;
>> if (flag_gcov_file)
>> {
>> - char *gcov_file_name
>> - = make_gcov_file_name (file_name, src->coverage.name);
>> + 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 (src->coverage.lines)
>> - {
>> - FILE *gcov_file = fopen (gcov_file_name, "w");
>> -
>> - if (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);
>> - }
>> - else
>> - {
>> - unlink (gcov_file_name);
>> - fnotice (stdout, "Removing '%s'\n", gcov_file_name);
>> - }
>> - free (gcov_file_name);
>> - }
>> - 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)
>> @@ -765,6 +922,9 @@ release_function (function_t *fn)
>> }
>> free (fn->blocks);
>> free (fn->counts);
>> + if (flag_demangled_names && fn->demangled_name != fn->name)
>> + free (fn->demangled_name);
>> + free (fn->name);
>> }
>>
>> /* Release all memory used. */
>> @@ -1050,6 +1210,12 @@ read_graph_file (void)
>>
>> fn = XCNEW (function_t);
>> fn->name = function_name;
>> + if (flag_demangled_names)
>> + {
>> + fn->demangled_name = cplus_demangle (fn->name, DMGL_PARAMS);
>> + if (!fn->demangled_name)
>> + fn->demangled_name = fn->name;
>> + }
>> fn->ident = ident;
>> fn->lineno_checksum = lineno_checksum;
>> fn->cfg_checksum = cfg_checksum;
>> @@ -2277,7 +2443,8 @@ output_lines (FILE *gcov_file, const source_t *src
>> if (arc->fake)
>> return_count -= arc->count;
>>
>> - fprintf (gcov_file, "function %s", fn->name);
>> + fprintf (gcov_file, "function %s", flag_demangled_names ?
>> + fn->demangled_name : fn->name);
>> fprintf (gcov_file, " called %s",
>> format_gcov (called_count, 0, -1));
>> fprintf (gcov_file, " returned %s",
>> Index: testsuite/lib/gcov.exp
>> ===================================================================
>> --- testsuite/lib/gcov.exp (revision 199273)
>> +++ testsuite/lib/gcov.exp (working copy)
>> @@ -70,7 +70,62 @@ proc verify-lines { testname testcase file } {
>> return $failed
>> }
>>
>> +
>> #
>> +# verify-intermediate -- check that intermediate file has certain lines
>> +#
>> +# TESTNAME is the name of the test, including unique flags.
>> +# TESTCASE is the name of the test.
>> +# FILE is the name of the gcov output file.
>> +#
>> +# Checks are very loose, they are based on certain tags being present
>> +# in the output. They do not check for exact expected execution
>> +# counts. For that the regular gcov format should be checked.
>> +#
>> +proc verify-intermediate { testname testcase file } {
>> + set failed 0
>> + set srcfile 0
>> + set function 0
>> + set lcount 0
>> + set branch 0
>> + set fd [open $file r]
>> + while { [gets $fd line] >= 0 } {
>> + if [regexp "^file:" $line] {
>> + incr srcfile
>> + }
>> + if [regexp "^function:(\[0-9\]+),(\[0-9\]+),.*" $line] {
>> + incr function
>> + }
>> + if [regexp "^lcount:(\[0-9\]+),(\[0-9\]+)" $line] {
>> + incr lcount
>> + }
>> + if [regexp "^branch:(\[0-9\]+),(taken|nottaken|notexec)" $line] {
>> + incr branch
>> + }
>> + }
>> +
>> + # We should see at least one tag of each type
>> + if {$srcfile == 0} {
>> + fail "$testname expected 'file:' tag not found"
>> + incr failed
>> + }
>> + if {$function == 0} {
>> + fail "$testname expected 'function:' tag not found"
>> + incr failed
>> + }
>> + if {$lcount == 0} {
>> + fail "$testname expected 'lcount:' tag not found"
>> + incr failed
>> + }
>> + if {$branch == 0} {
>> + fail "$testname expected 'branch:' tag not found"
>> + incr failed
>> + }
>> + return $failed
>> +}
>> +
>> +
>> +#
>> # verify-branches -- check that branch percentages are as expected
>> #
>> # TESTNAME is the name of the test, including unique flags.
>> @@ -248,6 +303,8 @@ proc run-gcov { args } {
>> set gcov_args ""
>> set gcov_verify_calls 0
>> set gcov_verify_branches 0
>> + set gcov_verify_lines 1
>> + set gcov_verify_intermediate 0
>> set xfailed 0
>>
>> foreach a $args {
>> @@ -255,6 +312,11 @@ proc run-gcov { args } {
>> set gcov_verify_calls 1
>> } elseif { $a == "branches" } {
>> set gcov_verify_branches 1
>> + } elseif { $a == "intermediate" } {
>> + set gcov_verify_intermediate 1
>> + set gcov_verify_calls 0
>> + set gcov_verify_branches 0
>> + set gcov_verify_lines 0
>> } elseif { $gcov_args == "" } {
>> set gcov_args $a
>> } else {
>> @@ -295,7 +357,12 @@ proc run-gcov { args } {
>> remote_upload host $testcase.gcov $testcase.gcov
>>
>> # Check that line execution counts are as expected.
>> - set lfailed [verify-lines $testname $testcase $testcase.gcov]
>> + if { $gcov_verify_lines } {
>> + # Check that line execution counts are as expected.
>> + set lfailed [verify-lines $testname $testcase $testcase.gcov]
>> + } else {
>> + set lfailed 0
>> + }
>>
>> # If requested via the .x file, check that branch and call information
>> # is correct.
>> @@ -309,15 +376,21 @@ proc run-gcov { args } {
>> } else {
>> set cfailed 0
>> }
>> + if { $gcov_verify_intermediate } {
>> + # Check that intermediate format has the expected format
>> + set ifailed [verify-intermediate $testname $testcase $testcase.gcov]
>> + } else {
>> + set ifailed 0
>> + }
>>
>> # Report whether the gcov test passed or failed. If there were
>> # multiple failures then the message is a summary.
>> - set tfailed [expr $lfailed + $bfailed + $cfailed]
>> + set tfailed [expr $lfailed + $bfailed + $cfailed + $ifailed]
>> if { $xfailed } {
>> setup_xfail "*-*-*"
>> }
>> if { $tfailed > 0 } {
>> - fail "$testname gcov: $lfailed failures in line counts, $bfailed in
>> branch percentages, $cfailed in return percentages"
>> + fail "$testname gcov: $lfailed failures in line counts, $bfailed in
>> branch percentages, $cfailed in return percentages, $ifailed in
>> intermediate format"
>> } else {
>> pass "$testname gcov"
>> clean-gcov $testcase