aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostic-format-json.cc
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2023-12-06 12:35:44 -0500
committerDavid Malcolm <dmalcolm@redhat.com>2023-12-06 12:35:44 -0500
commit3bd8241a1f19827586cbed7832a24f44ff3e22ac (patch)
tree5d30aa8826b5c856b8fd973286f095a85d7bfd4f /gcc/diagnostic-format-json.cc
parent8fc4e6c397e1ce64bec6f9fed148950821cc79e7 (diff)
downloadgcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.zip
gcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.tar.gz
gcc-3bd8241a1f19827586cbed7832a24f44ff3e22ac.tar.bz2
diagnostics: prettify JSON output formats
Previously our JSON output emitted the JSON all on one line, with no indentation to show the structure of the values. Although it's easy to reformat such output (e.g. with "python -m json.tool"), I've found it's a pain to need to do so e.g. my text editor sometimes hangs when opening a multimegabyte json file all on one line. Similarly diff-ing is easier if the json is already formatted. This patch add whitespace to json output to show the structure. It turned out to be fairly easy to implement using pretty_printer's existing indentation machinery. The patch uses this formatting for the various JSON-based diagnostic output formats. For example, with this patch, the output from fdiagnostics-format=json-stderr looks like: [{"kind": "warning", "message": "stack-based buffer overflow", "option": "-Wanalyzer-out-of-bounds", "option_url": "https://gcc.gnu.org/onlinedocs/gcc/Static-Analyzer-Options.html#index-Wanalyzer-out-of-bounds", "children": [{"kind": "note", "message": "write of 350 bytes to beyond the end of ‘buf’", "locations": [{"caret": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c", "line": 20, "display-column": 3, "byte-column": 3, "column": 3}, "finish": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c", "line": 20, "display-column": 27, "byte-column": 27, "column": 27}}], "escape-source": false}, {"kind": "note", "message": "valid subscripts for ‘buf’ are ‘[0]’ to ‘[99]’", "locations": [{"caret": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c", "line": 20, "display-column": 3, "byte-column": 3, "column": 3}, "finish": {"file": "../../src/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-19.c", "line": 20, "display-column": 27, "byte-column": 27, "column": 27}}], "escape-source": false}], "column-origin": 1, ...snip...] I was able to update almost all of our DejaGnu test cases for JSON to handle this format tweak, and IMHO it improved the readability of these test cases, but a couple were more awkward. Hence I added -fno-diagnostics-json-formatting as an option to disable this formatting. The formatting does not affect the output of -fsave-optimization-record or the JSON output from gcov (but this could be enabled if desirable). gcc/analyzer/ChangeLog: * engine.cc (dump_analyzer_json): Use flag_diagnostics_json_formatting. gcc/ChangeLog: * common.opt (fdiagnostics-json-formatting): New. * diagnostic-format-json.cc: Add "formatted" boolean to json_output_format and subclasses, and to the diagnostic_output_format_init_json_* functions. Use it when printing JSON. * diagnostic-format-sarif.cc: Likewise for sarif_builder, sarif_output_format, and the various diagnostic_output_format_init_sarif_* functions. * diagnostic.cc (diagnostic_output_format_init): Add "json_formatting" boolean and pass on to the various cases. * diagnostic.h (diagnostic_output_format_init): Add "json_formatted" param. (diagnostic_output_format_init_json_stderr): Add "formatted" param (diagnostic_output_format_init_json_file): Likewise. (diagnostic_output_format_init_sarif_stderr): Likewise. (diagnostic_output_format_init_sarif_file): Likewise. (diagnostic_output_format_init_sarif_stream): Likewise. * doc/invoke.texi (-fdiagnostics-format=json): Remove discussion about JSON output needing formatting. (-fno-diagnostics-json-formatting): Add. * gcc.cc (driver_handle_option): Use opts->x_flag_diagnostics_json_formatting. * gcov.cc (generate_results): Pass "false" for new formatting option when printing json. * json.cc (value::dump): Add new "formatted" param. (object::print): Likewise, using it to add whitespace to format the JSON output. (array::print): Likewise. (float_number::print): Add new "formatted" param. (integer_number::print): Likewise. (string::print): Likewise. (literal::print): Likewise. (selftest::assert_print_eq): Add "formatted" param. (ASSERT_PRINT_EQ): Add "FORMATTED" param. (selftest::test_writing_objects): Test both formatted and unformatted printing. (selftest::test_writing_arrays): Likewise. (selftest::test_writing_float_numbers): Update for new param of ASSERT_PRINT_EQ. (selftest::test_writing_integer_numbers): Likewise. (selftest::test_writing_strings): Likewise. (selftest::test_writing_literals): Likewise. (selftest::test_formatting): New. (selftest::json_cc_tests): Call it. * json.h (value::print): Add "formatted" param. (value::dump): Likewise. (object::print): Likewise. (array::print): Likewise. (float_number::print): Likewise. (integer_number::print): Likewise. (string::print): Likewise. (literal::print): Likewise. * optinfo-emit-json.cc (optrecord_json_writer::write): Pass "false" for new formatting option when printing json. (selftest::test_building_json_from_dump_calls): Likewise. * opts.cc (common_handle_option): Use opts->x_flag_diagnostics_json_formatting. gcc/testsuite/ChangeLog: * c-c++-common/diagnostic-format-json-1.c: Update expected JSON output to reflect whitespace. * c-c++-common/diagnostic-format-json-2.c: Likewise. * c-c++-common/diagnostic-format-json-3.c: Likewise. * c-c++-common/diagnostic-format-json-4.c: Likewise. * c-c++-common/diagnostic-format-json-5.c: Likewise. * c-c++-common/diagnostic-format-json-stderr-1.c: Likewise. * g++.dg/pr90462.C: Add -fno-diagnostics-json-formatting. * gcc.dg/analyzer/malloc-sarif-1.c: Likewise. * gcc.dg/plugin/diagnostic-test-paths-3.c: Update expected JSON output to reflect whitespace. * gfortran.dg/diagnostic-format-json-1.F90: Likewise. * gfortran.dg/diagnostic-format-json-2.F90: Likewise. * gfortran.dg/diagnostic-format-json-3.F90: Likewise. Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r--gcc/diagnostic-format-json.cc26
1 files changed, 18 insertions, 8 deletions
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc
index 418db74..c013192 100644
--- a/gcc/diagnostic-format-json.cc
+++ b/gcc/diagnostic-format-json.cc
@@ -56,11 +56,13 @@ public:
}
protected:
- json_output_format (diagnostic_context &context)
+ json_output_format (diagnostic_context &context,
+ bool formatted)
: diagnostic_output_format (context),
m_toplevel_array (new json::array ()),
m_cur_group (nullptr),
- m_cur_children_array (nullptr)
+ m_cur_children_array (nullptr),
+ m_formatted (formatted)
{
}
@@ -68,7 +70,7 @@ protected:
void
flush_to_file (FILE *outf)
{
- m_toplevel_array->dump (outf);
+ m_toplevel_array->dump (outf, m_formatted);
fprintf (outf, "\n");
delete m_toplevel_array;
m_toplevel_array = nullptr;
@@ -84,6 +86,8 @@ private:
/* The JSON array for the "children" array within the current diagnostic
group. */
json::array *m_cur_children_array;
+
+ bool m_formatted;
};
/* Generate a JSON object for LOC. */
@@ -301,8 +305,9 @@ json_output_format::on_end_diagnostic (const diagnostic_info &diagnostic,
class json_stderr_output_format : public json_output_format
{
public:
- json_stderr_output_format (diagnostic_context &context)
- : json_output_format (context)
+ json_stderr_output_format (diagnostic_context &context,
+ bool formatted)
+ : json_output_format (context, formatted)
{
}
~json_stderr_output_format ()
@@ -315,8 +320,9 @@ class json_file_output_format : public json_output_format
{
public:
json_file_output_format (diagnostic_context &context,
+ bool formatted,
const char *base_file_name)
- : json_output_format (context),
+ : json_output_format (context, formatted),
m_base_file_name (xstrdup (base_file_name))
{
}
@@ -367,10 +373,12 @@ diagnostic_output_format_init_json (diagnostic_context *context)
/* Populate CONTEXT in preparation for JSON output to stderr. */
void
-diagnostic_output_format_init_json_stderr (diagnostic_context *context)
+diagnostic_output_format_init_json_stderr (diagnostic_context *context,
+ bool formatted)
{
diagnostic_output_format_init_json (context);
- context->set_output_format (new json_stderr_output_format (*context));
+ context->set_output_format (new json_stderr_output_format (*context,
+ formatted));
}
/* Populate CONTEXT in preparation for JSON output to a file named
@@ -378,10 +386,12 @@ diagnostic_output_format_init_json_stderr (diagnostic_context *context)
void
diagnostic_output_format_init_json_file (diagnostic_context *context,
+ bool formatted,
const char *base_file_name)
{
diagnostic_output_format_init_json (context);
context->set_output_format (new json_file_output_format (*context,
+ formatted,
base_file_name));
}