aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostic-format-json.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostic-format-json.cc')
-rw-r--r--gcc/diagnostic-format-json.cc230
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