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>
This commit is contained in:
parent
4f9ad0b4b0
commit
5ab73173cc
9 changed files with 172 additions and 51 deletions
|
@ -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)
|
||||
|
|
|
@ -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. */
|
||||
|
||||
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 *)
|
||||
{
|
||||
char *filename = concat (json_output_base_file_name, ".gcc.json", NULL);
|
||||
FILE *outf = fopen (filename, "w");
|
||||
if (!outf)
|
||||
{
|
||||
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 (diagnostic_context *context,
|
||||
enum diagnostics_output_format format)
|
||||
diagnostic_output_format_init_json_stderr (diagnostic_context *context)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
|
||||
/* The default; do nothing. */
|
||||
break;
|
||||
diagnostic_output_format_init_json (context);
|
||||
context->final_cb = json_stderr_final_cb;
|
||||
}
|
||||
|
||||
case DIAGNOSTICS_OUTPUT_FORMAT_JSON:
|
||||
{
|
||||
/* Set up top-level JSON array. */
|
||||
if (toplevel_array == NULL)
|
||||
toplevel_array = new json::array ();
|
||||
/* Populate CONTEXT in preparation for JSON output to a file named
|
||||
BASE_FILE_NAME.gcc.json. */
|
||||
|
||||
/* 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;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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\"" } } */
|
33
gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c
Normal file
33
gcc/testsuite/c-c++-common/diagnostic-format-json-stderr-1.c
Normal file
|
@ -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 "\[\[\{\}, \]*\]" } */
|
Loading…
Add table
Reference in a new issue