diff options
author | David Malcolm <dmalcolm@redhat.com> | 2022-06-02 15:38:38 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2022-06-02 15:38:38 -0400 |
commit | 5ab73173cca4610e59df8a3fe9cb5b30ded75aec (patch) | |
tree | 4a87b670311228c8d5c16ad9af7d0c70fcd10061 /gcc | |
parent | 4f9ad0b4b0a8c780b85a06096b9926ca85d7a9a6 (diff) | |
download | gcc-5ab73173cca4610e59df8a3fe9cb5b30ded75aec.zip gcc-5ab73173cca4610e59df8a3fe9cb5b30ded75aec.tar.gz gcc-5ab73173cca4610e59df8a3fe9cb5b30ded75aec.tar.bz2 |
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 <dmalcolm@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/common.opt | 10 | ||||
-rw-r--r-- | gcc/diagnostic-format-json.cc | 116 | ||||
-rw-r--r-- | gcc/diagnostic.cc | 26 | ||||
-rw-r--r-- | gcc/diagnostic.h | 11 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 17 | ||||
-rw-r--r-- | gcc/gcc.cc | 2 | ||||
-rw-r--r-- | gcc/opts.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/diagnostic-format-json-file-1.c | 8 | ||||
-rw-r--r-- | gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c | 33 |
9 files changed, 173 insertions, 52 deletions
diff --git a/gcc/common.opt b/gcc/common.opt index 8a0dafc..3237ce9 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -1390,7 +1390,7 @@ Common Joined RejectNegative UInteger fdiagnostics-format= Common Joined RejectNegative Enum(diagnostics_output_format) --fdiagnostics-format=[text|json] Select output format. +-fdiagnostics-format=[text|json|json-stderr|json-file] Select output format. fdiagnostics-escape-format= Common Joined RejectNegative Enum(diagnostics_escape_format) @@ -1425,7 +1425,13 @@ EnumValue Enum(diagnostics_output_format) String(text) Value(DIAGNOSTICS_OUTPUT_FORMAT_TEXT) EnumValue -Enum(diagnostics_output_format) String(json) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON) +Enum(diagnostics_output_format) String(json) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR) + +EnumValue +Enum(diagnostics_output_format) String(json-stderr) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR) + +EnumValue +Enum(diagnostics_output_format) String(json-file) Value(DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE) fdiagnostics-parseable-fixits Common Var(flag_diagnostics_parseable_fixits) 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 diff --git a/gcc/diagnostic.cc b/gcc/diagnostic.cc index fef1146..2550483 100644 --- a/gcc/diagnostic.cc +++ b/gcc/diagnostic.cc @@ -2072,6 +2072,32 @@ auto_diagnostic_group::~auto_diagnostic_group () } } +/* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for + file-based output formats. */ + +void +diagnostic_output_format_init (diagnostic_context *context, + const char *base_file_name, + enum diagnostics_output_format format) +{ + switch (format) + { + default: + gcc_unreachable (); + case DIAGNOSTICS_OUTPUT_FORMAT_TEXT: + /* The default; do nothing. */ + break; + + case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR: + diagnostic_output_format_init_json_stderr (context); + break; + + case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE: + diagnostic_output_format_init_json_file (context, base_file_name); + break; + } +} + /* Implementation of diagnostic_path::num_events vfunc for simple_diagnostic_path: simply get the number of events in the vec. */ diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h index 3ca3297..dd3af03 100644 --- a/gcc/diagnostic.h +++ b/gcc/diagnostic.h @@ -59,8 +59,11 @@ enum diagnostics_output_format /* The default: textual output. */ DIAGNOSTICS_OUTPUT_FORMAT_TEXT, - /* JSON-based output. */ - DIAGNOSTICS_OUTPUT_FORMAT_JSON + /* JSON-based output, to stderr. */ + DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR, + + /* JSON-based output, to a file. */ + DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE }; /* An enum for controlling how diagnostic_paths should be printed. */ @@ -577,7 +580,11 @@ extern char *file_name_as_prefix (diagnostic_context *, const char *); extern char *build_message_string (const char *, ...) ATTRIBUTE_PRINTF_1; extern void diagnostic_output_format_init (diagnostic_context *, + const char *base_file_name, enum diagnostics_output_format); +extern void diagnostic_output_format_init_json_stderr (diagnostic_context *context); +extern void diagnostic_output_format_init_json_file (diagnostic_context *context, + const char *base_file_name); /* Compute the number of digits in the decimal representation of an integer. */ extern int num_digits (int); diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 71098d8..d85b66f 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -301,7 +301,7 @@ Objective-C and Objective-C++ Dialects}. -fdiagnostics-show-location=@r{[}once@r{|}every-line@r{]} @gol -fdiagnostics-color=@r{[}auto@r{|}never@r{|}always@r{]} @gol -fdiagnostics-urls=@r{[}auto@r{|}never@r{|}always@r{]} @gol --fdiagnostics-format=@r{[}text@r{|}json@r{]} @gol +-fdiagnostics-format=@r{[}text@r{|}json@r{|}json-stderr@r{|}json-file@r{]} @gol -fno-diagnostics-show-option -fno-diagnostics-show-caret @gol -fno-diagnostics-show-labels -fno-diagnostics-show-line-numbers @gol -fno-diagnostics-show-cwe @gol @@ -5305,14 +5305,19 @@ Unicode characters. For the example above, the following will be printed: @item -fdiagnostics-format=@var{FORMAT} @opindex fdiagnostics-format Select a different format for printing diagnostics. -@var{FORMAT} is @samp{text} or @samp{json}. +@var{FORMAT} is @samp{text}, @samp{json}, @samp{json-stderr}, +or @samp{json-file}. + The default is @samp{text}. -The @samp{json} format consists of a top-level JSON array containing JSON -objects representing the diagnostics. +The @samp{json} format is a synonym for @samp{json-stderr}. +The @samp{json-stderr} and @samp{json-file} formats are identical, apart from +where the JSON is emitted to - with the former, the JSON is emitted to stderr, +whereas with @samp{json-file} it is written to @file{@var{source}.gcc.json}. -The JSON is emitted as one line, without formatting; the examples below -have been formatted for clarity. +The emitted JSON consists of a top-level JSON array containing JSON objects +representing the diagnostics. The JSON is emitted as one line, without +formatting; the examples below have been formatted for clarity. Diagnostics can have child diagnostics. For example, this error and note: @@ -4335,7 +4335,7 @@ driver_handle_option (struct gcc_options *opts, break; case OPT_fdiagnostics_format_: - diagnostic_output_format_init (dc, + diagnostic_output_format_init (dc, opts->x_dump_base_name, (enum diagnostics_output_format)value); break; diff --git a/gcc/opts.cc b/gcc/opts.cc index f0c5c4d..bf06a55 100644 --- a/gcc/opts.cc +++ b/gcc/opts.cc @@ -2800,7 +2800,7 @@ common_handle_option (struct gcc_options *opts, break; case OPT_fdiagnostics_format_: - diagnostic_output_format_init (dc, + diagnostic_output_format_init (dc, opts->x_dump_base_name, (enum diagnostics_output_format)value); break; diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-file-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-file-1.c new file mode 100644 index 0000000..ddac780 --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-file-1.c @@ -0,0 +1,8 @@ +/* Check that -fdiagnostics-format=json-file works. */ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=json-file" } */ + +#warning message + +/* Verify that some JSON was written to a file with the expected name. */ +/* { dg-final { scan-file "diagnostic-format-json-file-1.c.gcc.json" "\"message\": \"#warning message\"" } } */ diff --git a/gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c b/gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c new file mode 100644 index 0000000..02f780b --- /dev/null +++ b/gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c @@ -0,0 +1,33 @@ +/* Check that "json" and "json-stderr" are synonymous when used as + arguments to "-fdiagnostics-format=". */ +/* { dg-do compile } */ +/* { dg-options "-fdiagnostics-format=json-stderr" } */ + +#error message + +/* Use dg-regexp to consume the JSON output starting with + the innermost values, and working outwards. + We can't rely on any ordering of the keys. */ + +/* { dg-regexp "\"kind\": \"error\"" } */ +/* { dg-regexp "\"column-origin\": 1" } */ +/* { dg-regexp "\"escape-source\": false" } */ +/* { dg-regexp "\"message\": \"#error message\"" } */ + +/* { dg-regexp "\"caret\": \{" } */ +/* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-stderr-1.c\"" } */ +/* { dg-regexp "\"line\": 6" } */ +/* { dg-regexp "\"column\": 2" } */ +/* { dg-regexp "\"display-column\": 2" } */ +/* { dg-regexp "\"byte-column\": 2" } */ + +/* { dg-regexp "\"finish\": \{" } */ +/* { dg-regexp "\"file\": \"\[^\n\r\"\]*diagnostic-format-json-stderr-1.c\"" } */ +/* { dg-regexp "\"line\": 6" } */ +/* { dg-regexp "\"column\": 6" } */ +/* { dg-regexp "\"display-column\": 6" } */ +/* { dg-regexp "\"byte-column\": 6" } */ + +/* { dg-regexp "\"locations\": \[\[\{\}, \]*\]" } */ +/* { dg-regexp "\"children\": \[\[\]\[\]\]" } */ +/* { dg-regexp "\[\[\{\}, \]*\]" } */ |