richloc.add_range (param, SHOW_RANGE_WITHOUT_CARET, ¶m_label);
test_diagnostic_context dc;
- diagnostic_show_locus (&dc, &richloc, DK_ERROR, dc.get_reference_printer ());
+ diagnostic_show_locus (&dc,
+ dc.m_source_printing,
+ &richloc, DK_ERROR, dc.get_reference_printer ());
if (c_dialect_cxx ())
/* "char*", without a space. */
ASSERT_STREQ (" printf (\"msg: %i\\n\", msg);\n"
pp_set_prefix (pp, text_output.build_indent_prefix (false));
pp_newline (pp);
diagnostic_show_locus (&text_output.get_context (),
+ text_output.get_source_printing_options (),
diagnostic->richloc, diagnostic->kind, pp);
/* By default print macro expansion contexts in the diagnostic
finalizer -- for tokens resulting from macro expansion. */
char *saved_prefix = pp_take_prefix (pp);
pp_set_prefix (pp, indent);
gcc_rich_location rich_loc (m_loc);
- diagnostic_show_locus (&m_text_output.get_context (), &rich_loc,
+ diagnostic_show_locus (&m_text_output.get_context (),
+ m_text_output.get_source_printing_options (),
+ &rich_loc,
DK_NOTE, pp);
pp_set_prefix (pp, saved_prefix);
}
char *saved_prefix = pp_take_prefix (pp);
pp_set_prefix (pp, nullptr);
gcc_rich_location rich_loc (m_loc);
- diagnostic_show_locus (&m_text_output.get_context (), &rich_loc,
+ diagnostic_show_locus (&m_text_output.get_context (),
+ m_text_output.get_source_printing_options (),
+ &rich_loc,
DK_NOTE, pp);
pp_set_prefix (pp, saved_prefix);
}
pp_destroy_prefix (pp);
pp_set_prefix (pp, saved_prefix);
pp_newline (pp);
- diagnostic_show_locus (context, &richloc, DK_NOTE, pp);
+ diagnostic_show_locus (context, get_source_printing_options (),
+ &richloc, DK_NOTE, pp);
va_end (ap);
}
pp_show_color (m_printer.get ()) = show_color;
m_printer->set_url_format (url_format);
// ...etc
+
+ m_source_printing = get_context ().m_source_printing;
}
/* If DIAGNOSTIC has a CWE identifier, print it.
pp_set_prefix (pp, NULL);
pp_newline (pp);
diagnostic_show_locus (&text_output.get_context (),
+ text_output.get_source_printing_options (),
diagnostic->richloc, diagnostic->kind, pp);
pp_set_prefix (pp, saved_prefix);
pp_flush (pp);
{
public:
diagnostic_text_output_format (diagnostic_context &context,
+ diagnostic_source_printing_options *source_printing = nullptr,
bool follows_reference_printer = false)
: diagnostic_output_format (context),
m_saved_output_buffer (nullptr),
m_column_policy (context),
m_last_module (nullptr),
m_includes_seen (nullptr),
+ m_source_printing (source_printing
+ ? *source_printing
+ : context.m_source_printing),
m_follows_reference_printer (follows_reference_printer),
m_show_nesting (false),
m_show_nesting_levels (false)
label_text get_location_text (const expanded_location &s) const;
+ diagnostic_source_printing_options &get_source_printing_options ()
+ {
+ return m_source_printing;
+ }
+ const diagnostic_source_printing_options &get_source_printing_options () const
+ {
+ return m_source_printing;
+ }
+
protected:
void print_any_cwe (const diagnostic_info &diagnostic);
void print_any_rules (const diagnostic_info &diagnostic);
include path for. */
hash_set<location_t, false, location_hash> *m_includes_seen;
+ diagnostic_source_printing_options &m_source_printing;
+
/* If true, this is the initial default text output format created
when the diagnostic_context was created, and, in particular, before
initializations of color and m_url_format. Hence this should follow
}
/* Call diagnostic_show_locus to show the events using labels. */
- diagnostic_show_locus (&dc, &m_richloc, DK_DIAGNOSTIC_PATH, &pp,
+ diagnostic_show_locus (&dc, text_output.get_source_printing_options (),
+ &m_richloc, DK_DIAGNOSTIC_PATH, &pp,
effect_info);
/* If we have a macro expansion, show the expansion to the user. */
pretty_printer *const pp = get_printer ();
const bool check_rich_locations = true;
const bool colorize = pp_show_color (pp);
- const bool show_event_links
- = get_context ().m_source_printing.show_event_links_p;
+ const bool show_event_links = m_source_printing.show_event_links_p;
path_summary summary (policy,
*pp,
path,
{
test_diagnostic_context dc;
- diagnostic_text_output_format text_output (dc, false);
+ diagnostic_text_output_format text_output (dc, nullptr, false);
path_print_policy policy (text_output);
path_summary summary (policy, *event_pp, path, false);
ASSERT_EQ (summary.get_num_ranges (), 9);
bool restrict_to_current_line_spans,
const range_label *label)
{
- diagnostic_source_print_policy source_policy (dc);
+ diagnostic_source_print_policy source_policy (dc,
+ dc.m_source_printing);
return add_location_if_nearby (source_policy, loc,
restrict_to_current_line_spans, label);
}
void
diagnostic_context::maybe_show_locus (const rich_location &richloc,
+ const diagnostic_source_printing_options &opts,
diagnostic_t diagnostic_kind,
pretty_printer &pp,
diagnostic_source_effect_info *effects)
{
const location_t loc = richloc.get_loc ();
/* Do nothing if source-printing has been disabled. */
- if (!m_source_printing.enabled)
+ if (!opts.enabled)
return;
/* Don't attempt to print source for UNKNOWN_LOCATION and for builtins. */
m_last_location = loc;
- diagnostic_source_print_policy source_policy (*this);
+ diagnostic_source_print_policy source_policy (*this, opts);
source_policy.print (pp, richloc, diagnostic_kind, effects);
}
{
}
+diagnostic_source_print_policy::
+diagnostic_source_print_policy (const diagnostic_context &dc,
+ const diagnostic_source_printing_options &opts)
+: m_options (opts),
+ m_location_policy (dc),
+ m_start_span_cb (dc.m_text_callbacks.m_start_span),
+ m_file_cache (dc.get_file_cache ()),
+ m_diagram_theme (dc.get_diagram_theme ()),
+ m_escape_format (dc.get_escape_format ())
+{
+}
+
/* Print to PP the physical source code corresponding to the location(s)
in RICHLOC, with additional annotations, as if for a diagnostic of the
given DIAGNOSTIC_KIND.
m_diagnostic_groups.m_group_nesting_depth = 0;
m_diagnostic_groups.m_diagnostic_nesting_level = 0;
m_diagnostic_groups.m_emission_count = 0;
- m_output_sinks.safe_push (new diagnostic_text_output_format (*this, true));
+ m_output_sinks.safe_push
+ (new diagnostic_text_output_format (*this, nullptr, true));
m_set_locations_cb = nullptr;
m_client_data_hooks = nullptr;
m_diagrams.m_theme = nullptr;
m_diagnostic_counters.dump (out, 2);
fprintf (out, " reference printer:\n");
m_reference_printer->dump (out, 4);
- for (unsigned i = 0; i < m_output_sinks.length (); ++i)
+ fprintf (out, " output sinks:\n");
+ if (m_output_sinks.length () > 0)
{
- fprintf (out, " sink %i:\n", i);
- m_output_sinks[i]->dump (out, 4);
+ for (unsigned i = 0; i < m_output_sinks.length (); ++i)
+ {
+ fprintf (out, " sink %i:\n", i);
+ m_output_sinks[i]->dump (out, 4);
+ }
}
+ else
+ fprintf (out, " (none):\n");
fprintf (out, " diagnostic buffer:\n");
if (m_diagnostic_buffer)
m_diagnostic_buffer->dump (out, 4);
}
void
-diagnostic_context::
-set_output_format (std::unique_ptr<diagnostic_output_format> output_format)
+diagnostic_context::remove_all_output_sinks ()
{
while (!m_output_sinks.is_empty ())
delete m_output_sinks.pop ();
+}
+
+void
+diagnostic_context::
+set_output_format (std::unique_ptr<diagnostic_output_format> output_format)
+{
+ remove_all_output_sinks ();
m_output_sinks.safe_push (output_format.release ());
}
{
public:
diagnostic_source_print_policy (const diagnostic_context &);
+ diagnostic_source_print_policy (const diagnostic_context &,
+ const diagnostic_source_printing_options &);
void
print (pretty_printer &pp,
}
void maybe_show_locus (const rich_location &richloc,
+ const diagnostic_source_printing_options &opts,
diagnostic_t diagnostic_kind,
pretty_printer &pp,
diagnostic_source_effect_info *effect_info);
void
add_sink (std::unique_ptr<diagnostic_output_format>);
+ void remove_all_output_sinks ();
+
bool supports_fnotice_on_stderr_p () const;
private:
inline void
diagnostic_show_locus (diagnostic_context *context,
+ const diagnostic_source_printing_options &opts,
rich_location *richloc,
diagnostic_t diagnostic_kind,
pretty_printer *pp,
gcc_assert (context);
gcc_assert (richloc);
gcc_assert (pp);
- context->maybe_show_locus (*richloc, diagnostic_kind, *pp, effect_info);
+ context->maybe_show_locus (*richloc, opts, diagnostic_kind, *pp, effect_info);
}
/* Because we read source files a second time after the frontend did it the
pp_newline (pp);
pp_set_prefix (pp, NULL);
pp_newline (pp);
- diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind,
+ diagnostic_show_locus (context,
+ text_output.get_source_printing_options (),
+ diagnostic->richloc, diagnostic->kind,
pp);
/* If the caret line was shown, the prefix does not contain the
locus. */
class sink
{
-public:
- virtual ~sink ();
-
- void begin_group ()
- {
- m_dc.begin_group ();
- }
- void end_group ()
- {
- m_dc.end_group ();
- }
-
- void emit (diagnostic &diag, const char *msgid, va_list *args)
- LIBGDIAGNOSTICS_PARAM_GCC_FORMAT_STRING (3, 0);
-
protected:
- sink (diagnostic_manager &mgr);
+ sink (diagnostic_manager &mgr) : m_mgr (mgr) {}
diagnostic_manager &m_mgr;
-
- /* One context per sink. */
- diagnostic_context m_dc;
};
/* This has to be a "struct" as it is exposed in the C API. */
FILE *dst_stream,
enum diagnostic_colorize colorize);
- void
- on_begin_text_diagnostic (diagnostic_text_output_format &text_format,
- const diagnostic_info *info);
-
diagnostic_source_printing_options &get_source_printing_options ()
{
- return m_dc.m_source_printing;
+ return m_source_printing;
}
void
set_colorize (enum diagnostic_colorize colorize);
+ static void
+ text_starter (diagnostic_text_output_format &text_output,
+ const diagnostic_info *diagnostic);
+
private:
- const diagnostic_logical_location *m_current_logical_loc;
+ diagnostic_text_output_format *m_inner_sink; // borrowed from dc
+ diagnostic_source_printing_options m_source_printing;
};
class sarif_sink : public sink
{
public:
diagnostic_manager ()
- : m_current_diag (nullptr),
- m_edit_context (m_file_cache)
+ : m_current_diag (nullptr),
+ m_prev_diag_logical_loc (nullptr)
{
linemap_init (&m_line_table, BUILTINS_LOCATION);
m_line_table.m_reallocator = xrealloc;
m_line_table.m_round_alloc_size = round_alloc_size;
m_line_table.default_range_bits = line_map_suggested_range_bits;
+
+ diagnostic_initialize (&m_dc, 0);
+ m_dc.remove_all_output_sinks ();
+
+ /* Get defaults from environemt. These might be
+ overridden by individual sinks. */
+ diagnostic_color_init (&m_dc, DIAGNOSTICS_COLOR_AUTO);
+ diagnostic_urls_init (&m_dc);
+
+ m_dc.set_show_cwe (true);
+ m_dc.set_show_rules (true);
+ m_dc.m_show_column = true;
+ m_dc.m_source_printing.enabled = true;
+ m_dc.m_source_printing.colorize_source_p = true;
+
+ /* We don't currently expose a way for clients to manipulate the
+ following. */
+ m_dc.m_source_printing.show_labels_p = true;
+ m_dc.m_source_printing.show_line_numbers_p = true;
+ m_dc.m_source_printing.min_margin_width = 6;
+ m_dc.set_path_format (DPF_INLINE_EVENTS);
+
+ m_dc.m_client_aux_data = this;
+ m_dc.set_client_data_hooks
+ (::make_unique<impl_diagnostic_client_data_hooks> (*this));
+
+ diagnostic_text_starter (&m_dc) = diagnostic_text_sink::text_starter;
+
+ m_edit_context = ::make_unique <edit_context> (m_dc.get_file_cache ());
}
+
~diagnostic_manager ()
{
- /* Clean up sinks first, as they can use other fields. */
+ diagnostic_finish (&m_dc);
+
for (size_t i = 0; i < m_sinks.size (); i++)
m_sinks[i] = nullptr;
}
line_maps *get_line_table () { return &m_line_table; }
- file_cache *get_file_cache () { return &m_file_cache; }
+ diagnostic_context &get_dc () { return m_dc; }
void write_patch (FILE *dst_stream);
void begin_group ()
{
- for (auto &sink : m_sinks)
- sink->begin_group ();
+ m_dc.begin_group ();
}
void end_group ()
{
- for (auto &sink : m_sinks)
- sink->end_group ();
+ m_dc.end_group ();
}
const char *
line_table = const_cast<line_maps *> (&m_line_table);
}
+ const diagnostic_logical_location *
+ get_prev_diag_logical_loc () const
+ {
+ return m_prev_diag_logical_loc;
+ }
+
private:
void
ensure_linemap_for_file_and_line (const diagnostic_file *file,
return phys_loc;
}
+ diagnostic_context m_dc;
line_maps m_line_table;
- file_cache m_file_cache;
impl_client_version_info m_client_version_info;
std::vector<std::unique_ptr<sink>> m_sinks;
hash_map<nofree_string_hash, diagnostic_file *> m_str_to_file_map;
diagnostic_physical_location *> m_location_t_map;
std::vector<std::unique_ptr<diagnostic_logical_location>> m_logical_locs;
const diagnostic *m_current_diag;
- edit_context m_edit_context;
+ const diagnostic_logical_location *m_prev_diag_logical_loc;
+ std::unique_ptr<edit_context> m_edit_context;
};
class impl_rich_location : public rich_location
// No-op.
}
-/* class sink. */
-
-void
-sink::emit (diagnostic &diag, const char *msgid, va_list *args)
-{
- diagnostic_info info;
-GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format)
- diagnostic_set_info (&info, msgid, args, diag.get_rich_location (),
- diagnostic_t_from_diagnostic_level (diag.get_level ()));
-GCC_DIAGNOSTIC_POP
- info.metadata = diag.get_metadata ();
- diagnostic_report_diagnostic (&m_dc, &info);
-}
-
-sink::sink (diagnostic_manager &mgr)
-: m_mgr (mgr)
-{
- diagnostic_initialize (&m_dc, 0);
- m_dc.m_client_aux_data = this;
- m_dc.set_client_data_hooks
- (::make_unique<impl_diagnostic_client_data_hooks> (mgr));
-}
+/* struct diagnostic_text_sink : public sink. */
-sink::~sink ()
-{
- diagnostic_finish (&m_dc);
+diagnostic_text_sink::diagnostic_text_sink (diagnostic_manager &mgr,
+ FILE *dst_stream,
+ enum diagnostic_colorize colorize)
+: sink (mgr),
+ m_source_printing (mgr.get_dc ().m_source_printing)
+{
+ auto inner_sink
+ = ::make_unique<diagnostic_text_output_format> (mgr.get_dc (),
+ &m_source_printing);
+ inner_sink->get_printer ()->set_output_stream (dst_stream);
+ m_inner_sink = inner_sink.get ();
+ set_colorize (colorize);
+ mgr.get_dc ().add_sink (std::move (inner_sink));
}
-/* struct diagnostic_text_sink : public sink. */
-
-static diagnostic_color_rule_t
-get_color_rule (enum diagnostic_colorize colorize)
+void
+diagnostic_text_sink::set_colorize (enum diagnostic_colorize colorize)
{
+ pretty_printer *const pp = m_inner_sink->get_printer ();
switch (colorize)
{
default:
gcc_unreachable ();
case DIAGNOSTIC_COLORIZE_IF_TTY:
- return DIAGNOSTICS_COLOR_AUTO;
+ pp_show_color (pp)
+ = pp_show_color (m_mgr.get_dc ().get_reference_printer ());
break;
case DIAGNOSTIC_COLORIZE_NO:
- return DIAGNOSTICS_COLOR_NO;
+ pp_show_color (pp) = false;
break;
case DIAGNOSTIC_COLORIZE_YES:
- return DIAGNOSTICS_COLOR_YES;
+ pp_show_color (pp) = true;
break;
}
}
-diagnostic_text_sink::diagnostic_text_sink (diagnostic_manager &mgr,
- FILE *dst_stream,
- enum diagnostic_colorize colorize)
-: sink (mgr),
- m_current_logical_loc (nullptr)
-{
- m_dc.set_show_cwe (true);
- m_dc.set_show_rules (true);
-
- diagnostic_color_init (&m_dc, get_color_rule (colorize));
- diagnostic_urls_init (&m_dc);
-
- auto text_format = ::make_unique<diagnostic_text_output_format> (m_dc, true);
- text_format->get_printer ()->set_output_stream (dst_stream);
- m_dc.set_output_format (std::move (text_format));
- diagnostic_text_starter (&m_dc)
- = [] (diagnostic_text_output_format &text_format,
- const diagnostic_info *info)
- {
- diagnostic_context &dc = text_format.get_context ();
- diagnostic_text_sink *sink
- = static_cast<diagnostic_text_sink *> (dc.m_client_aux_data);
- sink->on_begin_text_diagnostic (text_format, info);
- };
- m_dc.set_show_cwe (true);
- m_dc.set_show_rules (true);
- m_dc.m_show_column = true;
- m_dc.m_source_printing.enabled = true;
- m_dc.m_source_printing.colorize_source_p = true;
-
- /* We don't currently expose a way for clients to manipulate the
- following. */
- m_dc.m_source_printing.show_labels_p = true;
- m_dc.m_source_printing.show_line_numbers_p = true;
- m_dc.m_source_printing.min_margin_width = 6;
- m_dc.set_path_format (DPF_INLINE_EVENTS);
-}
-
-void
-diagnostic_text_sink::set_colorize (enum diagnostic_colorize colorize)
-{
- diagnostic_color_init (&m_dc, get_color_rule (colorize));
-}
-
void
-diagnostic_text_sink::
-on_begin_text_diagnostic (diagnostic_text_output_format &text_format,
- const diagnostic_info *info)
+diagnostic_text_sink::text_starter (diagnostic_text_output_format &text_output,
+ const diagnostic_info *info)
{
- const diagnostic *diag = m_mgr.get_current_diag ();
- gcc_assert (diag);
- pretty_printer *pp = text_format.get_printer ();
+ gcc_assert (info->x_data);
+ const diagnostic &diag = *static_cast<const diagnostic *> (info->x_data);
+ pretty_printer *pp = text_output.get_printer ();
const diagnostic_logical_location *diag_logical_loc
- = diag->get_logical_location ();
- if (m_current_logical_loc != diag_logical_loc)
+ = diag.get_logical_location ();
+ diagnostic_manager &mgr = diag.get_manager ();
+ if (diag_logical_loc && diag_logical_loc != mgr.get_prev_diag_logical_loc ())
{
- m_current_logical_loc = diag_logical_loc;
- if (m_current_logical_loc)
+ pp_set_prefix (pp, nullptr);
+ switch (diag_logical_loc->get_kind ())
{
- pp_set_prefix (pp, nullptr);
- switch (m_current_logical_loc->get_kind ())
+ default:
+ break;
+ case LOGICAL_LOCATION_KIND_FUNCTION:
+ if (const char *name
+ = diag_logical_loc->get_name_with_scope ())
{
- default:
- break;
- case LOGICAL_LOCATION_KIND_FUNCTION:
- if (const char *name
- = m_current_logical_loc->get_name_with_scope ())
- {
- pp_printf (pp, _("In function %qs"), name);
- pp_character (pp, ':');
- pp_newline (pp);
- }
- break;
- // TODO: handle other cases
+ pp_printf (pp, _("In function %qs"), name);
+ pp_character (pp, ':');
+ pp_newline (pp);
}
+ break;
+ // TODO: handle other cases
}
}
pp_set_prefix (pp,
- text_format.build_prefix (*info));
+ text_output.build_prefix (*info));
}
/* class sarif_sink : public sink. */
enum sarif_version version)
: sink (mgr)
{
- const char *main_input_filename = main_input_file->get_name ();
- diagnostic_output_format_init_sarif_stream (m_dc,
- mgr.get_line_table (),
- main_input_filename,
- true,
- version,
- dst_stream);
+ diagnostic_output_file output_file (dst_stream, false,
+ label_text::borrow ("sarif_sink"));
+ auto inner_sink = make_sarif_sink (mgr.get_dc (),
+ *mgr.get_line_table (),
+ main_input_file->get_name (),
+ version,
+ std::move (output_file));
+ mgr.get_dc ().add_sink (std::move (inner_sink));
}
/* struct diagnostic_manager. */
{
pretty_printer pp;
pp.set_output_stream (dst_stream);
- m_edit_context.print_diff (&pp, true);
+ m_edit_context->print_diff (&pp, true);
pp_flush (&pp);
}
set_line_table_global ();
m_current_diag = &diag;
- for (auto &sink : m_sinks)
- {
- va_list arg_copy;
- va_copy (arg_copy, *args);
- sink->emit (diag, msgid, &arg_copy);
- }
+
+ {
+ m_dc.begin_group ();
+
+ diagnostic_info info;
+GCC_DIAGNOSTIC_PUSH_IGNORED(-Wsuggest-attribute=format)
+ diagnostic_set_info (&info, msgid, args, diag.get_rich_location (),
+ diagnostic_t_from_diagnostic_level (diag.get_level ()));
+GCC_DIAGNOSTIC_POP
+ info.metadata = diag.get_metadata ();
+ info.x_data = &diag;
+ diagnostic_report_diagnostic (&m_dc, &info);
+
+ m_dc.end_group ();
+ }
rich_location *rich_loc = diag.get_rich_location ();
if (rich_loc->fixits_can_be_auto_applied_p ())
- m_edit_context.add_fixits (rich_loc);
+ m_edit_context->add_fixits (rich_loc);
+ m_prev_diag_logical_loc = diag.get_logical_location ();
m_current_diag = nullptr;
}
pp_set_prefix (pp, NULL);
pp_newline (pp);
diagnostic_show_locus (&text_output.get_context (),
+ text_output.get_source_printing_options (),
diagnostic->richloc, diagnostic->kind, pp);
pp_show_color (pp) = old_show_color;
pp_set_prefix (pp, saved_prefix);
auto pre = ::make_unique<xml::element> ("pre", true);
pre->set_attr ("class", label_text::borrow ("gcc-annotated-source"));
// TODO: ideally we'd like to capture elements within the following:
- diagnostic_show_locus (&m_context, diagnostic.richloc, diagnostic.kind,
+ diagnostic_show_locus (&m_context, m_context.m_source_printing,
+ diagnostic.richloc, diagnostic.kind,
m_printer);
pre->add_text
(label_text::take (xstrdup (pp_formatted_text (m_printer))));
{
/* Run the diagnostic and fix-it printing code. */
test_diagnostic_context dc;
- diagnostic_show_locus (&dc, richloc, DK_ERROR, dc.get_reference_printer ());
+ diagnostic_show_locus (&dc, dc.m_source_printing,
+ richloc, DK_ERROR, dc.get_reference_printer ());
/* Generate a diff. */
edit_context ec (global_dc->get_file_cache ());