diff options
author | David Malcolm <dmalcolm@redhat.com> | 2023-10-02 12:16:55 -0400 |
---|---|---|
committer | David Malcolm <dmalcolm@redhat.com> | 2023-10-02 12:16:55 -0400 |
commit | 140820265d96b0d115ade21235f8b8017fde9a5a (patch) | |
tree | 45e50166cafdee536b20ea2dec572a501554da26 /gcc/diagnostic-format-json.cc | |
parent | c5c565eff6277ac176d6c5c94f55859d0eb28938 (diff) | |
download | gcc-140820265d96b0d115ade21235f8b8017fde9a5a.zip gcc-140820265d96b0d115ade21235f8b8017fde9a5a.tar.gz gcc-140820265d96b0d115ade21235f8b8017fde9a5a.tar.bz2 |
diagnostics: add diagnostic_output_format class
Eliminate various global variables in the json/sarif output code by
bundling together callbacks and state into a new diagnostic_output_format
class, with per-output-format subclasses.
No functional change intended.
gcc/ChangeLog:
* diagnostic-format-json.cc (toplevel_array): Remove global in
favor of json_output_format::m_top_level_array.
(cur_group): Likewise, for json_output_format::m_cur_group.
(cur_children_array): Likewise, for
json_output_format::m_cur_children_array.
(class json_output_format): New.
(json_begin_diagnostic): Remove, in favor of
json_output_format::on_begin_diagnostic.
(json_end_diagnostic): Convert to...
(json_output_format::on_end_diagnostic): ...this.
(json_begin_group): Remove, in favor of
json_output_format::on_begin_group.
(json_end_group): Remove, in favor of
json_output_format::on_end_group.
(json_flush_to_file): Remove, in favor of
json_output_format::flush_to_file.
(json_stderr_final_cb): Remove, in favor of json_output_format
dtor.
(json_output_base_file_name): Remove global.
(class json_stderr_output_format): New.
(json_file_final_cb): Remove.
(class json_file_output_format): New.
(json_emit_diagram): Remove.
(diagnostic_output_format_init_json): Update.
(diagnostic_output_format_init_json_file): Update.
* diagnostic-format-sarif.cc (the_builder): Remove this global,
moving to a field of the sarif_output_format.
(sarif_builder::maybe_make_artifact_content_object): Use the
context's m_file_cache.
(get_source_lines): Convert to...
(sarif_builder::get_source_lines): ...this, using context's
m_file_cache.
(sarif_begin_diagnostic): Remove, in favor of
sarif_output_format::on_begin_diagnostic.
(sarif_end_diagnostic): Remove, in favor of
sarif_output_format::on_end_diagnostic.
(sarif_begin_group): Remove, in favor of
sarif_output_format::on_begin_group.
(sarif_end_group): Remove, in favor of
sarif_output_format::on_end_group.
(sarif_flush_to_file): Delete.
(sarif_stderr_final_cb): Delete.
(sarif_output_base_file_name): Delete.
(sarif_file_final_cb): Delete.
(class sarif_output_format): New.
(sarif_emit_diagram): Delete.
(class sarif_stream_output_format): New.
(class sarif_file_output_format): New.
(diagnostic_output_format_init_sarif): Update.
(diagnostic_output_format_init_sarif_stderr): Update.
(diagnostic_output_format_init_sarif_file): Update.
(diagnostic_output_format_init_sarif_stream): Update.
* diagnostic-show-locus.cc (diagnostic_show_locus): Update.
* diagnostic.cc (default_diagnostic_final_cb): Delete, moving to
diagnostic_text_output_format's dtor.
(diagnostic_initialize): Update, making a new instance of
diagnostic_text_output_format.
(diagnostic_finish): Delete m_output_format, rather than calling
final_cb.
(diagnostic_report_diagnostic): Assert that m_output_format is
non-NULL. Replace call to begin_group_cb with call to
m_output_format->on_begin_group. Replace call to
diagnostic_starter with call to
m_output_format->on_begin_diagnostic. Replace call to
diagnostic_finalizer with call to
m_output_format->on_end_diagnostic.
(diagnostic_emit_diagram): Replace both optional call to
m_diagrams.m_emission_cb and default implementation with call to
m_output_format->on_diagram. Move default implementation to
diagnostic_text_output_format::on_diagram.
(auto_diagnostic_group::~auto_diagnostic_group): Replace call to
end_group_cb with call to m_output_format->on_end_group.
(diagnostic_text_output_format::~diagnostic_text_output_format):
New, based on default_diagnostic_final_cb.
(diagnostic_text_output_format::on_begin_diagnostic): New, based
on code from diagnostic_report_diagnostic.
(diagnostic_text_output_format::on_end_diagnostic): Likewise.
(diagnostic_text_output_format::on_diagram): New, based on code
from diagnostic_emit_diagram.
* diagnostic.h (class diagnostic_output_format): New.
(class diagnostic_text_output_format): New.
(diagnostic_context::begin_diagnostic): Move to...
(diagnostic_context::m_text_callbacks::begin_diagnostic): ...here.
(diagnostic_context::start_span): Move to...
(diagnostic_context::m_text_callbacks::start_span): ...here.
(diagnostic_context::end_diagnostic): Move to...
(diagnostic_context::m_text_callbacks::end_diagnostic): ...here.
(diagnostic_context::begin_group_cb): Remove, in favor of
m_output_format->on_begin_group.
(diagnostic_context::end_group_cb): Remove, in favor of
m_output_format->on_end_group.
(diagnostic_context::final_cb): Remove, in favor of
m_output_format's dtor.
(diagnostic_context::m_output_format): New field.
(diagnostic_context::m_diagrams.m_emission_cb): Remove, in favor
of m_output_format->on_diagram.
(diagnostic_starter): Update.
(diagnostic_finalizer): Update.
(diagnostic_output_format_init_sarif_stream): New.
* input.cc (location_get_source_line): Move implementation apart from
call to diagnostic_file_cache_init to...
(file_cache::get_source_line): ...this new function...
(location_get_source_line): ...and reintroduce, rewritten in terms of
file_cache::get_source_line.
(get_source_file_content): Likewise, refactor into...
(file_cache::get_source_file_content): ...this new function.
* input.h (file_cache::get_source_line): New decl.
(file_cache::get_source_file_content): New decl.
* selftest-diagnostic.cc
(test_diagnostic_context::test_diagnostic_context): Update.
* tree-diagnostic-path.cc (event_range::print): Update for
change to diagnostic_context's start_span callback.
gcc/fortran/ChangeLog:
* error.cc (gfc_diagnostics_init): Update for change to start_span.
gcc/jit/ChangeLog:
* dummy-frontend.cc (jit_langhook_init): Update for change to
diagnostic_context callbacks.
gcc/testsuite/ChangeLog:
* gcc.dg/plugin/diagnostic_group_plugin.c
(test_begin_group_cb, test_end_group_cb): Replace with...
(class test_output_format): ...this new subclass.
(plugin_init): Update.
Signed-off-by: David Malcolm <dmalcolm@redhat.com>
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r-- | gcc/diagnostic-format-json.cc | 230 |
1 files changed, 121 insertions, 109 deletions
diff --git a/gcc/diagnostic-format-json.cc b/gcc/diagnostic-format-json.cc index 539b98b..346abb3 100644 --- a/gcc/diagnostic-format-json.cc +++ b/gcc/diagnostic-format-json.cc @@ -28,18 +28,63 @@ along with GCC; see the file COPYING3. If not see #include "json.h" #include "selftest.h" -/* The top-level JSON array of pending diagnostics. */ +/* Subclass of diagnostic_output_format for JSON output. */ -static json::array *toplevel_array; +class json_output_format : public diagnostic_output_format +{ +public: + void on_begin_group () final override + { + /* No-op. */ + } + void on_end_group () final override + { + m_cur_group = nullptr; + m_cur_children_array = nullptr; + } + void + on_begin_diagnostic (diagnostic_info *) final override + { + /* No-op. */ + } + void + on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) final override; + void on_diagram (const diagnostic_diagram &) final override + { + /* No-op. */ + } -/* The JSON object for the current diagnostic group. */ +protected: + json_output_format (diagnostic_context &context) + : diagnostic_output_format (context), + m_toplevel_array (new json::array ()), + m_cur_group (nullptr), + m_cur_children_array (nullptr) + { + } -static json::object *cur_group; + /* Flush the top-level array to OUTF. */ + void + flush_to_file (FILE *outf) + { + m_toplevel_array->dump (outf); + fprintf (outf, "\n"); + delete m_toplevel_array; + m_toplevel_array = nullptr; + } + +private: + /* The top-level JSON array of pending diagnostics. */ + json::array *m_toplevel_array; -/* The JSON array for the "children" array within the current diagnostic - group. */ + /* The JSON object for the current diagnostic group. */ + json::object *m_cur_group; -static json::array *cur_children_array; + /* The JSON array for the "children" array within the current diagnostic + group. */ + json::array *m_cur_children_array; +}; /* Generate a JSON object for LOC. */ @@ -139,20 +184,13 @@ json_from_metadata (const diagnostic_metadata *metadata) return metadata_obj; } -/* No-op implementation of "begin_diagnostic" for JSON output. */ - -static void -json_begin_diagnostic (diagnostic_context *, diagnostic_info *) -{ -} - -/* Implementation of "end_diagnostic" for JSON output. +/* Implementation of "on_end_diagnostic" vfunc for JSON output. Generate a JSON object for DIAGNOSTIC, and store for output within current diagnostic group. */ -static void -json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, - diagnostic_t orig_diag_kind) +void +json_output_format::on_end_diagnostic (diagnostic_info *diagnostic, + diagnostic_t orig_diag_kind) { json::object *diag_obj = new json::object (); @@ -178,22 +216,22 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, // FIXME: encoding of the message (json::string requires UTF-8) diag_obj->set ("message", - new json::string (pp_formatted_text (context->printer))); - pp_clear_output_area (context->printer); + new json::string (pp_formatted_text (m_context.printer))); + pp_clear_output_area (m_context.printer); char *option_text; - option_text = context->option_name (context, diagnostic->option_index, - orig_diag_kind, diagnostic->kind); + option_text = m_context.option_name (&m_context, diagnostic->option_index, + orig_diag_kind, diagnostic->kind); if (option_text) { diag_obj->set ("option", new json::string (option_text)); free (option_text); } - if (context->get_option_url) + if (m_context.get_option_url) { - char *option_url = context->get_option_url (context, - diagnostic->option_index); + char *option_url = m_context.get_option_url (&m_context, + diagnostic->option_index); if (option_url) { diag_obj->set ("option_url", new json::string (option_url)); @@ -203,21 +241,21 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, /* If we've already emitted a diagnostic within this auto_diagnostic_group, then add diag_obj to its "children" array. */ - if (cur_group) + if (m_cur_group) { - gcc_assert (cur_children_array); - cur_children_array->append (diag_obj); + gcc_assert (m_cur_children_array); + m_cur_children_array->append (diag_obj); } else { /* Otherwise, make diag_obj be the top-level object within the group; add a "children" array and record the column origin. */ - toplevel_array->append (diag_obj); - cur_group = diag_obj; - cur_children_array = new json::array (); - diag_obj->set ("children", cur_children_array); + m_toplevel_array->append (diag_obj); + m_cur_group = diag_obj; + m_cur_children_array = new json::array (); + diag_obj->set ("children", m_cur_children_array); diag_obj->set ("column-origin", - new json::integer_number (context->column_origin)); + new json::integer_number (m_context.column_origin)); } const rich_location *richloc = diagnostic->richloc; @@ -228,7 +266,8 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_locations (); i++) { const location_range *loc_range = richloc->get_range (i); - json::object *loc_obj = json_from_location_range (context, loc_range, i); + json::object *loc_obj + = json_from_location_range (&m_context, loc_range, i); if (loc_obj) loc_array->append (loc_obj); } @@ -240,7 +279,7 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, for (unsigned int i = 0; i < richloc->get_num_fixit_hints (); i++) { const fixit_hint *hint = richloc->get_fixit_hint (i); - json::object *fixit_obj = json_from_fixit_hint (context, hint); + json::object *fixit_obj = json_from_fixit_hint (&m_context, hint); fixit_array->append (fixit_obj); } } @@ -257,9 +296,9 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, } const diagnostic_path *path = richloc->get_path (); - if (path && context->make_json_for_path) + if (path && m_context.make_json_for_path) { - json::value *path_value = context->make_json_for_path (context, path); + json::value *path_value = m_context.make_json_for_path (&m_context, path); diag_obj->set ("path", path_value); } @@ -267,71 +306,51 @@ json_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic, new json::literal (richloc->escape_on_output_p ())); } -/* No-op implementation of "begin_group_cb" for JSON output. */ - -static void -json_begin_group (diagnostic_context *) -{ -} - -/* Implementation of "end_group_cb" for JSON output. */ - -static void -json_end_group (diagnostic_context *) +class json_stderr_output_format : public json_output_format { - cur_group = NULL; - cur_children_array = NULL; -} - -/* Flush the top-level array to OUTF. */ - -static void -json_flush_to_file (FILE *outf) -{ - toplevel_array->dump (outf); - fprintf (outf, "\n"); - delete toplevel_array; - toplevel_array = NULL; -} - -/* 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. */ +public: + json_stderr_output_format (diagnostic_context &context) + : json_output_format (context) + { + } + ~json_stderr_output_format () + { + flush_to_file (stderr); + } +}; -static void -json_file_final_cb (diagnostic_context *) +class json_file_output_format : public json_output_format { - 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); -} +public: + json_file_output_format (diagnostic_context &context, + const char *base_file_name) + : json_output_format (context), + m_base_file_name (xstrdup (base_file_name)) + { + } -/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */ + ~json_file_output_format () + { + char *filename = concat (m_base_file_name, ".gcc.json", NULL); + free (m_base_file_name); + m_base_file_name = nullptr; + 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; + } + flush_to_file (outf); + fclose (outf); + free (filename); + } -static void -json_emit_diagram (diagnostic_context *, - const diagnostic_diagram &) -{ - /* No-op. */ -} +private: + char *m_base_file_name; +}; /* Populate CONTEXT in preparation for JSON output (either to stderr, or to a file). */ @@ -339,17 +358,8 @@ json_emit_diagram (diagnostic_context *, 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. */ - context->m_diagrams.m_emission_cb = json_emit_diagram; /* The metadata is handled in JSON format, rather than as text. */ context->show_cwe = false; @@ -368,7 +378,8 @@ void diagnostic_output_format_init_json_stderr (diagnostic_context *context) { diagnostic_output_format_init_json (context); - context->final_cb = json_stderr_final_cb; + delete context->m_output_format; + context->m_output_format = new json_stderr_output_format (*context); } /* Populate CONTEXT in preparation for JSON output to a file named @@ -379,8 +390,9 @@ 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); + delete context->m_output_format; + context->m_output_format = new json_file_output_format (*context, + base_file_name); } #if CHECKING_P |