LCOV - code coverage report
Current view: top level - gcc/diagnostics - text-sink.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.2 % 342 305
Test Date: 2026-02-28 14:20:25 Functions: 90.9 % 33 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Classic text-based output of diagnostics.
       2              :    Copyright (C) 1999-2026 Free Software Foundation, Inc.
       3              : 
       4              : This file is part of GCC.
       5              : 
       6              : GCC is free software; you can redistribute it and/or modify it under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : for more details.
      15              : 
      16              : You should have received a copy of the GNU General Public License
      17              : along with GCC; see the file COPYING3.  If not see
      18              : <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : 
      21              : #include "config.h"
      22              : #define INCLUDE_VECTOR
      23              : #include "system.h"
      24              : #include "coretypes.h"
      25              : #include "version.h"
      26              : #include "intl.h"
      27              : #include "diagnostics/color.h"
      28              : #include "diagnostics/url.h"
      29              : #include "diagnostics/metadata.h"
      30              : #include "diagnostics/paths.h"
      31              : #include "diagnostics/client-data-hooks.h"
      32              : #include "diagnostics/diagram.h"
      33              : #include "diagnostics/text-sink.h"
      34              : #include "diagnostics/buffering.h"
      35              : #include "diagnostics/dumping.h"
      36              : #include "diagnostics/logging.h"
      37              : #include "text-art/theme.h"
      38              : 
      39              : /* Disable warnings about quoting issues in the pp_xxx calls below
      40              :    that (intentionally) don't follow GCC diagnostic conventions.  */
      41              : #if __GNUC__ >= 10
      42              : #  pragma GCC diagnostic push
      43              : #  pragma GCC diagnostic ignored "-Wformat-diag"
      44              : #endif
      45              : 
      46              : namespace diagnostics {
      47              : 
      48              : /* Concrete buffering implementation subclass for text output.  */
      49              : 
      50              : class text_sink_buffer : public per_sink_buffer
      51              : {
      52              : public:
      53              :   friend class text_sink;
      54              : 
      55              :   text_sink_buffer (sink &sink_);
      56              : 
      57              :   void dump (FILE *out, int indent) const final override;
      58              : 
      59              :   bool empty_p () const final override;
      60              :   void move_to (per_sink_buffer &dest) final override;
      61              :   void clear () final override;
      62              :   void flush () final override;
      63              : 
      64              : private:
      65              :   sink &m_sink;
      66              :   output_buffer m_output_buffer;
      67              : };
      68              : 
      69              : /* class text_sink_buffer : public per_sink_buffer.  */
      70              : 
      71        98059 : text_sink_buffer::text_sink_buffer (sink &sink_)
      72        98059 : : m_sink (sink_)
      73              : {
      74        98059 :   m_output_buffer.m_flush_p = false;
      75        98059 : }
      76              : 
      77              : void
      78            0 : text_sink_buffer::dump (FILE *out, int indent) const
      79              : {
      80            0 :   dumping::emit_heading (out, indent, "text_sink_buffer");
      81            0 :   m_output_buffer.dump (out, indent + 2);
      82            0 : }
      83              : 
      84              : bool
      85      8405876 : text_sink_buffer::empty_p () const
      86              : {
      87      8405876 :   return output_buffer_last_position_in_text (&m_output_buffer) == nullptr;
      88              : }
      89              : 
      90              : void
      91        23297 : text_sink_buffer::move_to (per_sink_buffer &base_dest)
      92              : {
      93        23297 :   text_sink_buffer &dest
      94              :     = static_cast<text_sink_buffer &> (base_dest);
      95        23297 :   const char *str = output_buffer_formatted_text (&m_output_buffer);
      96        23297 :   output_buffer_append_r (&dest.m_output_buffer, str, strlen (str));
      97              : 
      98        23297 :   obstack_free (m_output_buffer.m_obstack,
      99              :                 obstack_base (m_output_buffer.m_obstack));
     100        23297 :   m_output_buffer.m_line_length = 0;
     101        23297 : }
     102              : 
     103              : void
     104      5141150 : text_sink_buffer::clear ()
     105              : {
     106      5141150 :   pretty_printer *const pp = m_sink.get_printer ();
     107      5141150 :   output_buffer *const old_output_buffer = pp_buffer (pp);
     108              : 
     109      5141150 :   pp_buffer (pp) = &m_output_buffer;
     110              : 
     111      5141150 :   pp_clear_output_area (pp);
     112      5141150 :   gcc_assert (empty_p ());
     113              : 
     114      5141150 :   pp_buffer (pp) = old_output_buffer;
     115      5141150 : }
     116              : 
     117              : void
     118         7283 : text_sink_buffer::flush ()
     119              : {
     120         7283 :   pretty_printer *const pp = m_sink.get_printer ();
     121         7283 :   output_buffer *const old_output_buffer = pp_buffer (pp);
     122              : 
     123         7283 :   pp_buffer (pp) = &m_output_buffer;
     124              : 
     125         7283 :   pp_really_flush (pp);
     126         7283 :   gcc_assert (empty_p ());
     127              : 
     128         7283 :   pp_buffer (pp) = old_output_buffer;
     129         7283 : }
     130              : 
     131              : /* class diagnostics::text_sink : public diagnostics::sink.  */
     132              : 
     133       612985 : text_sink::~text_sink ()
     134              : {
     135              :   /* Some of the errors may actually have been warnings.  */
     136       307868 :   if (m_context.diagnostic_count (kind::werror))
     137              :     {
     138          190 :       pretty_printer *pp = get_printer ();
     139              :       /* -Werror was given.  */
     140          190 :       if (m_context.warning_as_error_requested_p ())
     141           75 :         pp_verbatim (pp,
     142           75 :                      _("%s: all warnings being treated as errors"),
     143              :                      progname);
     144              :       /* At least one -Werror= was given.  */
     145              :       else
     146          115 :         pp_verbatim (pp,
     147          115 :                      _("%s: some warnings being treated as errors"),
     148              :                      progname);
     149          190 :       pp_newline_and_flush (pp);
     150              :     }
     151              : 
     152       307868 :   if (m_includes_seen)
     153              :     {
     154         1008 :       delete m_includes_seen;
     155         1008 :       m_includes_seen = nullptr;
     156              :     }
     157       612985 : }
     158              : 
     159              : void
     160            0 : text_sink::dump (FILE *outfile, int indent) const
     161              : {
     162            0 :   DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_follows_reference_printer);
     163            0 :   DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_nesting);
     164            0 :   DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_locations_in_nesting);
     165            0 :   DIAGNOSTICS_DUMPING_EMIT_BOOL_FIELD (m_show_nesting_levels);
     166              : 
     167            0 :   sink::dump (outfile, indent);
     168            0 :   dumping::emit_heading (outfile, indent, "saved_output_buffer");
     169            0 :   if (m_saved_output_buffer)
     170            0 :     m_saved_output_buffer->dump (outfile, indent + 2);
     171              :   else
     172            0 :     dumping::emit_none (outfile, indent + 2);
     173            0 : }
     174              : 
     175              : void
     176      2432388 : text_sink::set_buffer (per_sink_buffer *base)
     177              : {
     178      2432388 :   text_sink_buffer * const buffer
     179              :     = static_cast<text_sink_buffer *> (base);
     180              : 
     181      2432388 :   pretty_printer *const pp = get_printer ();
     182              : 
     183      2432388 :   if (!m_saved_output_buffer)
     184        31139 :     m_saved_output_buffer = pp_buffer (pp);
     185              : 
     186      2432388 :   if (buffer)
     187      1216194 :     pp_buffer (pp) = &buffer->m_output_buffer;
     188              :   else
     189              :     {
     190      1216194 :       gcc_assert (m_saved_output_buffer);
     191      1216194 :       pp_buffer (pp) = m_saved_output_buffer;
     192              :     }
     193      2432388 : }
     194              : 
     195              : std::unique_ptr<per_sink_buffer>
     196        98059 : text_sink::make_per_sink_buffer ()
     197              : {
     198        98059 :   return std::make_unique<text_sink_buffer> (*this);
     199              : }
     200              : 
     201              : /* Implementation of diagnostics::sink::on_report_diagnostic vfunc
     202              :    for GCC's standard textual output.  */
     203              : 
     204              : void
     205      1560514 : text_sink::on_report_diagnostic (const diagnostic_info &diagnostic,
     206              :                                  enum kind orig_diag_kind)
     207              : {
     208      1560514 :   auto logger = get_logger ();
     209      1560514 :   DIAGNOSTICS_LOG_SCOPE_PRINTF0
     210              :     (logger,
     211      1560514 :      "diagnostics::text_sink::on_report_diagnostic");
     212              : 
     213      1560514 :   pretty_printer *pp = get_printer ();
     214              : 
     215      1560514 :   (*text_starter (&m_context)) (*this, &diagnostic);
     216              : 
     217      1560514 :   pp_output_formatted_text (pp, m_context.get_urlifier ());
     218              : 
     219      1560514 :   if (m_context.m_show_cwe)
     220      1559147 :     print_any_cwe (diagnostic);
     221              : 
     222      1560514 :   if (m_context.m_show_rules)
     223      1559147 :     print_any_rules (diagnostic);
     224              : 
     225      1560514 :   if (m_context.m_show_option_requested)
     226      1559147 :     print_option_information (diagnostic, orig_diag_kind);
     227              : 
     228              :   /* If we're showing nested diagnostics, then print the location
     229              :      on a new line, indented.  */
     230      1560514 :   if (m_show_nesting && m_show_locations_in_nesting)
     231              :     {
     232        21741 :       const int nesting_level = get_context ().get_diagnostic_nesting_level ();
     233        21741 :       if (nesting_level > 0)
     234              :         {
     235           60 :           location_t loc = diagnostic_location (&diagnostic);
     236           60 :           pp_set_prefix (pp, nullptr);
     237           60 :           char *indent_prefix = build_indent_prefix (false);
     238              :           /* Only print changes of location.  */
     239           60 :           if (loc != get_context ().m_last_location
     240           60 :               && loc > BUILTINS_LOCATION)
     241              :             {
     242            8 :               const expanded_location s
     243            8 :                 = diagnostic_expand_location (&diagnostic);
     244            8 :               label_text location_text = get_location_text (s);
     245            8 :               pp_newline (pp);
     246            8 :               pp_printf (pp, "%s%s", indent_prefix, location_text.get ());
     247            8 :             }
     248           60 :           pp_set_prefix (pp, indent_prefix);
     249              :         }
     250              :     }
     251              : 
     252      1560514 :   (*text_finalizer (&m_context)) (*this,
     253              :                                   &diagnostic,
     254              :                                   orig_diag_kind);
     255              : 
     256      1560513 :   if (m_show_nesting && m_show_locations_in_nesting)
     257        21741 :     get_context ().m_last_location = diagnostic_location (&diagnostic);
     258      1560513 : }
     259              : 
     260              : void
     261            0 : text_sink::on_report_verbatim (text_info &text)
     262              : {
     263            0 :   pp_format_verbatim (get_printer (), &text);
     264            0 :   pp_newline_and_flush (get_printer ());
     265            0 : }
     266              : 
     267              : void
     268           80 : text_sink::on_diagram (const diagnostics::diagram &d)
     269              : {
     270           80 :   pretty_printer *const pp = get_printer ();
     271              : 
     272           80 :   char *saved_prefix = pp_take_prefix (pp);
     273           80 :   pp_set_prefix (pp, nullptr);
     274              :   /* Use a newline before and after and a two-space indent
     275              :      to make the diagram stand out a little from the wall of text.  */
     276           80 :   pp_newline (pp);
     277           80 :   d.get_canvas ().print_to_pp (pp, "  ");
     278           80 :   pp_newline (pp);
     279           80 :   pp_set_prefix (pp, saved_prefix);
     280           80 :   pp_flush (pp);
     281           80 : }
     282              : 
     283              : void
     284       344473 : text_sink::
     285              : after_diagnostic (const diagnostic_info &diagnostic)
     286              : {
     287       344473 :   if (const paths::path *path = diagnostic.m_richloc->get_path ())
     288         9671 :     print_path (*path);
     289       344473 : }
     290              : 
     291              : /* Return a malloc'd string describing a location and the severity of the
     292              :    diagnostic, e.g. "foo.c:42:10: error: ".
     293              : 
     294              :    If m_show_nesting, then the above will be preceded by indentation to show
     295              :    the level, and a bullet point.
     296              : 
     297              :    The caller is responsible for freeing the memory.  */
     298              : char *
     299       344033 : text_sink::build_prefix (const diagnostic_info &diagnostic) const
     300              : {
     301       344033 :   gcc_assert (diagnostic.m_kind < kind::last_diagnostic_kind);
     302              : 
     303       344033 :   const char *text = _(get_text_for_kind (diagnostic.m_kind));
     304       344033 :   const char *text_cs = "", *text_ce = "";
     305       344033 :   pretty_printer *pp = get_printer ();
     306              : 
     307       344033 :   if (const char *color_name = get_color_for_kind (diagnostic.m_kind))
     308              :     {
     309       344033 :       text_cs = colorize_start (pp_show_color (pp), color_name);
     310       344033 :       text_ce = colorize_stop (pp_show_color (pp));
     311              :     }
     312              : 
     313       344033 :   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
     314       344033 :   if (m_show_nesting && nesting_level > 0)
     315              :     {
     316          162 :       char *indent_prefix = build_indent_prefix (true);
     317              : 
     318              :       /* Reduce verbosity of nested diagnostics by not printing "note: "
     319              :          all the time.  */
     320          162 :       if (diagnostic.m_kind == kind::note)
     321              :         return indent_prefix;
     322              : 
     323            6 :       char *result = build_message_string ("%s%s%s%s", indent_prefix,
     324              :                                            text_cs, text, text_ce);
     325            6 :       free (indent_prefix);
     326            6 :       return result;
     327              :     }
     328              :   else
     329              :     {
     330       343871 :       const expanded_location s = diagnostic_expand_location (&diagnostic);
     331       343871 :       label_text location_text = get_location_text (s);
     332       343871 :       return build_message_string ("%s %s%s%s", location_text.get (),
     333              :                                    text_cs, text, text_ce);
     334       343871 :     }
     335              : }
     336              : 
     337              : /* Same as build_prefix, but only the source FILE is given.  */
     338              : char *
     339        40347 : text_sink::file_name_as_prefix (const char *f) const
     340              : {
     341        40347 :   pretty_printer *const pp = get_printer ();
     342        40347 :   const char *locus_cs
     343        40347 :     = colorize_start (pp_show_color (pp), "locus");
     344        40347 :   const char *locus_ce = colorize_stop (pp_show_color (pp));
     345        40347 :   return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
     346              : }
     347              : 
     348              : /* Get the unicode code point for bullet points when showing
     349              :    nested diagnostics.  */
     350              : 
     351              : static unsigned
     352          321 : get_bullet_point_unichar (bool unicode)
     353              : {
     354          321 :   if (unicode)
     355              :     return 0x2022; /* U+2022: Bullet */
     356              :   else
     357          285 :     return '*';
     358              : }
     359              : 
     360              : /* Return true if DC's theme supports unicode characters.  */
     361              : 
     362              : static bool
     363          321 : use_unicode_p (const context &dc)
     364              : {
     365          321 :   if (text_art::theme *theme = dc.get_diagram_theme ())
     366           36 :     return theme->unicode_p ();
     367              :   else
     368              :     return false;
     369              : }
     370              : 
     371              : /* Get the unicode code point for bullet points when showing
     372              :    nested diagnostics.  */
     373              : 
     374              : static unsigned
     375          321 : get_bullet_point_unichar (context &dc)
     376              : {
     377          321 :   return get_bullet_point_unichar (use_unicode_p (dc));
     378              : }
     379              : 
     380              : /* Return a malloc'd string for use as a prefix to show indentation.
     381              :    If m_show_nesting is false, or we're at the top-level, then the
     382              :    result will be the empty string.
     383              : 
     384              :    If m_show_nesting, then the result will contain indentation to show
     385              :    the nesting level, then either a bullet point (if WITH_BULLET is true),
     386              :    or a space.
     387              : 
     388              :    The caller is responsible for freeing the memory.  */
     389              : 
     390              : char *
     391       556744 : text_sink::build_indent_prefix (bool with_bullet) const
     392              : {
     393       556744 :   if (!m_show_nesting)
     394       551122 :     return xstrdup ("");
     395              : 
     396         5622 :   const int nesting_level = get_context ().get_diagnostic_nesting_level ();
     397         5622 :   if (nesting_level == 0)
     398         5079 :     return xstrdup ("");
     399              : 
     400          543 :   pretty_printer pp;
     401         2201 :   for (int i = 0; i < nesting_level; i++)
     402         1658 :     pp_string (&pp, "  ");
     403          543 :   if (with_bullet)
     404          642 :     pp_unicode_character (&pp, get_bullet_point_unichar (get_context ()));
     405              :   else
     406          222 :     pp_space (&pp);
     407          543 :   pp_space (&pp);
     408          543 :   if (m_show_nesting_levels)
     409           36 :     pp_printf (&pp, "(level %i):", nesting_level);
     410          543 :   return xstrdup (pp_formatted_text (&pp));
     411          543 : }
     412              : 
     413              : /* Add a purely textual note with text GMSGID and with LOCATION.  */
     414              : 
     415              : void
     416        12644 : text_sink::append_note (location_t location,
     417              :                         const char * gmsgid, ...)
     418              : {
     419        12644 :   context *dc = &get_context ();
     420              : 
     421        12644 :   diagnostic_info diagnostic;
     422        12644 :   va_list ap;
     423        12644 :   rich_location richloc (line_table, location);
     424              : 
     425        12644 :   va_start (ap, gmsgid);
     426        12644 :   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, kind::note);
     427        12644 :   if (dc->m_inhibit_notes_p)
     428              :     {
     429            0 :       va_end (ap);
     430            0 :       return;
     431              :     }
     432        12644 :   pretty_printer *pp = get_printer ();
     433        12644 :   char *saved_prefix = pp_take_prefix (pp);
     434        12644 :   pp_set_prefix (pp, build_prefix (diagnostic));
     435        12644 :   pp_format (pp, &diagnostic.m_message);
     436        12644 :   pp_output_formatted_text (pp);
     437        12644 :   pp_destroy_prefix (pp);
     438        12644 :   pp_set_prefix (pp, saved_prefix);
     439        12644 :   pp_newline (pp);
     440        12644 :   diagnostic_show_locus (dc, get_source_printing_options (),
     441              :                          &richloc, kind::note, pp);
     442        12644 :   va_end (ap);
     443        12644 : }
     444              : 
     445              : bool
     446      4487240 : text_sink::follows_reference_printer_p () const
     447              : {
     448      4487240 :   return m_follows_reference_printer;
     449              : }
     450              : 
     451              : void
     452       494180 : text_sink::update_printer ()
     453              : {
     454       494180 :   pretty_printer *copy_from_pp
     455       494180 :     = (m_follows_reference_printer
     456       494180 :        ? get_context ().get_reference_printer ()
     457            0 :        : m_printer.get ());
     458       494180 :   const bool show_color = pp_show_color (copy_from_pp);
     459       494180 :   const diagnostic_url_format url_format = copy_from_pp->get_url_format ();
     460              : 
     461       494180 :   m_printer = get_context ().clone_printer ();
     462              : 
     463       494180 :   pp_show_color (m_printer.get ()) = show_color;
     464       494180 :   m_printer->set_url_format (url_format);
     465              :   // ...etc
     466              : 
     467       494180 :   m_source_printing = get_context ().m_source_printing;
     468       494180 : }
     469              : 
     470              : /* If DIAGNOSTIC has a CWE identifier, print it.
     471              : 
     472              :    For example, if the diagnostic metadata associates it with CWE-119,
     473              :    " [CWE-119]" will be printed, suitably colorized, and with a URL of a
     474              :    description of the security issue.  */
     475              : 
     476              : void
     477      1559147 : text_sink::print_any_cwe (const diagnostic_info &diagnostic)
     478              : {
     479      1559147 :   if (!diagnostic.m_metadata)
     480              :     return;
     481              : 
     482         4362 :   int cwe = diagnostic.m_metadata->get_cwe ();
     483         4362 :   if (cwe)
     484              :     {
     485         3266 :       pretty_printer * const pp = get_printer ();
     486         3266 :       char *saved_prefix = pp_take_prefix (pp);
     487         3266 :       pp_string (pp, " [");
     488         3266 :       const char *kind_color = get_color_for_kind (diagnostic.m_kind);
     489         3266 :       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
     490         3266 :       if (pp->supports_urls_p ())
     491              :         {
     492            0 :           char *cwe_url = get_cwe_url (cwe);
     493            0 :           pp_begin_url (pp, cwe_url);
     494            0 :           free (cwe_url);
     495              :         }
     496         3266 :       pp_printf (pp, "CWE-%i", cwe);
     497         3266 :       pp_set_prefix (pp, saved_prefix);
     498         3266 :       if (pp->supports_urls_p ())
     499            0 :         pp_end_url (pp);
     500         3266 :       pp_string (pp, colorize_stop (pp_show_color (pp)));
     501         3266 :       pp_character (pp, ']');
     502              :     }
     503              : }
     504              : 
     505              : /* If DIAGNOSTIC has any rules associated with it, print them.
     506              : 
     507              :    For example, if the diagnostic metadata associates it with a rule
     508              :    named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
     509              :    with any URL provided by the rule.  */
     510              : 
     511              : void
     512      1559147 : text_sink::print_any_rules (const diagnostic_info &diagnostic)
     513              : {
     514      1559147 :   if (!diagnostic.m_metadata)
     515              :     return;
     516              : 
     517         4813 :   for (unsigned idx = 0; idx < diagnostic.m_metadata->get_num_rules (); idx++)
     518              :     {
     519          451 :       const diagnostics::metadata::rule &rule
     520          451 :         = diagnostic.m_metadata->get_rule (idx);
     521          451 :       if (char *desc = rule.make_description ())
     522              :         {
     523          451 :           pretty_printer * const pp = get_printer ();
     524          451 :           char *saved_prefix = pp_take_prefix (pp);
     525          451 :           pp_string (pp, " [");
     526          451 :           const char *kind_color = get_color_for_kind (diagnostic.m_kind);
     527          451 :           pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
     528          451 :           char *url = nullptr;
     529          451 :           if (pp->supports_urls_p ())
     530              :             {
     531            0 :               url = rule.make_url ();
     532            0 :               if (url)
     533            0 :                 pp_begin_url (pp, url);
     534              :             }
     535          451 :           pp_string (pp, desc);
     536          451 :           pp_set_prefix (pp, saved_prefix);
     537          451 :           if (pp->supports_urls_p ())
     538            0 :             if (url)
     539            0 :               pp_end_url (pp);
     540          451 :           free (url);
     541          451 :           pp_string (pp, colorize_stop (pp_show_color (pp)));
     542          451 :           pp_character (pp, ']');
     543          451 :           free (desc);
     544              :         }
     545              :     }
     546              : }
     547              : 
     548              : /* Print any metadata about the option used to control DIAGNOSTIC to
     549              :    the context's printer, e.g. " [-Werror=uninitialized]".  */
     550              : 
     551              : void
     552      1559147 : text_sink::print_option_information (const diagnostic_info &diagnostic,
     553              :                                      enum kind orig_diag_kind)
     554              : {
     555      3118294 :   if (char *option_text
     556      1559147 :       = m_context.make_option_name (diagnostic.m_option_id,
     557      1559147 :                                     orig_diag_kind, diagnostic.m_kind))
     558              :     {
     559        93486 :       char *option_url = nullptr;
     560        93486 :       pretty_printer * const pp = get_printer ();
     561        93486 :       if (pp->supports_urls_p ())
     562            0 :         option_url = m_context.make_option_url (diagnostic.m_option_id);
     563        93486 :       pp_string (pp, " [");
     564        93486 :       const char *kind_color = get_color_for_kind (diagnostic.m_kind);
     565        93486 :       pp_string (pp, colorize_start (pp_show_color (pp), kind_color));
     566        93486 :       if (option_url)
     567            0 :         pp_begin_url (pp, option_url);
     568        93486 :       pp_string (pp, option_text);
     569        93486 :       if (option_url)
     570              :         {
     571            0 :           pp_end_url (pp);
     572            0 :           free (option_url);
     573              :         }
     574        93486 :       pp_string (pp, colorize_stop (pp_show_color (pp)));
     575        93486 :       pp_character (pp, ']');
     576        93486 :       free (option_text);
     577              :     }
     578      1559147 : }
     579              : 
     580              : /* Only dump the "In file included from..." stack once for each file.  */
     581              : 
     582              : bool
     583        62011 : text_sink::includes_seen_p (const line_map_ordinary *map)
     584              : {
     585              :   /* No include path for main.  */
     586        62011 :   if (MAIN_FILE_P (map))
     587              :     return true;
     588              : 
     589              :   /* Always identify C++ modules, at least for now.  */
     590         8358 :   auto probe = map;
     591         8358 :   if (linemap_check_ordinary (map)->reason == LC_RENAME)
     592              :     /* The module source file shows up as LC_RENAME inside LC_MODULE.  */
     593          621 :     probe = linemap_included_from_linemap (line_table, map);
     594         8358 :   if (MAP_MODULE_P (probe))
     595              :     return false;
     596              : 
     597         7174 :   if (!m_includes_seen)
     598         1008 :     m_includes_seen = new hash_set<location_t, false, location_hash>;
     599              : 
     600              :   /* Hash the location of the #include directive to better handle files
     601              :      that are included multiple times with different macros defined.  */
     602         7174 :   return m_includes_seen->add (linemap_included_from (map));
     603              : }
     604              : 
     605              : label_text
     606       343879 : text_sink::get_location_text (const expanded_location &s) const
     607              : {
     608       343879 :   column_policy column_policy_ (get_context ());
     609       343879 :   return column_policy_.get_location_text (s,
     610       343879 :                                            show_column_p (),
     611       343879 :                                            pp_show_color (get_printer ()));
     612              : }
     613              : 
     614              : /* Helpers for writing lang-specific starters/finalizers for text output.  */
     615              : 
     616              : /* Return a formatted line and column ':%line:%column'.  Elided if
     617              :    line == 0 or col < 0.  (A column of 0 may be valid due to the
     618              :    -fdiagnostics-column-origin option.)
     619              :    The result is a statically allocated buffer.  */
     620              : 
     621              : const char *
     622       350211 : text_sink::maybe_line_and_column (int line, int col)
     623              : {
     624       350211 :   static char result[32];
     625              : 
     626       350211 :   if (line)
     627              :     {
     628       345357 :       size_t l
     629       345357 :         = snprintf (result, sizeof (result),
     630       345357 :                     col >= 0 ? ":%d:%d" : ":%d", line, col);
     631       345357 :       gcc_checking_assert (l < sizeof (result));
     632              :     }
     633              :   else
     634         4854 :     result[0] = 0;
     635       350211 :   return result;
     636              : }
     637              : 
     638              : void
     639       331389 : text_sink::report_current_module (location_t where)
     640              : {
     641       331389 :   pretty_printer *pp = get_printer ();
     642       331389 :   const line_map_ordinary *map = nullptr;
     643              : 
     644       331389 :   if (pp_needs_newline (pp))
     645              :     {
     646            0 :       pp_newline (pp);
     647            0 :       pp_needs_newline (pp) = false;
     648              :     }
     649              : 
     650       331389 :   if (where <= BUILTINS_LOCATION)
     651         3507 :     return;
     652              : 
     653       327882 :   linemap_resolve_location (line_table, where,
     654              :                             LRK_MACRO_DEFINITION_LOCATION,
     655              :                             &map);
     656              : 
     657       327882 :   if (map && m_last_module != map)
     658              :     {
     659        57520 :       m_last_module = map;
     660        57520 :       if (!includes_seen_p (map))
     661              :         {
     662         2011 :           bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
     663         2011 :           expanded_location s = {};
     664         4491 :           do
     665              :             {
     666         4491 :               where = linemap_included_from (map);
     667         4491 :               map = linemap_included_from_linemap (line_table, map);
     668         4491 :               bool is_module = MAP_MODULE_P (map);
     669         4491 :               s.file = LINEMAP_FILE (map);
     670         4491 :               s.line = SOURCE_LINE (map, where);
     671         4491 :               int col = -1;
     672         4491 :               if (first && show_column_p ())
     673              :                 {
     674         1075 :                   s.column = SOURCE_COLUMN (map, where);
     675         1075 :                   col = get_column_policy ().converted_column (s);
     676              :                 }
     677         4491 :               const char *line_col = maybe_line_and_column (s.line, col);
     678         4491 :               static const char *const msgs[] =
     679              :                 {
     680              :                  nullptr,
     681              :                  N_("                 from"),
     682              :                  N_("In file included from"), /* 2 */
     683              :                  N_("        included from"),
     684              :                  N_("In module"),             /* 4 */
     685              :                  N_("of module"),
     686              :                  N_("In module imported at"), /* 6 */
     687              :                  N_("imported at"),
     688              :                 };
     689              : 
     690         4491 :               unsigned index = (was_module ? 6 : is_module ? 4
     691         3307 :                                 : need_inc ? 2 : 0) + !first;
     692              : 
     693         6411 :               pp_verbatim (pp, "%s%s %r%s%s%R",
     694              :                            first ? "" : was_module ? ", " : ",\n",
     695         4491 :                            _(msgs[index]),
     696              :                            "locus", s.file, line_col);
     697         4491 :               first = false, need_inc = was_module, was_module = is_module;
     698              :             }
     699         4491 :           while (!includes_seen_p (map));
     700         2011 :           pp_verbatim (pp, ":");
     701         2011 :           pp_newline (pp);
     702              :         }
     703              :     }
     704              : }
     705              : 
     706              : void
     707         1367 : default_text_starter (text_sink &text_output,
     708              :                       const diagnostic_info *diagnostic)
     709              : {
     710         1367 :   text_output.report_current_module (diagnostic_location (diagnostic));
     711         1367 :   pretty_printer *const pp = text_output.get_printer ();
     712         1367 :   pp_set_prefix (pp, text_output.build_prefix (*diagnostic));
     713         1367 : }
     714              : 
     715              : void
     716        17052 : default_text_finalizer (text_sink &text_output,
     717              :                         const diagnostic_info *diagnostic,
     718              :                         enum kind)
     719              : {
     720        17052 :   pretty_printer *const pp = text_output.get_printer ();
     721        17052 :   char *saved_prefix = pp_take_prefix (pp);
     722        17052 :   pp_set_prefix (pp, nullptr);
     723        17052 :   pp_newline (pp);
     724        17052 :   diagnostic_show_locus (&text_output.get_context (),
     725        17052 :                          text_output.get_source_printing_options (),
     726        17052 :                          diagnostic->m_richloc, diagnostic->m_kind, pp);
     727        17052 :   pp_set_prefix (pp, saved_prefix);
     728        17052 :   pp_flush (pp);
     729        17052 : }
     730              : 
     731              : #if __GNUC__ >= 10
     732              : #  pragma GCC diagnostic pop
     733              : #endif
     734              : 
     735              : } // namespace diagnostics
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.