diff options
Diffstat (limited to 'gcc/diagnostic-format-text.cc')
-rw-r--r-- | gcc/diagnostic-format-text.cc | 734 |
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 |