aboutsummaryrefslogtreecommitdiff
path: root/gcc/diagnostic-format-text.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/diagnostic-format-text.cc')
-rw-r--r--gcc/diagnostic-format-text.cc734
1 files changed, 0 insertions, 734 deletions
diff --git a/gcc/diagnostic-format-text.cc b/gcc/diagnostic-format-text.cc
deleted file mode 100644
index 9273973..0000000
--- a/gcc/diagnostic-format-text.cc
+++ /dev/null
@@ -1,734 +0,0 @@
-/* Classic text-based output of diagnostics.
- Copyright (C) 1999-2025 Free Software Foundation, Inc.
-
-This file is part of GCC.
-
-GCC is free software; you can redistribute it and/or modify it under
-the terms of the GNU General Public License as published by the Free
-Software Foundation; either version 3, or (at your option) any later
-version.
-
-GCC is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
-for more details.
-
-You should have received a copy of the GNU General Public License
-along with GCC; see the file COPYING3. If not see
-<http://www.gnu.org/licenses/>. */
-
-
-#include "config.h"
-#define INCLUDE_VECTOR
-#include "system.h"
-#include "coretypes.h"
-#include "version.h"
-#include "intl.h"
-#include "diagnostic.h"
-#include "diagnostic-color.h"
-#include "diagnostic-url.h"
-#include "diagnostic-metadata.h"
-#include "diagnostic-path.h"
-#include "diagnostic-client-data-hooks.h"
-#include "diagnostic-diagram.h"
-#include "diagnostic-format-text.h"
-#include "diagnostic-buffer.h"
-#include "text-art/theme.h"
-#include "make-unique.h"
-
-/* Disable warnings about quoting issues in the pp_xxx calls below
- that (intentionally) don't follow GCC diagnostic conventions. */
-#if __GNUC__ >= 10
-# pragma GCC diagnostic push
-# pragma GCC diagnostic ignored "-Wformat-diag"
-#endif
-
-/* Concrete buffering implementation subclass for JSON output. */
-
-class diagnostic_text_format_buffer : public diagnostic_per_format_buffer
-{
-public:
- friend class diagnostic_text_output_format;
-
- diagnostic_text_format_buffer (diagnostic_output_format &format);
-
- void dump (FILE *out, int indent) const final override;
-
- bool empty_p () const final override;
- void move_to (diagnostic_per_format_buffer &dest) final override;
- void clear () final override;
- void flush () final override;
-
-private:
- diagnostic_output_format &m_format;
- output_buffer m_output_buffer;
-};
-
-/* class diagnostic_text_format_buffer : public diagnostic_per_format_buffer. */
-
-diagnostic_text_format_buffer::
-diagnostic_text_format_buffer (diagnostic_output_format &format)
-: m_format (format)
-{
- m_output_buffer.m_flush_p = false;
-}
-
-void
-diagnostic_text_format_buffer::dump (FILE *out, int indent) const
-{
- fprintf (out, "%*sdiagnostic_text_format_buffer:\n", indent, "");
- m_output_buffer.dump (out, indent + 2);
-}
-
-bool
-diagnostic_text_format_buffer::empty_p () const
-{
- return output_buffer_last_position_in_text (&m_output_buffer) == nullptr;
-}
-
-void
-diagnostic_text_format_buffer::move_to (diagnostic_per_format_buffer &base_dest)
-{
- diagnostic_text_format_buffer &dest
- = static_cast<diagnostic_text_format_buffer &> (base_dest);
- const char *str = output_buffer_formatted_text (&m_output_buffer);
- output_buffer_append_r (&dest.m_output_buffer, str, strlen (str));
-
- obstack_free (m_output_buffer.m_obstack,
- obstack_base (m_output_buffer.m_obstack));
- m_output_buffer.m_line_length = 0;
-}
-
-void
-diagnostic_text_format_buffer::clear ()
-{
- pretty_printer *const pp = m_format.get_printer ();
- output_buffer *const old_output_buffer = pp_buffer (pp);
-
- pp_buffer (pp) = &m_output_buffer;
-
- pp_clear_output_area (pp);
- gcc_assert (empty_p ());
-
- pp_buffer (pp) = old_output_buffer;
-}
-
-void
-diagnostic_text_format_buffer::flush ()
-{
- pretty_printer *const pp = m_format.get_printer ();
- output_buffer *const old_output_buffer = pp_buffer (pp);
-
- pp_buffer (pp) = &m_output_buffer;
-
- pp_really_flush (pp);
- gcc_assert (empty_p ());
-
- pp_buffer (pp) = old_output_buffer;
-}
-
-/* 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 (m_context.diagnostic_count (DK_WERROR))
- {
- pretty_printer *pp = get_printer ();
- /* -Werror was given. */
- if (m_context.warning_as_error_requested_p ())
- pp_verbatim (pp,
- _("%s: all warnings being treated as errors"),
- progname);
- /* At least one -Werror= was given. */
- else
- pp_verbatim (pp,
- _("%s: some warnings being treated as errors"),
- progname);
- pp_newline_and_flush (pp);
- }
-
- if (m_includes_seen)
- {
- delete m_includes_seen;
- m_includes_seen = nullptr;
- }
-}
-
-void
-diagnostic_text_output_format::dump (FILE *out, int indent) const
-{
- fprintf (out, "%*sdiagnostic_text_output_format\n", indent, "");
- fprintf (out, "%*sm_follows_reference_printer: %s\n",
- indent, "",
- m_follows_reference_printer ? "true" : "false");
- diagnostic_output_format::dump (out, indent);
- fprintf (out, "%*ssaved_output_buffer:\n", indent + 2, "");
- if (m_saved_output_buffer)
- m_saved_output_buffer->dump (out, indent + 4);
- else
- fprintf (out, "%*s(none):\n", indent + 4, "");
-}
-
-void
-diagnostic_text_output_format::set_buffer (diagnostic_per_format_buffer *base)
-{
- diagnostic_text_format_buffer * const buffer
- = static_cast<diagnostic_text_format_buffer *> (base);
-
- pretty_printer *const pp = get_printer ();
-
- if (!m_saved_output_buffer)
- m_saved_output_buffer = pp_buffer (pp);
-
- if (buffer)
- pp_buffer (pp) = &buffer->m_output_buffer;
- else
- {
- gcc_assert (m_saved_output_buffer);
- pp_buffer (pp) = m_saved_output_buffer;
- }
-}
-
-std::unique_ptr<diagnostic_per_format_buffer>
-diagnostic_text_output_format::make_per_format_buffer ()
-{
- return ::make_unique<diagnostic_text_format_buffer> (*this);
-}
-
-/* Implementation of diagnostic_output_format::on_report_diagnostic vfunc
- for GCC's standard textual output. */
-
-void
-diagnostic_text_output_format::
-on_report_diagnostic (const diagnostic_info &diagnostic,
- diagnostic_t orig_diag_kind)
-{
- pretty_printer *pp = get_printer ();
-
- (*diagnostic_text_starter (&m_context)) (*this, &diagnostic);
-
- pp_output_formatted_text (pp, m_context.get_urlifier ());
-
- if (m_context.m_show_cwe)
- print_any_cwe (diagnostic);
-
- if (m_context.m_show_rules)
- print_any_rules (diagnostic);
-
- if (m_context.m_show_option_requested)
- print_option_information (diagnostic, orig_diag_kind);
-
- /* If we're showing nested diagnostics, then print the location
- on a new line, indented. */
- if (m_show_nesting && m_show_locations_in_nesting)
- {
- const int nesting_level = get_context ().get_diagnostic_nesting_level ();
- if (nesting_level > 0)
- {
- location_t loc = diagnostic_location (&diagnostic);
- pp_set_prefix (pp, nullptr);
- char *indent_prefix = build_indent_prefix (false);
- /* Only print changes of location. */
- if (loc != get_context ().m_last_location
- && loc > BUILTINS_LOCATION)
- {
- const expanded_location s
- = diagnostic_expand_location (&diagnostic);
- label_text location_text = get_location_text (s);
- pp_newline (pp);
- pp_printf (pp, "%s%s", indent_prefix, location_text.get ());
- }
- pp_set_prefix (pp, indent_prefix);
- }
- }
-
- (*diagnostic_text_finalizer (&m_context)) (*this,
- &diagnostic,
- orig_diag_kind);
-
- if (m_show_nesting && m_show_locations_in_nesting)
- get_context ().m_last_location = diagnostic_location (&diagnostic);
-}
-
-void
-diagnostic_text_output_format::on_report_verbatim (text_info &text)
-{
- pp_format_verbatim (get_printer (), &text);
- pp_newline_and_flush (get_printer ());
-}
-
-void
-diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
-{
- pretty_printer *const pp = get_printer ();
-
- char *saved_prefix = pp_take_prefix (pp);
- pp_set_prefix (pp, 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 (pp);
- diagram.get_canvas ().print_to_pp (pp, " ");
- pp_newline (pp);
- pp_set_prefix (pp, saved_prefix);
- pp_flush (pp);
-}
-
-void
-diagnostic_text_output_format::
-after_diagnostic (const diagnostic_info &diagnostic)
-{
- if (const diagnostic_path *path = diagnostic.richloc->get_path ())
- print_path (*path);
-}
-
-/* Return a malloc'd string describing a location and the severity of the
- diagnostic, e.g. "foo.c:42:10: error: ".
-
- If m_show_nesting, then the above will be preceded by indentation to show
- the level, and a bullet point.
-
- The caller is responsible for freeing the memory. */
-char *
-diagnostic_text_output_format::
-build_prefix (const diagnostic_info &diagnostic) const
-{
- gcc_assert (diagnostic.kind < DK_LAST_DIAGNOSTIC_KIND);
-
- const char *text = _(get_diagnostic_kind_text (diagnostic.kind));
- const char *text_cs = "", *text_ce = "";
- pretty_printer *pp = get_printer ();
-
- if (const char *color_name = diagnostic_get_color_for_kind (diagnostic.kind))
- {
- text_cs = colorize_start (pp_show_color (pp), color_name);
- text_ce = colorize_stop (pp_show_color (pp));
- }
-
- const int nesting_level = get_context ().get_diagnostic_nesting_level ();
- if (m_show_nesting && nesting_level > 0)
- {
- char *indent_prefix = build_indent_prefix (true);
-
- /* Reduce verbosity of nested diagnostics by not printing "note: "
- all the time. */
- if (diagnostic.kind == DK_NOTE)
- return indent_prefix;
-
- char *result = build_message_string ("%s%s%s%s", indent_prefix,
- text_cs, text, text_ce);
- free (indent_prefix);
- return result;
- }
- else
- {
- const expanded_location s = diagnostic_expand_location (&diagnostic);
- label_text location_text = get_location_text (s);
- return build_message_string ("%s %s%s%s", location_text.get (),
- text_cs, text, text_ce);
- }
-}
-
-/* Same as build_prefix, but only the source FILE is given. */
-char *
-diagnostic_text_output_format::file_name_as_prefix (const char *f) const
-{
- pretty_printer *const pp = get_printer ();
- const char *locus_cs
- = colorize_start (pp_show_color (pp), "locus");
- const char *locus_ce = colorize_stop (pp_show_color (pp));
- return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
-}
-
-/* Get the unicode code point for bullet points when showing
- nested diagnostics. */
-
-static unsigned
-get_bullet_point_unichar (bool unicode)
-{
- if (unicode)
- return 0x2022; /* U+2022: Bullet */
- else
- return '*';
-}
-
-/* Return true if DC's theme supports unicode characters. */
-
-static bool
-use_unicode_p (const diagnostic_context &dc)
-{
- if (text_art::theme *theme = dc.get_diagram_theme ())
- return theme->unicode_p ();
- else
- return false;
-}
-
-/* Get the unicode code point for bullet points when showing
- nested diagnostics. */
-
-static unsigned
-get_bullet_point_unichar (diagnostic_context &dc)
-{
- return get_bullet_point_unichar (use_unicode_p (dc));
-}
-
-/* Return a malloc'd string for use as a prefix to show indentation.
- If m_show_nesting is false, or we're at the top-level, then the
- result will be the empty string.
-
- If m_show_nesting, then the result will contain indentation to show
- the nesting level, then either a bullet point (if WITH_BULLET is true),
- or a space.
-
- The caller is responsible for freeing the memory. */
-
-char *
-diagnostic_text_output_format::build_indent_prefix (bool with_bullet) const
-{
- if (!m_show_nesting)
- return xstrdup ("");
-
- const int nesting_level = get_context ().get_diagnostic_nesting_level ();
- if (nesting_level == 0)
- return xstrdup ("");
-
- pretty_printer pp;
- for (int i = 0; i < nesting_level; i++)
- pp_string (&pp, " ");
- if (with_bullet)
- pp_unicode_character (&pp, get_bullet_point_unichar (get_context ()));
- else
- pp_space (&pp);
- pp_space (&pp);
- if (m_show_nesting_levels)
- pp_printf (&pp, "(level %i):", nesting_level);
- return xstrdup (pp_formatted_text (&pp));
-}
-
-/* Add a purely textual note with text GMSGID and with LOCATION. */
-
-void
-diagnostic_text_output_format::append_note (location_t location,
- const char * gmsgid, ...)
-{
- diagnostic_context *context = &get_context ();
-
- diagnostic_info diagnostic;
- va_list ap;
- rich_location richloc (line_table, location);
-
- va_start (ap, gmsgid);
- diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
- if (context->m_inhibit_notes_p)
- {
- va_end (ap);
- return;
- }
- pretty_printer *pp = get_printer ();
- char *saved_prefix = pp_take_prefix (pp);
- pp_set_prefix (pp, build_prefix (diagnostic));
- pp_format (pp, &diagnostic.message);
- pp_output_formatted_text (pp);
- pp_destroy_prefix (pp);
- pp_set_prefix (pp, saved_prefix);
- pp_newline (pp);
- diagnostic_show_locus (context, get_source_printing_options (),
- &richloc, DK_NOTE, pp);
- va_end (ap);
-}
-
-bool
-diagnostic_text_output_format::follows_reference_printer_p () const
-{
- return m_follows_reference_printer;
-}
-
-void
-diagnostic_text_output_format::
-update_printer ()
-{
- pretty_printer *copy_from_pp
- = (m_follows_reference_printer
- ? get_context ().get_reference_printer ()
- : m_printer.get ());
- const bool show_color = pp_show_color (copy_from_pp);
- const diagnostic_url_format url_format = copy_from_pp->get_url_format ();
-
- m_printer = get_context ().clone_printer ();
-
- 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.
-
- For example, if the diagnostic metadata associates it with CWE-119,
- " [CWE-119]" will be printed, suitably colorized, and with a URL of a
- description of the security issue. */
-
-void
-diagnostic_text_output_format::print_any_cwe (const diagnostic_info &diagnostic)
-{
- if (diagnostic.metadata == NULL)
- return;
-
- int cwe = diagnostic.metadata->get_cwe ();
- if (cwe)
- {
- pretty_printer * const pp = get_printer ();
- char *saved_prefix = pp_take_prefix (pp);
- pp_string (pp, " [");
- const char *kind_color = diagnostic_get_color_for_kind (diagnostic.kind);
- pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
- if (pp->supports_urls_p ())
- {
- char *cwe_url = get_cwe_url (cwe);
- pp_begin_url (pp, cwe_url);
- free (cwe_url);
- }
- pp_printf (pp, "CWE-%i", cwe);
- pp_set_prefix (pp, saved_prefix);
- if (pp->supports_urls_p ())
- pp_end_url (pp);
- pp_string (pp, colorize_stop (pp_show_color (pp)));
- pp_character (pp, ']');
- }
-}
-
-/* If DIAGNOSTIC has any rules associated with it, print them.
-
- For example, if the diagnostic metadata associates it with a rule
- named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
- with any URL provided by the rule. */
-
-void
-diagnostic_text_output_format::
-print_any_rules (const diagnostic_info &diagnostic)
-{
- if (diagnostic.metadata == NULL)
- return;
-
- for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
- {
- const diagnostic_metadata::rule &rule
- = diagnostic.metadata->get_rule (idx);
- if (char *desc = rule.make_description ())
- {
- pretty_printer * const pp = get_printer ();
- char *saved_prefix = pp_take_prefix (pp);
- pp_string (pp, " [");
- const char *kind_color
- = diagnostic_get_color_for_kind (diagnostic.kind);
- pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
- char *url = NULL;
- if (pp->supports_urls_p ())
- {
- url = rule.make_url ();
- if (url)
- pp_begin_url (pp, url);
- }
- pp_string (pp, desc);
- pp_set_prefix (pp, saved_prefix);
- if (pp->supports_urls_p ())
- if (url)
- pp_end_url (pp);
- free (url);
- pp_string (pp, colorize_stop (pp_show_color (pp)));
- pp_character (pp, ']');
- free (desc);
- }
- }
-}
-
-/* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
- printer, e.g. " [-Werror=uninitialized]".
- Subroutine of diagnostic_context::report_diagnostic. */
-
-void
-diagnostic_text_output_format::
-print_option_information (const diagnostic_info &diagnostic,
- diagnostic_t orig_diag_kind)
-{
- if (char *option_text
- = m_context.make_option_name (diagnostic.option_id,
- orig_diag_kind, diagnostic.kind))
- {
- char *option_url = nullptr;
- pretty_printer * const pp = get_printer ();
- if (pp->supports_urls_p ())
- option_url = m_context.make_option_url (diagnostic.option_id);
- pp_string (pp, " [");
- const char *kind_color = diagnostic_get_color_for_kind (diagnostic.kind);
- pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
- if (option_url)
- pp_begin_url (pp, option_url);
- pp_string (pp, option_text);
- if (option_url)
- {
- pp_end_url (pp);
- free (option_url);
- }
- pp_string (pp, colorize_stop (pp_show_color (pp)));
- pp_character (pp, ']');
- free (option_text);
- }
-}
-
-/* Only dump the "In file included from..." stack once for each file. */
-
-bool
-diagnostic_text_output_format::includes_seen_p (const line_map_ordinary *map)
-{
- /* No include path for main. */
- if (MAIN_FILE_P (map))
- return true;
-
- /* Always identify C++ modules, at least for now. */
- auto probe = map;
- if (linemap_check_ordinary (map)->reason == LC_RENAME)
- /* The module source file shows up as LC_RENAME inside LC_MODULE. */
- probe = linemap_included_from_linemap (line_table, map);
- if (MAP_MODULE_P (probe))
- return false;
-
- if (!m_includes_seen)
- m_includes_seen = new hash_set<location_t, false, location_hash>;
-
- /* Hash the location of the #include directive to better handle files
- that are included multiple times with different macros defined. */
- return m_includes_seen->add (linemap_included_from (map));
-}
-
-label_text
-diagnostic_text_output_format::
-get_location_text (const expanded_location &s) const
-{
- diagnostic_column_policy column_policy (get_context ());
- return column_policy.get_location_text (s,
- show_column_p (),
- pp_show_color (get_printer ()));
-}
-
-/* Helpers for writing lang-specific starters/finalizers for text output. */
-
-/* Return a formatted line and column ':%line:%column'. Elided if
- line == 0 or col < 0. (A column of 0 may be valid due to the
- -fdiagnostics-column-origin option.)
- The result is a statically allocated buffer. */
-
-const char *
-maybe_line_and_column (int line, int col)
-{
- static char result[32];
-
- if (line)
- {
- size_t l
- = snprintf (result, sizeof (result),
- col >= 0 ? ":%d:%d" : ":%d", line, col);
- gcc_checking_assert (l < sizeof (result));
- }
- else
- result[0] = 0;
- return result;
-}
-
-void
-diagnostic_text_output_format::report_current_module (location_t where)
-{
- pretty_printer *pp = get_printer ();
- const line_map_ordinary *map = NULL;
-
- if (pp_needs_newline (pp))
- {
- pp_newline (pp);
- pp_needs_newline (pp) = false;
- }
-
- if (where <= BUILTINS_LOCATION)
- return;
-
- linemap_resolve_location (line_table, where,
- LRK_MACRO_DEFINITION_LOCATION,
- &map);
-
- if (map && m_last_module != map)
- {
- m_last_module = map;
- if (!includes_seen_p (map))
- {
- bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
- expanded_location s = {};
- do
- {
- where = linemap_included_from (map);
- map = linemap_included_from_linemap (line_table, map);
- bool is_module = MAP_MODULE_P (map);
- s.file = LINEMAP_FILE (map);
- s.line = SOURCE_LINE (map, where);
- int col = -1;
- if (first && show_column_p ())
- {
- s.column = SOURCE_COLUMN (map, where);
- col = get_column_policy ().converted_column (s);
- }
- const char *line_col = maybe_line_and_column (s.line, col);
- static const char *const msgs[] =
- {
- NULL,
- N_(" from"),
- N_("In file included from"), /* 2 */
- N_(" included from"),
- N_("In module"), /* 4 */
- N_("of module"),
- N_("In module imported at"), /* 6 */
- N_("imported at"),
- };
-
- unsigned index = (was_module ? 6 : is_module ? 4
- : need_inc ? 2 : 0) + !first;
-
- pp_verbatim (pp, "%s%s %r%s%s%R",
- first ? "" : was_module ? ", " : ",\n",
- _(msgs[index]),
- "locus", s.file, line_col);
- first = false, need_inc = was_module, was_module = is_module;
- }
- while (!includes_seen_p (map));
- pp_verbatim (pp, ":");
- pp_newline (pp);
- }
- }
-}
-
-void
-default_diagnostic_text_starter (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic)
-{
- text_output.report_current_module (diagnostic_location (diagnostic));
- pretty_printer *const pp = text_output.get_printer ();
- pp_set_prefix (pp, text_output.build_prefix (*diagnostic));
-}
-
-void
-default_diagnostic_text_finalizer (diagnostic_text_output_format &text_output,
- const diagnostic_info *diagnostic,
- diagnostic_t)
-{
- pretty_printer *const pp = text_output.get_printer ();
- char *saved_prefix = pp_take_prefix (pp);
- 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);
-}
-
-#if __GNUC__ >= 10
-# pragma GCC diagnostic pop
-#endif