From c8fda30f0cc084626af70dea607fc081f67d95f1 Mon Sep 17 00:00:00 2001 From: Martin Liska Date: Mon, 29 Oct 2018 13:00:54 +0100 Subject: [PATCH] GCOV: introduce --json-format. 2018-10-29 Martin Liska * Makefile.in: Make dependency to json.o. * doc/gcov.texi: Document new JSON format, remove old intermediate format documentation. * gcov.c (struct function_info): Come up with m_name and m_demangled_name. (function_info::function_info): Initialize it. (function_info::~function_info): Release it. (main): Rename flag_intermediate_format to flag_json_format. (print_usage): Describe --json-format. (process_args): Set flag_json_format. (output_intermediate_line): Remove. (output_intermediate_json_line): Likewise. (get_gcov_intermediate_filename): Return new extension ".gcov.json.gz". (output_intermediate_file): Implement JSON emission. (output_json_intermediate_file): Implement JSON emission. (generate_results): Use ::get_name for function name. Handle JSON output file. (read_graph_file): Use ::get_name instead of cplus_demangle. (read_count_file): Likewise. (solve_flow_graph): Likewise. (add_line_counts): Likewise. (accumulate_line_counts): Use new flag_json_format. (output_function_details): Use ::get_name instead of cplus_demangle. (output_lines): Likewise. * json.cc (test_writing_literals): Add new tests. * json.h (class literal): Add new boolean constructor. 2018-10-29 Martin Liska * g++.dg/gcov/gcov-8.C: Do not check intermediate format. * lib/gcov.exp: Remove legacy verify-intermediate. From-SVN: r265587 --- gcc/ChangeLog | 30 ++++ gcc/Makefile.in | 7 +- gcc/doc/gcov.texi | 193 +++++++++++++-------- gcc/gcov.c | 260 +++++++++++++++++------------ gcc/json.cc | 3 + gcc/json.h | 3 + gcc/testsuite/ChangeLog | 5 + gcc/testsuite/g++.dg/gcov/gcov-8.C | 4 +- gcc/testsuite/lib/gcov.exp | 55 ------ 9 files changed, 329 insertions(+), 231 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0dd2c511fe2..165ae049dba 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2018-10-29 Martin Liska + + * Makefile.in: Make dependency to json.o. + * doc/gcov.texi: Document new JSON format, remove + old intermediate format documentation. + * gcov.c (struct function_info): Come up with m_name and + m_demangled_name. + (function_info::function_info): Initialize it. + (function_info::~function_info): Release it. + (main): Rename flag_intermediate_format to flag_json_format. + (print_usage): Describe --json-format. + (process_args): Set flag_json_format. + (output_intermediate_line): Remove. + (output_intermediate_json_line): Likewise. + (get_gcov_intermediate_filename): Return new extension + ".gcov.json.gz". + (output_intermediate_file): Implement JSON emission. + (output_json_intermediate_file): Implement JSON emission. + (generate_results): Use ::get_name for function name. + Handle JSON output file. + (read_graph_file): Use ::get_name instead of cplus_demangle. + (read_count_file): Likewise. + (solve_flow_graph): Likewise. + (add_line_counts): Likewise. + (accumulate_line_counts): Use new flag_json_format. + (output_function_details): Use ::get_name instead of cplus_demangle. + (output_lines): Likewise. + * json.cc (test_writing_literals): Add new tests. + * json.h (class literal): Add new boolean constructor. + 2018-10-29 Segher Boessenkool PR rtl-optimization/87701 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index a1643321408..719a516c356 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -2899,10 +2899,13 @@ s-iov: build/gcov-iov$(build_exeext) $(BASEVER) $(DEVPHASE) $(SHELL) $(srcdir)/../move-if-change tmp-gcov-iov.h gcov-iov.h $(STAMP) s-iov -GCOV_OBJS = gcov.o +# gcov.o needs $(ZLIBINC) added to the include flags. +CFLAGS-gcov.o += $(ZLIBINC) + +GCOV_OBJS = gcov.o json.o gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_OBJS) \ - hash-table.o ggc-none.o $(LIBS) -o $@ + hash-table.o ggc-none.o $(LIBS) $(ZLIB) -o $@ GCOV_DUMP_OBJS = gcov-dump.o gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS) +$(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) \ diff --git a/gcc/doc/gcov.texi b/gcc/doc/gcov.texi index 3b1b38aebfa..8046fd78e35 100644 --- a/gcc/doc/gcov.texi +++ b/gcc/doc/gcov.texi @@ -124,7 +124,7 @@ gcov [@option{-v}|@option{--version}] [@option{-h}|@option{--help}] [@option{-c}|@option{--branch-counts}] [@option{-d}|@option{--display-progress}] [@option{-f}|@option{--function-summaries}] - [@option{-i}|@option{--intermediate-format}] + [@option{-i}|@option{--json-format}] [@option{-j}|@option{--human-readable}] [@option{-k}|@option{--use-colors}] [@option{-l}|@option{--long-file-names}] @@ -181,79 +181,142 @@ Display help about using @command{gcov} (on the standard output), and exit without doing any further processing. @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. +@itemx --json-format +Output gcov file in an easy-to-parse JSON intermediate format +which does not require source code for generation. The JSON +file is compressed with gzip compression algorithm +and the files have @file{.gcov.json.gz} extension. -The format of the intermediate @file{.gcov} file is plain text with -one entry per line +Structure of the JSON is following: @smallexample -version:@var{gcc_version} -cwd:@var{working_directory} -file:@var{source_file_name} -function:@var{start_line_number},@var{end_line_number},@var{execution_count},@var{function_name} -lcount:@var{line number},@var{execution_count},@var{has_unexecuted_block} -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) +@{ + "current_working_directory": @var{current_working_directory}, + "format_version": @var{format_version}, + "gcc_version": @var{gcc_version} + "files": [@var{file}] +@} @end smallexample -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. If there are multiple functions that -start on a single line, then corresponding lcount is repeated multiple -times. +Fields of the root element have following semantics: -Here is a sample when @option{-i} is used in conjunction with @option{-b} option: +@itemize @bullet +@item +@var{current_working_directory}: working directory where +a compilation unit was compiled + +@item +@var{format_version}: semantic version of the format + +@item +@var{gcc_version}: version of the GCC compiler +@end itemize + +Each @var{file} has the following form: + +@smallexample +@{ + "file": @var{file_name}, + "functions": [@var{function}], + "lines": [@var{line}] +@} +@end smallexample + +Fields of the @var{file} element have following semantics: + +@itemize @bullet +@item +@var{file_name}: name of the source file +@end itemize + +Each @var{function} has the following form: + +@smallexample +@{ + "blocks": @var{blocks}, + "blocks_executed": @var{blocks_executed}, + "demangled_name": "@var{demangled_name}, + "end_line": @var{end_line}, + "execution_count": @var{execution_count}, + "name": @var{name}, + "start_line": @var{start_line} +@} +@end smallexample + +Fields of the @var{function} element have following semantics: + +@itemize @bullet +@item +@var{blocks}: number of blocks that are in the function + +@item +@var{blocks_executed}: number of executed blocks of the function + +@item +@var{demangled_name}: demangled name of the function + +@item +@var{end_line}: line in the source file where the function ends + +@item +@var{execution_count}: number of executions of the function + +@item +@var{name}: name of the function + +@item +@var{start_line}: line in the source file where the function begins +@end itemize + +Each @var{line} has the following form: + +@smallexample +@{ + "branches": [@var{branch}], + "count": @var{count}, + "line_number": @var{line_number}, + "unexecuted_block": @var{unexecuted_block} +@} +@end smallexample + +Branches are present only with @var{-b} option. +Fields of the @var{line} element have following semantics: + +@itemize @bullet +@item +@var{count}: number of executions of the line + +@item +@var{line_number}: line number + +@item +@var{unexecuted_block}: flag whether the line contains an unexecuted block +(not all statements on the line are executed) +@end itemize + +Each @var{branch} has the following form: @smallexample -version: 8.1.0 20180103 -cwd:/home/gcc/testcase -file:tmp.cpp -function:7,7,0,_ZN3FooIcEC2Ev -function:7,7,1,_ZN3FooIiEC2Ev -function:8,8,0,_ZN3FooIcE3incEv -function:8,8,2,_ZN3FooIiE3incEv -function:18,37,1,main -lcount:7,0,1 -lcount:7,1,0 -lcount:8,0,1 -lcount:8,2,0 -lcount:18,1,0 -lcount:21,1,0 -branch:21,taken -branch:21,nottaken -lcount:23,1,0 -branch:23,taken -branch:23,nottaken -lcount:24,1,0 -branch:24,taken -branch:24,nottaken -lcount:25,1,0 -lcount:27,11,0 -branch:27,taken -branch:27,taken -lcount:28,10,0 -lcount:30,1,1 -branch:30,nottaken -branch:30,taken -lcount:32,1,0 -branch:32,nottaken -branch:32,taken -lcount:33,0,1 -branch:33,notexec -branch:33,notexec -lcount:35,1,0 -branch:35,taken -branch:35,nottaken -lcount:36,1,0 +@{ + "count": @var{count}, + "fallthrough": @var{fallthrough}, + "throw": @var{throw} +@} @end smallexample +Fields of the @var{branch} element have following semantics: + +@itemize @bullet +@item +@var{count}: number of executions of the branch + +@item +@var{fallthrough}: true when the branch is a fall through branch + +@item +@var{throw}: true when the branch is an exceptional branch +@end itemize + @item -j @itemx --human-readable Write counts in human readable format (like 24.6k). @@ -842,7 +905,7 @@ some summary information. It is not recommended to access the coverage files directly. Consumers should use the intermediate format that is provided -by @command{gcov} tool via @option{--intermediate-format} option. +by @command{gcov} tool via @option{--json-format} option. @node Cross-profiling @section Data File Relocation to Support Cross-Profiling diff --git a/gcc/gcov.c b/gcc/gcov.c index e255e4e3922..26d352ce7f1 100644 --- a/gcc/gcov.c +++ b/gcc/gcov.c @@ -44,7 +44,10 @@ along with Gcov; see the file COPYING3. If not see #include "version.h" #include "demangle.h" #include "color-macros.h" +#include "pretty-print.h" +#include "json.h" +#include #include #include "md5.h" @@ -221,6 +224,10 @@ line_info::has_block (block_info *needle) return std::find (blocks.begin (), blocks.end (), needle) != blocks.end (); } +/* Output demangled function names. */ + +static int flag_demangled_names = 0; + /* Describes a single function. Contains an array of basic blocks. */ struct function_info @@ -241,8 +248,8 @@ struct function_info } /* Name of function. */ - char *name; - char *demangled_name; + char *m_name; + char *m_demangled_name; unsigned ident; unsigned lineno_checksum; unsigned cfg_checksum; @@ -284,6 +291,32 @@ struct function_info /* Next function. */ struct function_info *next; + + /* Get demangled name of a function. The demangled name + is converted when it is used for the first time. */ + char *get_demangled_name () + { + if (m_demangled_name == NULL) + { + m_demangled_name = cplus_demangle (m_name, DMGL_PARAMS); + if (!m_demangled_name) + m_demangled_name = m_name; + } + + return m_demangled_name; + } + + /* Get name of the function based on flag_demangled_names. */ + char *get_name () + { + return flag_demangled_names ? get_demangled_name () : m_name; + } + + /* Return number of basic blocks (without entry and exit block). */ + unsigned get_block_count () + { + return blocks.size () - 2; + } }; /* Function info comparer that will sort functions according to starting @@ -477,13 +510,9 @@ static int flag_use_stdout = 0; static int flag_display_progress = 0; -/* Output *.gcov file in intermediate format used by 'lcov'. */ +/* Output *.gcov file in JSON intermediate format used by consumers. */ -static int flag_intermediate_format = 0; - -/* Output demangled function names. */ - -static int flag_demangled_names = 0; +static int flag_json_format = 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, @@ -576,7 +605,7 @@ static char *mangle_name (const char *, char *); static void release_structures (void); extern int main (int, char **); -function_info::function_info (): name (NULL), demangled_name (NULL), +function_info::function_info (): m_name (NULL), m_demangled_name (NULL), ident (0), lineno_checksum (0), cfg_checksum (0), has_catch (0), artificial (0), is_group (0), blocks (), blocks_executed (0), counts (), @@ -596,9 +625,9 @@ function_info::~function_info () free (arc); } } - if (flag_demangled_names && demangled_name != name) - free (demangled_name); - free (name); + if (m_demangled_name != m_name) + free (m_demangled_name); + free (m_name); } bool function_info::group_line_p (unsigned n, unsigned src_idx) @@ -807,7 +836,7 @@ main (int argc, char **argv) argc - first_arg); process_file (argv[argno]); - if (flag_intermediate_format || argno == argc - 1) + if (flag_json_format || argno == argc - 1) { process_all_functions (); generate_results (argv[argno]); @@ -836,7 +865,7 @@ print_usage (int error_p) fnotice (file, " -d, --display-progress Display progress information\n"); fnotice (file, " -f, --function-summaries Output summaries for each function\n"); fnotice (file, " -h, --help Print this help, then exit\n"); - fnotice (file, " -i, --intermediate-format Output .gcov file in intermediate text format\n"); + fnotice (file, " -i, --json-format Output JSON intermediate format into .gcov.json.gz file\n"); fnotice (file, " -j, --human-readable Output human readable numbers\n"); fnotice (file, " -k, --use-colors Emit colored output\n"); fnotice (file, " -l, --long-file-names Use long output file names for included\n\ @@ -881,7 +910,7 @@ 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' }, + { "json-format", no_argument, NULL, 'i' }, { "human-readable", no_argument, NULL, 'j' }, { "no-output", no_argument, NULL, 'n' }, { "long-file-names", no_argument, NULL, 'l' }, @@ -963,12 +992,12 @@ process_args (int argc, char **argv) flag_unconditional = 1; break; case 'i': - flag_intermediate_format = 1; - flag_gcov_file = 1; - break; - case 'd': - flag_display_progress = 1; - break; + flag_json_format = 1; + flag_gcov_file = 1; + break; + case 'd': + flag_display_progress = 1; + break; case 'x': flag_hash_filenames = 1; break; @@ -990,17 +1019,23 @@ process_args (int argc, char **argv) return optind; } -/* Output intermediate LINE sitting on LINE_NUM to output file F. */ +/* Output intermediate LINE sitting on LINE_NUM to JSON OBJECT. */ static void -output_intermediate_line (FILE *f, line_info *line, unsigned line_num) +output_intermediate_json_line (json::array *object, + line_info *line, unsigned line_num) { if (!line->exists) return; - fprintf (f, "lcount:%u,%s,%d\n", line_num, - format_gcov (line->count, 0, -1), - line->has_unexecuted_block); + json::object *lineo = new json::object (); + lineo->set ("line_number", new json::number (line_num)); + lineo->set ("count", new json::number (line->count)); + lineo->set ("unexecuted_block", + new json::literal (line->has_unexecuted_block)); + + json::array *branches = new json::array (); + lineo->set ("branches", branches); vector::const_iterator it; if (flag_branches) @@ -1009,21 +1044,16 @@ output_intermediate_line (FILE *f, line_info *line, unsigned line_num) { if (!(*it)->is_unconditional && !(*it)->is_call_non_return) { - const char *branch_type; - /* branch:, - branch_coverage_infoype - : notexec (Branch not executed) - : taken (Branch executed and taken) - : nottaken (Branch executed, but not taken) - */ - if ((*it)->src->count) - branch_type - = ((*it)->count > 0) ? "taken" : "nottaken"; - else - branch_type = "notexec"; - fprintf (f, "branch:%d,%s\n", line_num, branch_type); + json::object *branch = new json::object (); + branch->set ("count", new json::number ((*it)->count)); + branch->set ("throw", new json::literal ((*it)->is_throw)); + branch->set ("fallthrough", + new json::literal ((*it)->fall_through)); + branches->append (branch); } } + + object->append (lineo); } /* Get the name of the gcov file. The return value must be free'd. @@ -1038,7 +1068,7 @@ output_intermediate_line (FILE *f, line_info *line, unsigned line_num) static char * get_gcov_intermediate_filename (const char *file_name) { - const char *gcov = ".gcov"; + const char *gcov = ".gcov.json.gz"; char *result; const char *cptr; @@ -1051,34 +1081,44 @@ get_gcov_intermediate_filename (const char *file_name) 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. - -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. */ +/* Output the result in JSON intermediate format. + Source info SRC is dumped into JSON_FILES which is JSON array. */ static void -output_intermediate_file (FILE *gcov_file, source_info *src) +output_json_intermediate_file (json::array *json_files, source_info *src) { - fprintf (gcov_file, "version:%s\n", version_string); - fprintf (gcov_file, "file:%s\n", src->name); /* source file name */ - fprintf (gcov_file, "cwd:%s\n", bbg_cwd); + json::object *root = new json::object (); + json_files->append (root); + + root->set ("file", new json::string (src->name)); + + json::array *functions = new json::array (); + root->set ("functions", functions); std::sort (src->functions.begin (), src->functions.end (), function_line_start_cmp ()); for (vector::iterator it = src->functions.begin (); it != src->functions.end (); it++) { - /* function:,, */ - fprintf (gcov_file, "function:%d,%d,%s,%s\n", (*it)->start_line, - (*it)->end_line, format_gcov ((*it)->blocks[0].count, 0, -1), - flag_demangled_names ? (*it)->demangled_name : (*it)->name); + json::object *function = new json::object (); + 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 ("end_line", new json::number ((*it)->end_line)); + function->set ("blocks", + new json::number ((*it)->get_block_count ())); + function->set ("blocks_executed", + new json::number ((*it)->blocks_executed)); + function->set ("execution_count", + new json::number ((*it)->blocks[0].count)); + + functions->append (function); } + json::array *lineso = new json::array (); + root->set ("lines", lineso); + for (unsigned line_num = 1; line_num <= src->lines.size (); line_num++) { vector fns = src->get_functions_at_location (line_num); @@ -1091,13 +1131,13 @@ output_intermediate_file (FILE *gcov_file, source_info *src) for (unsigned i = 0; i < lines.size (); i++) { line_info *line = &lines[i]; - output_intermediate_line (gcov_file, line, line_num + i); + output_intermediate_json_line (lineso, line, line_num + i); } } /* Follow with lines associated with the source file. */ if (line_num < src->lines.size ()) - output_intermediate_line (gcov_file, &src->lines[line_num], line_num); + output_intermediate_json_line (lineso, &src->lines[line_num], line_num); } } @@ -1301,8 +1341,7 @@ output_gcov_file (const char *file_name, source_info *src) static void generate_results (const char *file_name) { - FILE *gcov_intermediate_file = NULL; - char *gcov_intermediate_filename = NULL; + char *gcov_intermediate_filename; for (vector::iterator it = functions.begin (); it != functions.end (); it++) @@ -1311,7 +1350,7 @@ generate_results (const char *file_name) coverage_info coverage; memset (&coverage, 0, sizeof (coverage)); - coverage.name = flag_demangled_names ? fn->demangled_name : fn->name; + coverage.name = fn->get_name (); add_line_counts (flag_function_summary ? &coverage : NULL, fn); if (flag_function_summary) { @@ -1333,18 +1372,15 @@ generate_results (const char *file_name) file_name = canonicalize_name (file_name); } - if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout) - { - /* 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; - } - } + gcov_intermediate_filename = get_gcov_intermediate_filename (file_name); + + json::object *root = new json::object (); + root->set ("format_version", new json::string ("1")); + root->set ("gcc_version", new json::string (version_string)); + root->set ("current_working_directory", new json::string (bbg_cwd)); + + json::array *json_files = new json::array (); + root->set ("files", json_files); for (vector::iterator it = sources.begin (); it != sources.end (); it++) @@ -1372,11 +1408,8 @@ generate_results (const char *file_name) total_executed += src->coverage.lines_executed; if (flag_gcov_file) { - if (flag_intermediate_format) - /* Output the intermediate format without requiring source - files. This outputs a section to a *single* file. */ - output_intermediate_file ((flag_use_stdout - ? stdout : gcov_intermediate_file), src); + if (flag_json_format) + output_json_intermediate_file (json_files, src); else { if (flag_use_stdout) @@ -1393,11 +1426,35 @@ generate_results (const char *file_name) } } - if (flag_gcov_file && flag_intermediate_format && !flag_use_stdout) + if (flag_gcov_file && flag_json_format) { - /* Now we've finished writing the intermediate file. */ - fclose (gcov_intermediate_file); - XDELETEVEC (gcov_intermediate_filename); + if (flag_use_stdout) + { + root->dump (stdout); + printf ("\n"); + } + else + { + pretty_printer pp; + root->print (&pp); + pp_formatted_text (&pp); + + gzFile output = gzopen (gcov_intermediate_filename, "w"); + if (output == NULL) + { + fnotice (stderr, "Cannot open JSON output file %s\n", + gcov_intermediate_filename); + return; + } + + if (gzputs (output, pp_formatted_text (&pp)) == EOF + || gzclose (output)) + { + fnotice (stderr, "Error writing JSON output file %s\n", + gcov_intermediate_filename); + return; + } + } } if (!file_name) @@ -1634,13 +1691,7 @@ read_graph_file (void) fn = new function_info (); functions.push_back (fn); - 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->m_name = function_name; fn->ident = ident; fn->lineno_checksum = lineno_checksum; fn->cfg_checksum = cfg_checksum; @@ -1656,7 +1707,7 @@ read_graph_file (void) { if (!fn->blocks.empty ()) fnotice (stderr, "%s:already seen blocks for '%s'\n", - bbg_file_name, fn->name); + bbg_file_name, fn->get_name ()); else fn->blocks.resize (gcov_read_unsigned ()); } @@ -1862,7 +1913,7 @@ read_count_file (void) { mismatch:; fnotice (stderr, "%s:profile mismatch for '%s'\n", - da_file_name, fn->name); + da_file_name, fn->get_name ()); goto cleanup; } } @@ -1927,12 +1978,12 @@ solve_flow_graph (function_info *fn) if (fn->blocks.size () < 2) fnotice (stderr, "%s:'%s' lacks entry and/or exit blocks\n", - bbg_file_name, fn->name); + bbg_file_name, fn->get_name ()); else { if (fn->blocks[ENTRY_BLOCK].num_pred) fnotice (stderr, "%s:'%s' has arcs to entry block\n", - bbg_file_name, fn->name); + bbg_file_name, fn->get_name ()); else /* We can't deduce the entry block counts from the lack of predecessors. */ @@ -1940,7 +1991,7 @@ solve_flow_graph (function_info *fn) if (fn->blocks[EXIT_BLOCK].num_succ) fnotice (stderr, "%s:'%s' has arcs from exit block\n", - bbg_file_name, fn->name); + bbg_file_name, fn->get_name ()); else /* Likewise, we can't deduce exit block counts from the lack of its successors. */ @@ -2149,7 +2200,7 @@ solve_flow_graph (function_info *fn) if (!fn->blocks[i].count_valid) { fnotice (stderr, "%s:graph is unsolvable for '%s'\n", - bbg_file_name, fn->name); + bbg_file_name, fn->get_name ()); break; } } @@ -2553,7 +2604,8 @@ add_line_counts (coverage_info *coverage, function_info *fn) } if (!has_any_line) - fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, fn->name); + fnotice (stderr, "%s:no lines for '%s'\n", bbg_file_name, + fn->get_name ()); } /* Accumulate info for LINE that belongs to SRC source file. If ADD_COVERAGE @@ -2633,7 +2685,7 @@ accumulate_line_counts (source_info *src) /* If not using intermediate mode, sum lines of group functions and add them to lines that live in a source file. */ - if (!flag_intermediate_format) + if (!flag_json_format) for (vector::iterator it = src->functions.begin (); it != src->functions.end (); it++) { @@ -2895,7 +2947,7 @@ output_line_details (FILE *f, const line_info *line, unsigned line_num) /* Output detail statistics about function FN to file F. */ static void -output_function_details (FILE *f, const function_info *fn) +output_function_details (FILE *f, function_info *fn) { if (!flag_branches) return; @@ -2908,15 +2960,13 @@ output_function_details (FILE *f, const function_info *fn) if (arc->fake) return_count -= arc->count; - fprintf (f, "function %s", - flag_demangled_names ? fn->demangled_name : fn->name); + fprintf (f, "function %s", fn->get_name ()); fprintf (f, " called %s", format_gcov (called_count, 0, -1)); fprintf (f, " returned %s", format_gcov (return_count, called_count, 0)); fprintf (f, " blocks executed %s", - format_gcov (fn->blocks_executed, fn->blocks.size () - 2, - 0)); + format_gcov (fn->blocks_executed, fn->get_block_count (), 0)); fprintf (f, "\n"); } @@ -3028,9 +3078,7 @@ output_lines (FILE *gcov_file, const source_info *src) fprintf (gcov_file, FN_SEPARATOR); - string fn_name - = flag_demangled_names ? fn->demangled_name : fn->name; - + string fn_name = fn->get_name (); if (flag_use_colors) { fn_name.insert (0, SGR_SEQ (COLOR_FG_CYAN)); diff --git a/gcc/json.cc b/gcc/json.cc index 3ead98073f6..a0c439560e9 100644 --- a/gcc/json.cc +++ b/gcc/json.cc @@ -296,6 +296,9 @@ test_writing_literals () assert_print_eq (literal (JSON_TRUE), "true"); assert_print_eq (literal (JSON_FALSE), "false"); assert_print_eq (literal (JSON_NULL), "null"); + + assert_print_eq (literal (true), "true"); + assert_print_eq (literal (false), "false"); } /* Run all of the selftests within this file. */ diff --git a/gcc/json.h b/gcc/json.h index 154d9e1b575..e99141e71e1 100644 --- a/gcc/json.h +++ b/gcc/json.h @@ -154,6 +154,9 @@ class literal : public value public: literal (enum kind kind) : m_kind (kind) {} + /* Construct literal for a boolean value. */ + literal (bool value): m_kind (value ? JSON_TRUE : JSON_FALSE) {} + enum kind get_kind () const FINAL OVERRIDE { return m_kind; } void print (pretty_printer *pp) const FINAL OVERRIDE; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 40ea5a7b436..5584b886f1d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-10-29 Martin Liska + + * g++.dg/gcov/gcov-8.C: Do not check intermediate format. + * lib/gcov.exp: Remove legacy verify-intermediate. + 2018-10-28 Kugan Vivekanandarajah * gcc.dg/gimplefe-30.c: New test. diff --git a/gcc/testsuite/g++.dg/gcov/gcov-8.C b/gcc/testsuite/g++.dg/gcov/gcov-8.C index 7acab4672ff..1c97c35d8c1 100644 --- a/gcc/testsuite/g++.dg/gcov/gcov-8.C +++ b/gcc/testsuite/g++.dg/gcov/gcov-8.C @@ -1,5 +1,3 @@ -/* Verify that intermediate coverage format can be generated for simple code. */ - /* { dg-options "-fprofile-arcs -ftest-coverage" } */ /* { dg-do run { target native } } */ @@ -32,4 +30,4 @@ int main() foo(); } -/* { dg-final { run-gcov intermediate { -i -b gcov-8.C } } } */ +/* { dg-final { run-gcov { -b gcov-8.C } } } */ diff --git a/gcc/testsuite/lib/gcov.exp b/gcc/testsuite/lib/gcov.exp index f35ca59fbe3..a7b8c0a1ef4 100644 --- a/gcc/testsuite/lib/gcov.exp +++ b/gcc/testsuite/lib/gcov.exp @@ -83,61 +83,6 @@ proc verify-lines { testname testcase file } { } -# -# 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\]+),(\[01\])" $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 - } - close $fd - return $failed -} - - # # verify-branches -- check that branch percentages are as expected # -- 2.30.2