From 5ab73173cca4610e59df8a3fe9cb5b30ded75aec Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Thu, 2 Jun 2022 15:38:38 -0400 Subject: Add -fdiagnostics-format={json-stderr|json-file} This commit adds -fdiagnostics-format=json-file, writing to DUMP_BASE_NAME.gcc.json, and adds -fdiagnostics-format=json-stderr, a synonym for the existing -fdiagnostics-format=json. gcc/ChangeLog: * common.opt (fdiagnostics-format=): Add json-stderr and json-file to description. (DIAGNOSTICS_OUTPUT_FORMAT_JSON): Rename to... (DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR): ...this. (diagnostics_output_format): Add json-stderr and json-file. * diagnostic-format-json.cc (json_flush_to_file): New. (json_final_cb): Convert to... (json_flush_to_file): ...this, ... (json_stderr_final_cb): ...this, and... (json_file_final_cb): ...this. (diagnostic_output_format_init): Move to diagnostic.cc. (json_output_base_file_name): New. (diagnostic_output_format_init_json): New. (diagnostic_output_format_init_json_stderr): New. (diagnostic_output_format_init_json_file): New. * diagnostic.cc (diagnostic_output_format_init): Move here from diagnostic-format-json.cc; update for changes to enum. * diagnostic.h (enum diagnostics_output_format): Rename DIAGNOSTICS_OUTPUT_FORMAT_JSON to DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR, and add DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE. (diagnostic_output_format_init): Add base_file_name param. (diagnostic_output_format_init_json_stderr): New decl. (diagnostic_output_format_init_json_file): New dec. * doc/invoke.texi (-fdiagnostics-format=): Add "json-stderr" and "json-file". Rewrite so that the existing "json" is a synonym of "json-stderr". * gcc.cc (driver_handle_option): Pass dump_base_name to diagnostic_output_format_init. * opts.cc (common_handle_option): Likewise. gcc/testsuite/ChangeLog: * c-c++-common/diagnostic-format-json-file-1.c: New test. * c-c++-common/diagnostic-format-json-stderr-1.c: New test. Signed-off-by: David Malcolm --- gcc/diagnostic-format-json.cc | 116 +++++++++++++++++++++++++++--------------- 1 file changed, 76 insertions(+), 40 deletions(-) (limited to 'gcc/diagnostic-format-json.cc') diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 62594eb..051fa6c 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -285,57 +285,93 @@ json_end_group (diagnostic_context *) cur_children_array = NULL; } -/* Callback for final cleanup for JSON output. */ +/* Flush the top-level array to OUTF. */ static void -json_final_cb (diagnostic_context *) +json_flush_to_file (FILE *outf) { - /* Flush the top-level array. */ - toplevel_array->dump (stderr); - fprintf (stderr, "\n"); + toplevel_array->dump (outf); + fprintf (outf, "\n"); delete toplevel_array; toplevel_array = NULL; } -/* Set the output format for CONTEXT to FORMAT. */ +/* Callback for final cleanup for JSON output to stderr. */ -void -diagnostic_output_format_init (diagnostic_context *context, - enum diagnostics_output_format format) +static void +json_stderr_final_cb (diagnostic_context *) +{ + json_flush_to_file (stderr); +} + +static char *json_output_base_file_name; + +/* Callback for final cleanup for JSON output to a file. */ + +static void +json_file_final_cb (diagnostic_context *) { - switch (format) + char *filename = concat (json_output_base_file_name, ".gcc.json", NULL); + FILE *outf = fopen (filename, "w"); + if (!outf) { - default: - gcc_unreachable (); - case DIAGNOSTICS_OUTPUT_FORMAT_TEXT: - /* The default; do nothing. */ - break; - - case DIAGNOSTICS_OUTPUT_FORMAT_JSON: - { - /* Set up top-level JSON array. */ - if (toplevel_array == NULL) - toplevel_array = new json::array (); - - /* Override callbacks. */ - context->begin_diagnostic = json_begin_diagnostic; - context->end_diagnostic = json_end_diagnostic; - context->begin_group_cb = json_begin_group; - context->end_group_cb = json_end_group; - context->final_cb = json_final_cb; - context->print_path = NULL; /* handled in json_end_diagnostic. */ - - /* The metadata is handled in JSON format, rather than as text. */ - context->show_cwe = false; - - /* The option is handled in JSON format, rather than as text. */ - context->show_option_requested = false; - - /* Don't colorize the text. */ - pp_show_color (context->printer) = false; - } - break; + const char *errstr = xstrerror (errno); + fnotice (stderr, "error: unable to open '%s' for writing: %s\n", + filename, errstr); + free (filename); + return; } + json_flush_to_file (outf); + fclose (outf); + free (filename); +} + +/* Populate CONTEXT in preparation for JSON output (either to stderr, or + to a file). */ + +static void +diagnostic_output_format_init_json (diagnostic_context *context) +{ + /* Set up top-level JSON array. */ + if (toplevel_array == NULL) + toplevel_array = new json::array (); + + /* Override callbacks. */ + context->begin_diagnostic = json_begin_diagnostic; + context->end_diagnostic = json_end_diagnostic; + context->begin_group_cb = json_begin_group; + context->end_group_cb = json_end_group; + context->print_path = NULL; /* handled in json_end_diagnostic. */ + + /* The metadata is handled in JSON format, rather than as text. */ + context->show_cwe = false; + + /* The option is handled in JSON format, rather than as text. */ + context->show_option_requested = false; + + /* Don't colorize the text. */ + pp_show_color (context->printer) = false; +} + +/* Populate CONTEXT in preparation for JSON output to stderr. */ + +void +diagnostic_output_format_init_json_stderr (diagnostic_context *context) +{ + diagnostic_output_format_init_json (context); + context->final_cb = json_stderr_final_cb; +} + +/* Populate CONTEXT in preparation for JSON output to a file named + BASE_FILE_NAME.gcc.json. */ + +void +diagnostic_output_format_init_json_file (diagnostic_context *context, + const char *base_file_name) +{ + diagnostic_output_format_init_json (context); + context->final_cb = json_file_final_cb; + json_output_base_file_name = xstrdup (base_file_name); } #if CHECKING_P -- cgit v1.1