mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/* The JSON array for the "children" array within the current diagnostic
|
||||
group. */
|
||||
private:
|
||||
/* The top-level JSON array of pending diagnostics. */
|
||||
json::array *m_toplevel_array;
|
||||
|
||||
static json::array *cur_children_array;
|
||||
/* The JSON object for the current diagnostic group. */
|
||||
json::object *m_cur_group;
|
||||
|
||||
/* 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 *)
|
||||
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 ()
|
||||
{
|
||||
flush_to_file (stderr);
|
||||
}
|
||||
};
|
||||
|
||||
/* Implementation of "end_group_cb" for JSON output. */
|
||||
|
||||
static void
|
||||
json_end_group (diagnostic_context *)
|
||||
class json_file_output_format : public json_output_format
|
||||
{
|
||||
cur_group = NULL;
|
||||
cur_children_array = NULL;
|
||||
}
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
/* Flush the top-level array to OUTF. */
|
||||
~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_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. */
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */
|
||||
|
||||
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
|
||||
|
||||
@@ -215,6 +215,9 @@ private:
|
||||
json::object *
|
||||
make_reporting_descriptor_reference_object_for_cwe_id (int cwe_id);
|
||||
json::object *make_artifact_object (const char *filename);
|
||||
char *get_source_lines (const char *filename,
|
||||
int start_line,
|
||||
int end_line) const;
|
||||
json::object *maybe_make_artifact_content_object (const char *filename) const;
|
||||
json::object *maybe_make_artifact_content_object (const char *filename,
|
||||
int start_line,
|
||||
@@ -248,8 +251,6 @@ private:
|
||||
int m_tabstop;
|
||||
};
|
||||
|
||||
static sarif_builder *the_builder;
|
||||
|
||||
/* class sarif_object : public json::object. */
|
||||
|
||||
sarif_property_bag &
|
||||
@@ -1540,7 +1541,8 @@ json::object *
|
||||
sarif_builder::maybe_make_artifact_content_object (const char *filename) const
|
||||
{
|
||||
/* Let input.cc handle any charset conversion. */
|
||||
char_span utf8_content = get_source_file_content (filename);
|
||||
char_span utf8_content
|
||||
= m_context->m_file_cache->get_source_file_content (filename);
|
||||
if (!utf8_content)
|
||||
return NULL;
|
||||
|
||||
@@ -1558,16 +1560,17 @@ sarif_builder::maybe_make_artifact_content_object (const char *filename) const
|
||||
/* Attempt to read the given range of lines from FILENAME; return
|
||||
a freshly-allocated 0-terminated buffer containing them, or NULL. */
|
||||
|
||||
static char *
|
||||
get_source_lines (const char *filename,
|
||||
int start_line,
|
||||
int end_line)
|
||||
char *
|
||||
sarif_builder::get_source_lines (const char *filename,
|
||||
int start_line,
|
||||
int end_line) const
|
||||
{
|
||||
auto_vec<char> result;
|
||||
|
||||
for (int line = start_line; line <= end_line; line++)
|
||||
{
|
||||
char_span line_content = location_get_source_line (filename, line);
|
||||
char_span line_content
|
||||
= m_context->m_file_cache->get_source_line (filename, line);
|
||||
if (!line_content.get_buffer ())
|
||||
return NULL;
|
||||
result.reserve (line_content.length () + 1);
|
||||
@@ -1680,82 +1683,6 @@ sarif_builder::make_artifact_content_object (const char *text) const
|
||||
return content_obj;
|
||||
}
|
||||
|
||||
/* No-op implementation of "begin_diagnostic" for SARIF output. */
|
||||
|
||||
static void
|
||||
sarif_begin_diagnostic (diagnostic_context *, diagnostic_info *)
|
||||
{
|
||||
}
|
||||
|
||||
/* Implementation of "end_diagnostic" for SARIF output. */
|
||||
|
||||
static void
|
||||
sarif_end_diagnostic (diagnostic_context *context, diagnostic_info *diagnostic,
|
||||
diagnostic_t orig_diag_kind)
|
||||
{
|
||||
gcc_assert (the_builder);
|
||||
the_builder->end_diagnostic (context, diagnostic, orig_diag_kind);
|
||||
}
|
||||
|
||||
/* No-op implementation of "begin_group_cb" for SARIF output. */
|
||||
|
||||
static void
|
||||
sarif_begin_group (diagnostic_context *)
|
||||
{
|
||||
}
|
||||
|
||||
/* Implementation of "end_group_cb" for SARIF output. */
|
||||
|
||||
static void
|
||||
sarif_end_group (diagnostic_context *)
|
||||
{
|
||||
gcc_assert (the_builder);
|
||||
the_builder->end_group ();
|
||||
}
|
||||
|
||||
/* Flush the top-level array to OUTF. */
|
||||
|
||||
static void
|
||||
sarif_flush_to_file (FILE *outf)
|
||||
{
|
||||
gcc_assert (the_builder);
|
||||
the_builder->flush_to_file (outf);
|
||||
delete the_builder;
|
||||
the_builder = NULL;
|
||||
}
|
||||
|
||||
/* Callback for final cleanup for SARIF output to stderr. */
|
||||
|
||||
static void
|
||||
sarif_stderr_final_cb (diagnostic_context *)
|
||||
{
|
||||
gcc_assert (the_builder);
|
||||
sarif_flush_to_file (stderr);
|
||||
}
|
||||
|
||||
static char *sarif_output_base_file_name;
|
||||
|
||||
/* Callback for final cleanup for SARIF output to a file. */
|
||||
|
||||
static void
|
||||
sarif_file_final_cb (diagnostic_context *)
|
||||
{
|
||||
char *filename = concat (sarif_output_base_file_name, ".sarif", 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;
|
||||
}
|
||||
gcc_assert (the_builder);
|
||||
sarif_flush_to_file (outf);
|
||||
fclose (outf);
|
||||
free (filename);
|
||||
}
|
||||
|
||||
/* Callback for diagnostic_context::ice_handler_cb for when an ICE
|
||||
occurs. */
|
||||
|
||||
@@ -1773,15 +1700,89 @@ sarif_ice_handler (diagnostic_context *context)
|
||||
fnotice (stderr, "Internal compiler error:\n");
|
||||
}
|
||||
|
||||
/* Callback for diagnostic_context::m_diagrams.m_emission_cb. */
|
||||
|
||||
static void
|
||||
sarif_emit_diagram (diagnostic_context *context,
|
||||
const diagnostic_diagram &diagram)
|
||||
class sarif_output_format : public diagnostic_output_format
|
||||
{
|
||||
gcc_assert (the_builder);
|
||||
the_builder->emit_diagram (context, diagram);
|
||||
}
|
||||
public:
|
||||
void on_begin_group () final override
|
||||
{
|
||||
/* No-op, */
|
||||
}
|
||||
void on_end_group () final override
|
||||
{
|
||||
m_builder.end_group ();
|
||||
}
|
||||
void
|
||||
on_begin_diagnostic (diagnostic_info *) final override
|
||||
{
|
||||
/* No-op, */
|
||||
}
|
||||
void
|
||||
on_end_diagnostic (diagnostic_info *diagnostic,
|
||||
diagnostic_t orig_diag_kind) final override
|
||||
{
|
||||
m_builder.end_diagnostic (&m_context, diagnostic, orig_diag_kind);
|
||||
}
|
||||
void on_diagram (const diagnostic_diagram &diagram) final override
|
||||
{
|
||||
m_builder.emit_diagram (&m_context, diagram);
|
||||
}
|
||||
|
||||
protected:
|
||||
sarif_output_format (diagnostic_context &context)
|
||||
: diagnostic_output_format (context),
|
||||
m_builder (&context)
|
||||
{}
|
||||
|
||||
sarif_builder m_builder;
|
||||
};
|
||||
|
||||
class sarif_stream_output_format : public sarif_output_format
|
||||
{
|
||||
public:
|
||||
sarif_stream_output_format (diagnostic_context &context, FILE *stream)
|
||||
: sarif_output_format (context),
|
||||
m_stream (stream)
|
||||
{
|
||||
}
|
||||
~sarif_stream_output_format ()
|
||||
{
|
||||
m_builder.flush_to_file (m_stream);
|
||||
}
|
||||
private:
|
||||
FILE *m_stream;
|
||||
};
|
||||
|
||||
class sarif_file_output_format : public sarif_output_format
|
||||
{
|
||||
public:
|
||||
sarif_file_output_format (diagnostic_context &context,
|
||||
const char *base_file_name)
|
||||
: sarif_output_format (context),
|
||||
m_base_file_name (xstrdup (base_file_name))
|
||||
{
|
||||
}
|
||||
~sarif_file_output_format ()
|
||||
{
|
||||
char *filename = concat (m_base_file_name, ".sarif", 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;
|
||||
}
|
||||
m_builder.flush_to_file (outf);
|
||||
fclose (outf);
|
||||
free (filename);
|
||||
}
|
||||
|
||||
private:
|
||||
char *m_base_file_name;
|
||||
};
|
||||
|
||||
/* Populate CONTEXT in preparation for SARIF output (either to stderr, or
|
||||
to a file). */
|
||||
@@ -1789,16 +1790,9 @@ sarif_emit_diagram (diagnostic_context *context,
|
||||
static void
|
||||
diagnostic_output_format_init_sarif (diagnostic_context *context)
|
||||
{
|
||||
the_builder = new sarif_builder (context);
|
||||
|
||||
/* Override callbacks. */
|
||||
context->begin_diagnostic = sarif_begin_diagnostic;
|
||||
context->end_diagnostic = sarif_end_diagnostic;
|
||||
context->begin_group_cb = sarif_begin_group;
|
||||
context->end_group_cb = sarif_end_group;
|
||||
context->print_path = NULL; /* handled in sarif_end_diagnostic. */
|
||||
context->ice_handler_cb = sarif_ice_handler;
|
||||
context->m_diagrams.m_emission_cb = sarif_emit_diagram;
|
||||
|
||||
/* The metadata is handled in SARIF format, rather than as text. */
|
||||
context->show_cwe = false;
|
||||
@@ -1817,7 +1811,8 @@ void
|
||||
diagnostic_output_format_init_sarif_stderr (diagnostic_context *context)
|
||||
{
|
||||
diagnostic_output_format_init_sarif (context);
|
||||
context->final_cb = sarif_stderr_final_cb;
|
||||
delete context->m_output_format;
|
||||
context->m_output_format = new sarif_stream_output_format (*context, stderr);
|
||||
}
|
||||
|
||||
/* Populate CONTEXT in preparation for SARIF output to a file named
|
||||
@@ -1825,9 +1820,22 @@ diagnostic_output_format_init_sarif_stderr (diagnostic_context *context)
|
||||
|
||||
void
|
||||
diagnostic_output_format_init_sarif_file (diagnostic_context *context,
|
||||
const char *base_file_name)
|
||||
const char *base_file_name)
|
||||
{
|
||||
diagnostic_output_format_init_sarif (context);
|
||||
context->final_cb = sarif_file_final_cb;
|
||||
sarif_output_base_file_name = xstrdup (base_file_name);
|
||||
delete context->m_output_format;
|
||||
context->m_output_format = new sarif_file_output_format (*context,
|
||||
base_file_name);
|
||||
}
|
||||
|
||||
/* Populate CONTEXT in preparation for SARIF output to STREAM. */
|
||||
|
||||
void
|
||||
diagnostic_output_format_init_sarif_stream (diagnostic_context *context,
|
||||
FILE *stream)
|
||||
{
|
||||
diagnostic_output_format_init_sarif (context);
|
||||
delete context->m_output_format;
|
||||
context->m_output_format = new sarif_stream_output_format (*context,
|
||||
stream);
|
||||
}
|
||||
|
||||
@@ -2876,7 +2876,7 @@ diagnostic_show_locus (diagnostic_context * context,
|
||||
{
|
||||
expanded_location exploc
|
||||
= layout.get_expanded_location (line_span);
|
||||
context->start_span (context, exploc);
|
||||
context->m_text_callbacks.start_span (context, exploc);
|
||||
}
|
||||
}
|
||||
/* Iterate over the lines within this span (using linenum_arith_t to
|
||||
|
||||
@@ -150,28 +150,6 @@ diagnostic_set_caret_max_width (diagnostic_context *context, int value)
|
||||
context->m_source_printing.max_width = value;
|
||||
}
|
||||
|
||||
/* Default implementation of final_cb. */
|
||||
|
||||
static void
|
||||
default_diagnostic_final_cb (diagnostic_context *context)
|
||||
{
|
||||
/* Some of the errors may actually have been warnings. */
|
||||
if (diagnostic_kind_count (context, DK_WERROR))
|
||||
{
|
||||
/* -Werror was given. */
|
||||
if (context->warning_as_error_requested)
|
||||
pp_verbatim (context->printer,
|
||||
_("%s: all warnings being treated as errors"),
|
||||
progname);
|
||||
/* At least one -Werror= was given. */
|
||||
else
|
||||
pp_verbatim (context->printer,
|
||||
_("%s: some warnings being treated as errors"),
|
||||
progname);
|
||||
pp_newline_and_flush (context->printer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize the diagnostic message outputting machinery. */
|
||||
void
|
||||
diagnostic_initialize (diagnostic_context *context, int n_opts)
|
||||
@@ -209,7 +187,7 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
|
||||
context->max_errors = 0;
|
||||
context->internal_error = NULL;
|
||||
diagnostic_starter (context) = default_diagnostic_starter;
|
||||
context->start_span = default_diagnostic_start_span_fn;
|
||||
context->m_text_callbacks.start_span = default_diagnostic_start_span_fn;
|
||||
diagnostic_finalizer (context) = default_diagnostic_finalizer;
|
||||
context->option_enabled = NULL;
|
||||
context->option_state = NULL;
|
||||
@@ -242,15 +220,12 @@ diagnostic_initialize (diagnostic_context *context, int n_opts)
|
||||
context->edit_context_ptr = NULL;
|
||||
context->diagnostic_group_nesting_depth = 0;
|
||||
context->diagnostic_group_emission_count = 0;
|
||||
context->begin_group_cb = NULL;
|
||||
context->end_group_cb = NULL;
|
||||
context->final_cb = default_diagnostic_final_cb;
|
||||
context->m_output_format = new diagnostic_text_output_format (*context);
|
||||
context->set_locations_cb = nullptr;
|
||||
context->ice_handler_cb = NULL;
|
||||
context->includes_seen = NULL;
|
||||
context->m_client_data_hooks = NULL;
|
||||
context->m_diagrams.m_theme = NULL;
|
||||
context->m_diagrams.m_emission_cb = NULL;
|
||||
diagnostics_text_art_charset_init (context,
|
||||
DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT);
|
||||
}
|
||||
@@ -326,8 +301,8 @@ void diagnostic_initialize_input_context (diagnostic_context *context,
|
||||
void
|
||||
diagnostic_finish (diagnostic_context *context)
|
||||
{
|
||||
if (context->final_cb)
|
||||
context->final_cb (context);
|
||||
delete context->m_output_format;
|
||||
context->m_output_format= nullptr;
|
||||
|
||||
if (context->m_diagrams.m_theme)
|
||||
{
|
||||
@@ -1508,6 +1483,8 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
||||
location_t location = diagnostic_location (diagnostic);
|
||||
diagnostic_t orig_diag_kind = diagnostic->kind;
|
||||
|
||||
gcc_assert (context->m_output_format);
|
||||
|
||||
/* Give preference to being able to inhibit warnings, before they
|
||||
get reclassified to something else. */
|
||||
bool report_warning_p = true;
|
||||
@@ -1598,14 +1575,11 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
||||
|
||||
/* Is this the initial diagnostic within the stack of groups? */
|
||||
if (context->diagnostic_group_emission_count == 0)
|
||||
{
|
||||
if (context->begin_group_cb)
|
||||
context->begin_group_cb (context);
|
||||
}
|
||||
context->m_output_format->on_begin_group ();
|
||||
context->diagnostic_group_emission_count++;
|
||||
|
||||
pp_format (context->printer, &diagnostic->message);
|
||||
(*diagnostic_starter (context)) (context, diagnostic);
|
||||
context->m_output_format->on_begin_diagnostic (diagnostic);
|
||||
pp_output_formatted_text (context->printer);
|
||||
if (context->show_cwe)
|
||||
print_any_cwe (context, diagnostic);
|
||||
@@ -1613,7 +1587,7 @@ diagnostic_report_diagnostic (diagnostic_context *context,
|
||||
print_any_rules (context, diagnostic);
|
||||
if (context->show_option_requested)
|
||||
print_option_information (context, diagnostic, orig_diag_kind);
|
||||
(*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
|
||||
context->m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind);
|
||||
switch (context->extra_output_kind)
|
||||
{
|
||||
default:
|
||||
@@ -2214,22 +2188,8 @@ diagnostic_emit_diagram (diagnostic_context *context,
|
||||
if (context->m_diagrams.m_theme == nullptr)
|
||||
return;
|
||||
|
||||
if (context->m_diagrams.m_emission_cb)
|
||||
{
|
||||
context->m_diagrams.m_emission_cb (context, diagram);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Default implementation. */
|
||||
char *saved_prefix = pp_take_prefix (context->printer);
|
||||
pp_set_prefix (context->printer, NULL);
|
||||
/* Use a newline before and after and a two-space indent
|
||||
to make the diagram stand out a little from the wall of text. */
|
||||
pp_newline (context->printer);
|
||||
diagram.get_canvas ().print_to_pp (context->printer, " ");
|
||||
pp_newline (context->printer);
|
||||
pp_set_prefix (context->printer, saved_prefix);
|
||||
pp_flush (context->printer);
|
||||
gcc_assert (context->m_output_format);
|
||||
context->m_output_format->on_diagram (diagram);
|
||||
}
|
||||
|
||||
/* Special case error functions. Most are implemented in terms of the
|
||||
@@ -2331,14 +2291,59 @@ auto_diagnostic_group::~auto_diagnostic_group ()
|
||||
If any diagnostics were emitted, give the context a chance
|
||||
to do something. */
|
||||
if (global_dc->diagnostic_group_emission_count > 0)
|
||||
{
|
||||
if (global_dc->end_group_cb)
|
||||
global_dc->end_group_cb (global_dc);
|
||||
}
|
||||
global_dc->m_output_format->on_end_group ();
|
||||
global_dc->diagnostic_group_emission_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* class diagnostic_text_output_format : public diagnostic_output_format. */
|
||||
|
||||
diagnostic_text_output_format::~diagnostic_text_output_format ()
|
||||
{
|
||||
/* Some of the errors may actually have been warnings. */
|
||||
if (diagnostic_kind_count (&m_context, DK_WERROR))
|
||||
{
|
||||
/* -Werror was given. */
|
||||
if (m_context.warning_as_error_requested)
|
||||
pp_verbatim (m_context.printer,
|
||||
_("%s: all warnings being treated as errors"),
|
||||
progname);
|
||||
/* At least one -Werror= was given. */
|
||||
else
|
||||
pp_verbatim (m_context.printer,
|
||||
_("%s: some warnings being treated as errors"),
|
||||
progname);
|
||||
pp_newline_and_flush (m_context.printer);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
diagnostic_text_output_format::on_begin_diagnostic (diagnostic_info *diagnostic)
|
||||
{
|
||||
(*diagnostic_starter (&m_context)) (&m_context, diagnostic);
|
||||
}
|
||||
|
||||
void
|
||||
diagnostic_text_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
|
||||
diagnostic_t orig_diag_kind)
|
||||
{
|
||||
(*diagnostic_finalizer (&m_context)) (&m_context, diagnostic, orig_diag_kind);
|
||||
}
|
||||
|
||||
void
|
||||
diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
|
||||
{
|
||||
char *saved_prefix = pp_take_prefix (m_context.printer);
|
||||
pp_set_prefix (m_context.printer, NULL);
|
||||
/* Use a newline before and after and a two-space indent
|
||||
to make the diagram stand out a little from the wall of text. */
|
||||
pp_newline (m_context.printer);
|
||||
diagram.get_canvas ().print_to_pp (m_context.printer, " ");
|
||||
pp_newline (m_context.printer);
|
||||
pp_set_prefix (m_context.printer, saved_prefix);
|
||||
pp_flush (m_context.printer);
|
||||
}
|
||||
|
||||
/* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
|
||||
file-based output formats. */
|
||||
|
||||
|
||||
105
gcc/diagnostic.h
105
gcc/diagnostic.h
@@ -177,6 +177,51 @@ class diagnostic_client_data_hooks;
|
||||
class logical_location;
|
||||
class diagnostic_diagram;
|
||||
|
||||
/* Abstract base class for a particular output format for diagnostics;
|
||||
each value of -fdiagnostics-output-format= will have its own
|
||||
implementation. */
|
||||
|
||||
class diagnostic_output_format
|
||||
{
|
||||
public:
|
||||
virtual ~diagnostic_output_format () {}
|
||||
|
||||
virtual void on_begin_group () = 0;
|
||||
virtual void on_end_group () = 0;
|
||||
virtual void on_begin_diagnostic (diagnostic_info *) = 0;
|
||||
virtual void on_end_diagnostic (diagnostic_info *,
|
||||
diagnostic_t orig_diag_kind) = 0;
|
||||
virtual void on_diagram (const diagnostic_diagram &diagram) = 0;
|
||||
|
||||
protected:
|
||||
diagnostic_output_format (diagnostic_context &context)
|
||||
: m_context (context)
|
||||
{}
|
||||
|
||||
diagnostic_context &m_context;
|
||||
};
|
||||
|
||||
/* Subclass of diagnostic_output_format for classic text-based output
|
||||
to stderr.
|
||||
|
||||
Uses diagnostic_context.m_text_callbacks to provide client-specific
|
||||
textual output (e.g. include paths, macro expansions, etc). */
|
||||
|
||||
class diagnostic_text_output_format : public diagnostic_output_format
|
||||
{
|
||||
public:
|
||||
diagnostic_text_output_format (diagnostic_context &context)
|
||||
: diagnostic_output_format (context)
|
||||
{}
|
||||
~diagnostic_text_output_format ();
|
||||
void on_begin_group () override {}
|
||||
void on_end_group () override {}
|
||||
void on_begin_diagnostic (diagnostic_info *) override;
|
||||
void on_end_diagnostic (diagnostic_info *,
|
||||
diagnostic_t orig_diag_kind) override;
|
||||
void on_diagram (const diagnostic_diagram &diagram) override;
|
||||
};
|
||||
|
||||
/* This data structure bundles altogether any information relevant to
|
||||
the context of a diagnostic message. */
|
||||
struct diagnostic_context
|
||||
@@ -264,22 +309,25 @@ struct diagnostic_context
|
||||
/* Maximum number of errors to report. */
|
||||
int max_errors;
|
||||
|
||||
/* This function is called before any message is printed out. It is
|
||||
responsible for preparing message prefix and such. For example, it
|
||||
might say:
|
||||
In file included from "/usr/local/include/curses.h:5:
|
||||
from "/home/gdr/src/nifty_printer.h:56:
|
||||
...
|
||||
*/
|
||||
diagnostic_starter_fn begin_diagnostic;
|
||||
/* Client-supplied callbacks for use in text output. */
|
||||
struct {
|
||||
/* This function is called before any message is printed out. It is
|
||||
responsible for preparing message prefix and such. For example, it
|
||||
might say:
|
||||
In file included from "/usr/local/include/curses.h:5:
|
||||
from "/home/gdr/src/nifty_printer.h:56:
|
||||
...
|
||||
*/
|
||||
diagnostic_starter_fn begin_diagnostic;
|
||||
|
||||
/* This function is called by diagnostic_show_locus in between
|
||||
disjoint spans of source code, so that the context can print
|
||||
something to indicate that a new span of source code has begun. */
|
||||
diagnostic_start_span_fn start_span;
|
||||
/* This function is called by diagnostic_show_locus in between
|
||||
disjoint spans of source code, so that the context can print
|
||||
something to indicate that a new span of source code has begun. */
|
||||
diagnostic_start_span_fn start_span;
|
||||
|
||||
/* This function is called after the diagnostic message is printed. */
|
||||
diagnostic_finalizer_fn end_diagnostic;
|
||||
/* This function is called after the diagnostic message is printed. */
|
||||
diagnostic_finalizer_fn end_diagnostic;
|
||||
} m_text_callbacks;
|
||||
|
||||
/* Client hook to report an internal error. */
|
||||
void (*internal_error) (diagnostic_context *, const char *, va_list *);
|
||||
@@ -402,18 +450,9 @@ struct diagnostic_context
|
||||
diagnostic_group was pushed. */
|
||||
int diagnostic_group_emission_count;
|
||||
|
||||
/* Optional callbacks for handling diagnostic groups. */
|
||||
|
||||
/* If non-NULL, this will be called immediately before the first
|
||||
time a diagnostic is emitted within a stack of groups. */
|
||||
void (*begin_group_cb) (diagnostic_context * context);
|
||||
|
||||
/* If non-NULL, this will be called when a stack of groups is
|
||||
popped if any diagnostics were emitted within that group. */
|
||||
void (*end_group_cb) (diagnostic_context * context);
|
||||
|
||||
/* Callback for final cleanup. */
|
||||
void (*final_cb) (diagnostic_context *context);
|
||||
/* How to output diagnostics (text vs a structured format such as JSON).
|
||||
Must be non-NULL; owned by context. */
|
||||
diagnostic_output_format *m_output_format;
|
||||
|
||||
/* Callback to set the locations of call sites along the inlining
|
||||
stack corresponding to a diagnostic location. Needed to traverse
|
||||
@@ -441,9 +480,6 @@ struct diagnostic_context
|
||||
Can be NULL (if text art is disabled). */
|
||||
text_art::theme *m_theme;
|
||||
|
||||
/* Callback for emitting diagrams. */
|
||||
void (*m_emission_cb) (diagnostic_context *context,
|
||||
const diagnostic_diagram &diagram);
|
||||
} m_diagrams;
|
||||
};
|
||||
|
||||
@@ -454,12 +490,13 @@ diagnostic_inhibit_notes (diagnostic_context * context)
|
||||
}
|
||||
|
||||
|
||||
/* Client supplied function to announce a diagnostic. */
|
||||
#define diagnostic_starter(DC) (DC)->begin_diagnostic
|
||||
/* Client supplied function to announce a diagnostic
|
||||
(for text-based diagnostic output). */
|
||||
#define diagnostic_starter(DC) (DC)->m_text_callbacks.begin_diagnostic
|
||||
|
||||
/* Client supplied function called after a diagnostic message is
|
||||
displayed. */
|
||||
#define diagnostic_finalizer(DC) (DC)->end_diagnostic
|
||||
displayed (for text-based diagnostic output). */
|
||||
#define diagnostic_finalizer(DC) (DC)->m_text_callbacks.end_diagnostic
|
||||
|
||||
/* Extension hooks for client. */
|
||||
#define diagnostic_context_auxiliary_data(DC) (DC)->x_data
|
||||
@@ -638,6 +675,8 @@ extern void diagnostic_output_format_init_json_file (diagnostic_context *context
|
||||
extern void diagnostic_output_format_init_sarif_stderr (diagnostic_context *context);
|
||||
extern void diagnostic_output_format_init_sarif_file (diagnostic_context *context,
|
||||
const char *base_file_name);
|
||||
extern void diagnostic_output_format_init_sarif_stream (diagnostic_context *context,
|
||||
FILE *stream);
|
||||
|
||||
/* Compute the number of digits in the decimal representation of an integer. */
|
||||
extern int num_digits (int);
|
||||
|
||||
@@ -1637,7 +1637,7 @@ void
|
||||
gfc_diagnostics_init (void)
|
||||
{
|
||||
diagnostic_starter (global_dc) = gfc_diagnostic_starter;
|
||||
global_dc->start_span = gfc_diagnostic_start_span;
|
||||
global_dc->m_text_callbacks.start_span = gfc_diagnostic_start_span;
|
||||
diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer;
|
||||
diagnostic_format_decoder (global_dc) = gfc_format_decoder;
|
||||
global_dc->m_source_printing.caret_chars[0] = '1';
|
||||
|
||||
26
gcc/input.cc
26
gcc/input.cc
@@ -946,7 +946,7 @@ file_cache_slot::read_line_num (size_t line_num,
|
||||
If the function fails, a NULL char_span is returned. */
|
||||
|
||||
char_span
|
||||
location_get_source_line (const char *file_path, int line)
|
||||
file_cache::get_source_line (const char *file_path, int line)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
ssize_t len;
|
||||
@@ -957,9 +957,7 @@ location_get_source_line (const char *file_path, int line)
|
||||
if (file_path == NULL)
|
||||
return char_span (NULL, 0);
|
||||
|
||||
diagnostic_file_cache_init ();
|
||||
|
||||
file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
|
||||
file_cache_slot *c = lookup_or_add_file (file_path);
|
||||
if (c == NULL)
|
||||
return char_span (NULL, 0);
|
||||
|
||||
@@ -970,6 +968,13 @@ location_get_source_line (const char *file_path, int line)
|
||||
return char_span (buffer, len);
|
||||
}
|
||||
|
||||
char_span
|
||||
location_get_source_line (const char *file_path, int line)
|
||||
{
|
||||
diagnostic_file_cache_init ();
|
||||
return global_dc->m_file_cache->get_source_line (file_path, line);
|
||||
}
|
||||
|
||||
/* Return a NUL-terminated copy of the source text between two locations, or
|
||||
NULL if the arguments are invalid. The caller is responsible for freeing
|
||||
the return value. */
|
||||
@@ -1062,6 +1067,15 @@ get_source_text_between (location_t start, location_t end)
|
||||
return xstrdup (buf);
|
||||
}
|
||||
|
||||
|
||||
char_span
|
||||
file_cache::get_source_file_content (const char *file_path)
|
||||
{
|
||||
file_cache_slot *c = lookup_or_add_file (file_path);
|
||||
return c->get_full_file_content ();
|
||||
}
|
||||
|
||||
|
||||
/* Get a borrowed char_span to the full content of FILE_PATH
|
||||
as decoded according to the input charset, encoded as UTF-8. */
|
||||
|
||||
@@ -1069,9 +1083,7 @@ char_span
|
||||
get_source_file_content (const char *file_path)
|
||||
{
|
||||
diagnostic_file_cache_init ();
|
||||
|
||||
file_cache_slot *c = global_dc->m_file_cache->lookup_or_add_file (file_path);
|
||||
return c->get_full_file_content ();
|
||||
return global_dc->m_file_cache->get_source_file_content (file_path);
|
||||
}
|
||||
|
||||
/* Determine if FILE_PATH missing a trailing newline on its final line.
|
||||
|
||||
@@ -150,6 +150,9 @@ class file_cache
|
||||
void initialize_input_context (diagnostic_input_charset_callback ccb,
|
||||
bool should_skip_bom);
|
||||
|
||||
char_span get_source_file_content (const char *file_path);
|
||||
char_span get_source_line (const char *file_path, int line);
|
||||
|
||||
private:
|
||||
file_cache_slot *evicted_cache_tab_entry (unsigned *highest_use_count);
|
||||
file_cache_slot *add_file (const char *file_path);
|
||||
|
||||
@@ -589,8 +589,8 @@ jit_langhook_init (void)
|
||||
}
|
||||
|
||||
gcc_assert (global_dc);
|
||||
global_dc->begin_diagnostic = jit_begin_diagnostic;
|
||||
global_dc->end_diagnostic = jit_end_diagnostic;
|
||||
diagnostic_starter (global_dc) = jit_begin_diagnostic;
|
||||
diagnostic_finalizer (global_dc) = jit_end_diagnostic;
|
||||
|
||||
build_common_tree_nodes (false);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ test_diagnostic_context::test_diagnostic_context ()
|
||||
m_source_printing.enabled = true;
|
||||
m_source_printing.show_labels_p = true;
|
||||
show_column = true;
|
||||
start_span = start_span_cb;
|
||||
m_text_callbacks.start_span = start_span_cb;
|
||||
m_source_printing.min_margin_width = 6;
|
||||
m_source_printing.max_width = 80;
|
||||
}
|
||||
|
||||
@@ -181,27 +181,31 @@ test_diagnostic_start_span_fn (diagnostic_context *context,
|
||||
pp_newline (context->printer);
|
||||
}
|
||||
|
||||
/* Custom diagnostic callback: loudly announce a new diagnostic group. */
|
||||
/* Custom output format subclass. */
|
||||
|
||||
static void
|
||||
test_begin_group_cb (diagnostic_context * context)
|
||||
class test_output_format : public diagnostic_text_output_format
|
||||
{
|
||||
pp_string (context->printer,
|
||||
"================================= BEGIN GROUP ==============================");
|
||||
pp_newline (context->printer);
|
||||
}
|
||||
public:
|
||||
test_output_format (diagnostic_context &context)
|
||||
: diagnostic_text_output_format (context)
|
||||
{}
|
||||
|
||||
/* Custom diagnostic callback: loudly announce the end of a
|
||||
diagnostic group. */
|
||||
|
||||
static void
|
||||
test_end_group_cb (diagnostic_context * context)
|
||||
{
|
||||
pp_set_prefix (context->printer, NULL);
|
||||
pp_string (context->printer,
|
||||
"---------------------------------- END GROUP -------------------------------");
|
||||
pp_newline_and_flush (context->printer);
|
||||
}
|
||||
void on_begin_group () final override
|
||||
{
|
||||
/* Loudly announce a new diagnostic group. */
|
||||
pp_string (m_context.printer,
|
||||
"================================= BEGIN GROUP ==============================");
|
||||
pp_newline (m_context.printer);
|
||||
}
|
||||
void on_end_group () final override
|
||||
{
|
||||
/* Loudly announce the end of a diagnostic group. */
|
||||
pp_set_prefix (m_context.printer, NULL);
|
||||
pp_string (m_context.printer,
|
||||
"---------------------------------- END GROUP -------------------------------");
|
||||
pp_newline_and_flush (m_context.printer);
|
||||
}
|
||||
};
|
||||
|
||||
/* Entrypoint for the plugin.
|
||||
Install custom callbacks into the global_dc.
|
||||
@@ -220,9 +224,8 @@ plugin_init (struct plugin_name_args *plugin_info,
|
||||
return 1;
|
||||
|
||||
diagnostic_starter (global_dc) = test_diagnostic_starter;
|
||||
global_dc->start_span = test_diagnostic_start_span_fn;
|
||||
global_dc->begin_group_cb = test_begin_group_cb;
|
||||
global_dc->end_group_cb = test_end_group_cb;
|
||||
global_dc->m_text_callbacks.start_span = test_diagnostic_start_span_fn;
|
||||
global_dc->m_output_format = new test_output_format (*global_dc);
|
||||
|
||||
pass_info.pass = new pass_test_groups (g);
|
||||
pass_info.reference_pass_name = "*warn_function_noreturn";
|
||||
|
||||
@@ -206,7 +206,7 @@ struct event_range
|
||||
= linemap_client_expand_location_to_spelling_point
|
||||
(initial_loc, LOCATION_ASPECT_CARET);
|
||||
if (exploc.file != LOCATION_FILE (dc->last_location))
|
||||
dc->start_span (dc, exploc);
|
||||
dc->m_text_callbacks.start_span (dc, exploc);
|
||||
}
|
||||
|
||||
/* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
|
||||
|
||||
Reference in New Issue
Block a user