LCOV - code coverage report
Current view: top level - gcc/fortran - error.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.6 % 467 437
Test Date: 2026-02-28 14:20:25 Functions: 95.7 % 47 45
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Handle errors.
       2              :    Copyright (C) 2000-2026 Free Software Foundation, Inc.
       3              :    Contributed by Andy Vaught & Niels Kristian Bech Jensen
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : /* Handle the inevitable errors.  A major catch here is that things
      22              :    flagged as errors in one match subroutine can conceivably be legal
      23              :    elsewhere.  This means that error messages are recorded and saved
      24              :    for possible use later.  If a line does not match a legal
      25              :    construction, then the saved error message is reported.  */
      26              : 
      27              : #define INCLUDE_VECTOR
      28              : #include "config.h"
      29              : #include "system.h"
      30              : #include "coretypes.h"
      31              : #include "options.h"
      32              : #include "gfortran.h"
      33              : 
      34              : #include "diagnostic.h"
      35              : #include "diagnostics/color.h"
      36              : #include "tree-diagnostic.h" /* tree_diagnostics_defaults */
      37              : #include "diagnostics/text-sink.h"
      38              : 
      39              : static int suppress_errors = 0;
      40              : 
      41              : static bool warnings_not_errors = false;
      42              : 
      43              : /* True if the error/warnings should be buffered.  */
      44              : static bool buffered_p;
      45              : 
      46              : static gfc_error_buffer *error_buffer;
      47              : static diagnostics::buffer *pp_error_buffer, *pp_warning_buffer;
      48              : 
      49      8506406 : gfc_error_buffer::gfc_error_buffer ()
      50      8506406 : : flag (false), buffer (*global_dc)
      51              : {
      52      8506406 : }
      53              : 
      54              : /* Return a location_t suitable for 'tree' for a gfortran locus.  During
      55              :    parsing in gfortran, loc->u.lb->location contains only the line number
      56              :    and LOCATION_COLUMN is 0; hence, the column has to be added when generating
      57              :    locations for 'tree'.  If available, return location_t directly, which
      58              :    might be a range. */
      59              : 
      60              : location_t
      61     20322665 : gfc_get_location_with_offset (locus *loc, unsigned offset)
      62              : {
      63     20322665 :   if (loc->nextc == (gfc_char_t *) -1)
      64              :     {
      65       408326 :       gcc_checking_assert (offset == 0);
      66       408326 :       return loc->u.location;
      67              :     }
      68     19914339 :   gcc_checking_assert (loc->nextc >= loc->u.lb->line);
      69     19914339 :   return linemap_position_for_loc_and_offset (line_table, loc->u.lb->location,
      70     19914339 :                                               loc->nextc - loc->u.lb->line
      71     19914339 :                                               + offset);
      72              : }
      73              : 
      74              : /* Convert a locus to a range. */
      75              : 
      76              : locus
      77      7660997 : gfc_get_location_range (locus *caret_loc, unsigned caret_offset,
      78              :                         locus *start_loc, unsigned start_offset,
      79              :                         locus *end_loc)
      80              : {
      81      7660997 :   location_t caret;
      82      7660997 :   location_t start = gfc_get_location_with_offset (start_loc, start_offset);
      83      7660997 :   location_t end = gfc_get_location_with_offset (end_loc, 0);
      84              : 
      85      7660997 :   if (caret_loc)
      86           12 :     caret = gfc_get_location_with_offset (caret_loc, caret_offset);
      87              : 
      88           12 :   locus range;
      89           12 :   range.nextc = (gfc_char_t *) -1;
      90      7660997 :   range.u.location = make_location (caret_loc ? caret : start, start, end);
      91      7660997 :   return range;
      92              : }
      93              : 
      94              : /* Return buffered_p.  */
      95              : bool
      96           78 : gfc_buffered_p (void)
      97              : {
      98           78 :   return buffered_p;
      99              : }
     100              : 
     101              : /* Go one level deeper suppressing errors.  */
     102              : 
     103              : void
     104       469731 : gfc_push_suppress_errors (void)
     105              : {
     106       469731 :   gcc_assert (suppress_errors >= 0);
     107       469731 :   ++suppress_errors;
     108       469731 : }
     109              : 
     110              : static void
     111              : gfc_error_opt (int opt, const char *gmsgid, va_list ap)  ATTRIBUTE_GCC_GFC(2,0);
     112              : 
     113              : static bool
     114              : gfc_warning (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
     115              : 
     116              : 
     117              : /* Leave one level of error suppressing.  */
     118              : 
     119              : void
     120       469731 : gfc_pop_suppress_errors (void)
     121              : {
     122       469731 :   gcc_assert (suppress_errors > 0);
     123       469731 :   --suppress_errors;
     124       469731 : }
     125              : 
     126              : 
     127              : /* Query whether errors are suppressed.  */
     128              : 
     129              : bool
     130          146 : gfc_query_suppress_errors (void)
     131              : {
     132          146 :   return suppress_errors > 0;
     133              : }
     134              : 
     135              : 
     136              : /* Per-file error initialization.  */
     137              : 
     138              : void
     139        31306 : gfc_error_init_1 (void)
     140              : {
     141        31306 :   gfc_buffer_error (false);
     142        31306 : }
     143              : 
     144              : 
     145              : /* Set the flag for buffering errors or not.  */
     146              : 
     147              : void
     148      6335438 : gfc_buffer_error (bool flag)
     149              : {
     150      6335438 :   buffered_p = flag;
     151      6335438 : }
     152              : 
     153              : 
     154              : static int
     155           25 : print_wide_char_into_buffer (gfc_char_t c, char *buf)
     156              : {
     157           25 :   static const char xdigit[16] = { '0', '1', '2', '3', '4', '5', '6',
     158              :     '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
     159              : 
     160           25 :   if (gfc_wide_is_printable (c) || c == '\t')
     161              :     {
     162            2 :       buf[1] = '\0';
     163              :       /* Tabulation is output as a space.  */
     164            2 :       buf[0] = (unsigned char) (c == '\t' ? ' ' : c);
     165            2 :       return 1;
     166              :     }
     167           23 :   else if (c < ((gfc_char_t) 1 << 8))
     168              :     {
     169           14 :       buf[4] = '\0';
     170           14 :       buf[3] = xdigit[c & 0x0F];
     171           14 :       c = c >> 4;
     172           14 :       buf[2] = xdigit[c & 0x0F];
     173              : 
     174           14 :       buf[1] = 'x';
     175           14 :       buf[0] = '\\';
     176           14 :       return 4;
     177              :     }
     178            9 :   else if (c < ((gfc_char_t) 1 << 16))
     179              :     {
     180            8 :       buf[6] = '\0';
     181            8 :       buf[5] = xdigit[c & 0x0F];
     182            8 :       c = c >> 4;
     183            8 :       buf[4] = xdigit[c & 0x0F];
     184            8 :       c = c >> 4;
     185            8 :       buf[3] = xdigit[c & 0x0F];
     186            8 :       c = c >> 4;
     187            8 :       buf[2] = xdigit[c & 0x0F];
     188              : 
     189            8 :       buf[1] = 'u';
     190            8 :       buf[0] = '\\';
     191            8 :       return 6;
     192              :     }
     193              :   else
     194              :     {
     195            1 :       buf[10] = '\0';
     196            1 :       buf[9] = xdigit[c & 0x0F];
     197            1 :       c = c >> 4;
     198            1 :       buf[8] = xdigit[c & 0x0F];
     199            1 :       c = c >> 4;
     200            1 :       buf[7] = xdigit[c & 0x0F];
     201            1 :       c = c >> 4;
     202            1 :       buf[6] = xdigit[c & 0x0F];
     203            1 :       c = c >> 4;
     204            1 :       buf[5] = xdigit[c & 0x0F];
     205            1 :       c = c >> 4;
     206            1 :       buf[4] = xdigit[c & 0x0F];
     207            1 :       c = c >> 4;
     208            1 :       buf[3] = xdigit[c & 0x0F];
     209            1 :       c = c >> 4;
     210            1 :       buf[2] = xdigit[c & 0x0F];
     211              : 
     212            1 :       buf[1] = 'U';
     213            1 :       buf[0] = '\\';
     214            1 :       return 10;
     215              :     }
     216              : }
     217              : 
     218              : static char wide_char_print_buffer[11];
     219              : 
     220              : const char *
     221           25 : gfc_print_wide_char (gfc_char_t c)
     222              : {
     223           25 :   print_wide_char_into_buffer (c, wide_char_print_buffer);
     224           25 :   return wide_char_print_buffer;
     225              : }
     226              : 
     227              : 
     228              : /* Clear any output buffered in THIS_BUFFER without issuing
     229              :    it to global_dc.  */
     230              : 
     231              : static void
     232     23260742 : gfc_clear_diagnostic_buffer (diagnostics::buffer *this_buffer)
     233              : {
     234     23260742 :   gcc_assert (this_buffer);
     235     23260742 :   global_dc->clear_diagnostic_buffer (*this_buffer);
     236     23260742 : }
     237              : 
     238              : /* The currently-printing diagnostic, for use by gfc_format_decoder,
     239              :    for colorizing %C and %L.  */
     240              : 
     241              : static diagnostics::diagnostic_info *curr_diagnostic;
     242              : 
     243              : /* A helper function to call diagnostic_report_diagnostic, while setting
     244              :    curr_diagnostic for the duration of the call.  */
     245              : 
     246              : static bool
     247      1256299 : gfc_report_diagnostic (diagnostics::diagnostic_info *diagnostic)
     248              : {
     249      1256299 :   gcc_assert (diagnostic != NULL);
     250      1256299 :   curr_diagnostic = diagnostic;
     251      1256299 :   bool ret = diagnostic_report_diagnostic (global_dc, diagnostic);
     252      1256289 :   curr_diagnostic = NULL;
     253      1256289 :   return ret;
     254              : }
     255              : 
     256              : /* This is just a helper function to avoid duplicating the logic of
     257              :    gfc_warning.  */
     258              : 
     259              : static bool
     260        21857 : gfc_warning (int opt, const char *gmsgid, va_list ap)
     261              : {
     262        21857 :   va_list argp;
     263        21857 :   va_copy (argp, ap);
     264              : 
     265        21857 :   diagnostics::diagnostic_info diagnostic;
     266        21857 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     267        21857 :   diagnostics::buffer *old_buffer = global_dc->get_diagnostic_buffer ();
     268        21857 :   gcc_assert (!old_buffer);
     269              : 
     270        21857 :   gfc_clear_diagnostic_buffer (pp_warning_buffer);
     271              : 
     272        21857 :   if (buffered_p)
     273        16963 :     global_dc->set_diagnostic_buffer (pp_warning_buffer);
     274              : 
     275        21857 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     276              :                        diagnostics::kind::warning);
     277        21857 :   diagnostic.m_option_id = opt;
     278        21857 :   bool ret = gfc_report_diagnostic (&diagnostic);
     279              : 
     280        21857 :   if (buffered_p)
     281        16963 :     global_dc->set_diagnostic_buffer (old_buffer);
     282              : 
     283        21857 :   va_end (argp);
     284        43714 :   return ret;
     285        21857 : }
     286              : 
     287              : /* Issue a warning.  */
     288              : 
     289              : bool
     290         5925 : gfc_warning (int opt, const char *gmsgid, ...)
     291              : {
     292         5925 :   va_list argp;
     293              : 
     294         5925 :   va_start (argp, gmsgid);
     295         5925 :   bool ret = gfc_warning (opt, gmsgid, argp);
     296         5925 :   va_end (argp);
     297         5925 :   return ret;
     298              : }
     299              : 
     300              : 
     301              : /* Whether, for a feature included in a given standard set (GFC_STD_*),
     302              :    we should issue an error or a warning, or be quiet.  */
     303              : 
     304              : notification
     305       255738 : gfc_notification_std (int std)
     306              : {
     307       255738 :   bool warning;
     308              : 
     309       255738 :   warning = ((gfc_option.warn_std & std) != 0) && !inhibit_warnings;
     310       255738 :   if ((gfc_option.allow_std & std) != 0 && !warning)
     311              :     return SILENT;
     312              : 
     313          442 :   return warning ? WARNING : ERROR;
     314              : }
     315              : 
     316              : 
     317              : /* Return a string describing the nature of a standard violation
     318              :  * and/or the relevant version of the standard.  */
     319              : 
     320              : char const*
     321        16632 : notify_std_msg(int std)
     322              : {
     323              : 
     324        16632 :   if (std & GFC_STD_F2023_DEL)
     325           10 :     return _("Prohibited in Fortran 2023:");
     326        16622 :   else if (std & GFC_STD_F2023)
     327            9 :     return _("Fortran 2023:");
     328        16613 :   else if (std & GFC_STD_F2018_DEL)
     329            1 :     return _("Fortran 2018 deleted feature:");
     330        16612 :   else if (std & GFC_STD_F2018_OBS)
     331            8 :     return _("Fortran 2018 obsolescent feature:");
     332        16604 :   else if (std & GFC_STD_F2018)
     333          120 :     return _("Fortran 2018:");
     334        16484 :   else if (std & GFC_STD_F2008_OBS)
     335            2 :     return _("Fortran 2008 obsolescent feature:");
     336        16482 :   else if (std & GFC_STD_F2008)
     337              :     return "Fortran 2008:";
     338        16092 :   else if (std & GFC_STD_F2003)
     339              :     return "Fortran 2003:";
     340        15967 :   else if (std & GFC_STD_GNU)
     341          378 :     return _("GNU Extension:");
     342        15589 :   else if (std & GFC_STD_LEGACY)
     343        11560 :     return _("Legacy Extension:");
     344         4029 :   else if (std & GFC_STD_F95_OBS)
     345         3898 :     return _("Obsolescent feature:");
     346          131 :   else if (std & GFC_STD_F95_DEL)
     347          130 :     return _("Deleted feature:");
     348            1 :   else if (std & GFC_STD_UNSIGNED)
     349            1 :     return _("Unsigned:");
     350              :   else
     351            0 :     gcc_unreachable ();
     352              : }
     353              : 
     354              : 
     355              : /* Possibly issue a warning/error about use of a nonstandard (or deleted)
     356              :    feature.  An error/warning will be issued if the currently selected
     357              :    standard does not contain the requested bits.  Return false if
     358              :    an error is generated.  */
     359              : 
     360              : bool
     361       348399 : gfc_notify_std (int std, const char *gmsgid, ...)
     362              : {
     363       348399 :   va_list argp;
     364       348399 :   const char *msg, *msg2;
     365       348399 :   char *buffer;
     366              : 
     367              :   /* Determine whether an error or a warning is needed.  */
     368       348399 :   const int wstd = std & gfc_option.warn_std;    /* Standard to warn about.  */
     369       348399 :   const int estd = std & ~gfc_option.allow_std;  /* Standard to error about.  */
     370       348399 :   const bool warning = (wstd != 0) && !inhibit_warnings;
     371       348399 :   const bool error = (estd != 0);
     372              : 
     373       348399 :   if (!error && !warning)
     374              :     return true;
     375        16633 :   if (suppress_errors)
     376              :     return !error;
     377              : 
     378        16632 :   if (error)
     379          743 :     msg = notify_std_msg (estd);
     380              :   else
     381        15889 :     msg = notify_std_msg (wstd);
     382              : 
     383        16632 :   msg2 = _(gmsgid);
     384        16632 :   buffer = (char *) alloca (strlen (msg) + strlen (msg2) + 2);
     385        16632 :   strcpy (buffer, msg);
     386        16632 :   strcat (buffer, " ");
     387        16632 :   strcat (buffer, msg2);
     388              : 
     389        16632 :   va_start (argp, gmsgid);
     390        16632 :   if (error)
     391          743 :     gfc_error_opt (0, buffer, argp);
     392              :   else
     393        15889 :     gfc_warning (0, buffer, argp);
     394        16632 :   va_end (argp);
     395              : 
     396        16632 :   if (error)
     397              :     return false;
     398              :   else
     399        15892 :     return (warning && !warnings_are_errors);
     400              : }
     401              : 
     402              : 
     403              : /* Called from output_format -- during diagnostic message processing
     404              :    to handle Fortran specific format specifiers with the following meanings:
     405              : 
     406              :    %C  Current locus (no argument)
     407              :    %L  Takes locus argument
     408              : */
     409              : static bool
     410      1226598 : gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
     411              :                     int precision, bool wide, bool set_locus, bool hash,
     412              :                     bool *quoted, pp_token_list &formatted_token_list)
     413              : {
     414      1226598 :   unsigned offset = 0;
     415      1226598 :   switch (*spec)
     416              :     {
     417      1226575 :     case 'C':
     418      1226575 :     case 'L':
     419      1226575 :       {
     420      1226575 :         static const char *result[2] = { "(1)", "(2)" };
     421      1226575 :         locus *loc;
     422      1226575 :         if (*spec == 'C')
     423              :           {
     424      1208741 :             loc = &gfc_current_locus;
     425              :             /* Point %C first offending character not the last good one. */
     426      1208741 :             if (*loc->nextc != '\0')
     427      1144540 :               offset++;
     428              :           }
     429              :         else
     430        17834 :           loc = va_arg (*text->m_args_ptr, locus *);
     431              : 
     432              :         /* If location[0] != UNKNOWN_LOCATION means that we already
     433              :            processed one of %C/%L.  */
     434      1226575 :         int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1;
     435      1226575 :         location_t src_loc = gfc_get_location_with_offset (loc, offset);
     436      1226575 :         text->set_location (loc_num, src_loc, SHOW_RANGE_WITH_CARET);
     437              :         /* Colorize the markers to match the color choices of
     438              :            diagnostic_show_locus (the initial location has a color given
     439              :            by the "kind" of the diagnostic, the secondary location has
     440              :            color "range1").  */
     441      1226575 :         gcc_assert (curr_diagnostic != NULL);
     442      1226575 :         const char *color
     443              :           = (loc_num
     444      1226575 :              ? "range1"
     445      1226020 :              : diagnostics::get_color_for_kind (curr_diagnostic->m_kind));
     446      1226575 :         pp_string (pp, colorize_start (pp_show_color (pp), color));
     447      1226575 :         pp_string (pp, result[loc_num]);
     448      1226575 :         pp_string (pp, colorize_stop (pp_show_color (pp)));
     449      1226575 :         return true;
     450              :       }
     451           23 :     default:
     452              :       /* Fall through info the middle-end decoder, as e.g. stor-layout.cc
     453              :          etc. diagnostics can use the FE printer while the FE is still
     454              :          active.  */
     455           23 :       return default_tree_printer (pp, text, spec, precision, wide,
     456              :                                    set_locus, hash, quoted,
     457           23 :                                    formatted_token_list);
     458              :     }
     459              : }
     460              : 
     461              : /* Return a malloc'd string describing the kind of diagnostic.  The
     462              :    caller is responsible for freeing the memory.  */
     463              : static char *
     464      1229087 : gfc_diagnostic_build_kind_prefix (diagnostics::context *context,
     465              :                                   const diagnostics::diagnostic_info *diagnostic)
     466              : {
     467      1229087 :   static const char *const diagnostic_kind_text[] = {
     468              : #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
     469              : #include "gfc-diagnostic.def"
     470              : #undef DEFINE_DIAGNOSTIC_KIND
     471              :     "must-not-happen"
     472              :   };
     473      1229087 :   static const char *const diagnostic_kind_color[] = {
     474              : #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
     475              : #include "gfc-diagnostic.def"
     476              : #undef DEFINE_DIAGNOSTIC_KIND
     477              :     NULL
     478              :   };
     479      1229087 :   const int diag_kind_idx = static_cast<int> (diagnostic->m_kind);
     480      1229087 :   gcc_assert (diagnostic->m_kind < diagnostics::kind::last_diagnostic_kind);
     481      1229087 :   const char *text = _(diagnostic_kind_text[diag_kind_idx]);
     482      1229087 :   const char *text_cs = "", *text_ce = "";
     483      1229087 :   pretty_printer *const pp = context->get_reference_printer ();
     484              : 
     485      1229087 : if (diagnostic_kind_color[diag_kind_idx])
     486              :     {
     487      2458174 :       text_cs = colorize_start (pp_show_color (pp),
     488      1229087 :                                 diagnostic_kind_color[diag_kind_idx]);
     489      1229087 :       text_ce = colorize_stop (pp_show_color (pp));
     490              :     }
     491      1229087 :   return build_message_string ("%s%s:%s ", text_cs, text, text_ce);
     492              : }
     493              : 
     494              : /* Return a malloc'd string describing a location.  The caller is
     495              :    responsible for freeing the memory.  */
     496              : static char *
     497      1229215 : gfc_diagnostic_build_locus_prefix (const diagnostics::location_print_policy &loc_policy,
     498              :                                    expanded_location s,
     499              :                                    bool colorize)
     500              : {
     501      1229215 :   const char *locus_cs = colorize_start (colorize, "locus");
     502      1229215 :   const char *locus_ce = colorize_stop (colorize);
     503      1229215 :   return (s.file == NULL
     504      1229215 :           ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
     505      1229144 :           : !strcmp (s.file, special_fname_builtin ())
     506      1229144 :           ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
     507      1229134 :           : loc_policy.show_column_p ()
     508      1229134 :           ? build_message_string ("%s%s:%d:%d:%s", locus_cs, s.file, s.line,
     509              :                                   s.column, locus_ce)
     510            0 :           : build_message_string ("%s%s:%d:%s", locus_cs, s.file, s.line, locus_ce));
     511              : }
     512              : 
     513              : /* Return a malloc'd string describing two locations.  The caller is
     514              :    responsible for freeing the memory.  */
     515              : static char *
     516          213 : gfc_diagnostic_build_locus_prefix (const diagnostics::location_print_policy &loc_policy,
     517              :                                    expanded_location s, expanded_location s2,
     518              :                                    bool colorize)
     519              : {
     520          213 :   const char *locus_cs = colorize_start (colorize, "locus");
     521          213 :   const char *locus_ce = colorize_stop (colorize);
     522              : 
     523          213 :   return (s.file == NULL
     524          213 :           ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
     525          213 :           : !strcmp (s.file, special_fname_builtin ())
     526          213 :           ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
     527          213 :           : loc_policy.show_column_p ()
     528          213 :           ? build_message_string ("%s%s:%d:%d-%d:%s", locus_cs, s.file, s.line,
     529              :                                   MIN (s.column, s2.column),
     530              :                                   MAX (s.column, s2.column), locus_ce)
     531            0 :           : build_message_string ("%s%s:%d:%s", locus_cs, s.file, s.line,
     532          213 :                                   locus_ce));
     533              : }
     534              : 
     535              : /* This function prints the locus (file:line:column), the diagnostic kind
     536              :    (Error, Warning) and (optionally) the relevant lines of code with
     537              :    annotation lines with '1' and/or '2' below them.
     538              : 
     539              :    With -fdiagnostic-show-caret (the default) it prints:
     540              : 
     541              :        [locus of primary range]:
     542              : 
     543              :           some code
     544              :                  1
     545              :        Error: Some error at (1)
     546              : 
     547              :   With -fno-diagnostic-show-caret or if the primary range is not
     548              :   valid, it prints:
     549              : 
     550              :        [locus of primary range]: Error: Some error at (1) and (2)
     551              : */
     552              : static void
     553      1229087 : gfc_diagnostic_text_starter (diagnostics::text_sink &text_output,
     554              :                              const diagnostics::diagnostic_info *diagnostic)
     555              : {
     556      1229087 :   diagnostics::context *const context = &text_output.get_context ();
     557      1229087 :   pretty_printer *const pp = text_output.get_printer ();
     558      1229087 :   char * kind_prefix = gfc_diagnostic_build_kind_prefix (context, diagnostic);
     559              : 
     560      1229087 :   expanded_location s1 = diagnostic_expand_location (diagnostic);
     561      1229087 :   expanded_location s2;
     562      1229087 :   bool one_locus = diagnostic->m_richloc->get_num_locations () < 2;
     563      1229087 :   bool same_locus = false;
     564              : 
     565      1229087 :   if (!one_locus)
     566              :     {
     567          555 :       s2 = diagnostic_expand_location (diagnostic, 1);
     568         1110 :       same_locus = diagnostic_same_line (context, s1, s2);
     569              :     }
     570              : 
     571      1229087 :   diagnostics::location_print_policy loc_policy (text_output);
     572      1229087 :   const bool colorize = pp_show_color (pp);
     573      1229087 :   char * locus_prefix = (one_locus || !same_locus)
     574      1229087 :     ? gfc_diagnostic_build_locus_prefix (loc_policy, s1, colorize)
     575          213 :     : gfc_diagnostic_build_locus_prefix (loc_policy, s1, s2, colorize);
     576              : 
     577      1229087 :   if (!context->get_source_printing_options ().enabled
     578        16756 :       || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
     579      1245843 :       || diagnostic_location (diagnostic, 0) == context->m_last_location)
     580              :     {
     581      1212331 :       pp_set_prefix (pp,
     582              :                      concat (locus_prefix, " ", kind_prefix, NULL));
     583      1212331 :       free (locus_prefix);
     584              : 
     585      1212331 :       if (one_locus || same_locus)
     586              :         {
     587      1211991 :           free (kind_prefix);
     588      1211991 :           return;
     589              :         }
     590              :       /* In this case, we print the previous locus and prefix as:
     591              : 
     592              :           [locus]:[prefix]: (1)
     593              : 
     594              :          and we flush with a new line before setting the new prefix.  */
     595          340 :       pp_string (pp, "(1)");
     596          340 :       pp_newline (pp);
     597          340 :       locus_prefix = gfc_diagnostic_build_locus_prefix (loc_policy, s2, colorize);
     598          340 :       pp_set_prefix (pp,
     599              :                      concat (locus_prefix, " ", kind_prefix, NULL));
     600          340 :       free (kind_prefix);
     601          340 :       free (locus_prefix);
     602              :     }
     603              :   else
     604              :     {
     605        16756 :       pp_verbatim (pp, "%s", locus_prefix);
     606        16756 :       free (locus_prefix);
     607              :       /* Fortran uses an empty line between locus and caret line.  */
     608        16756 :       pp_newline (pp);
     609        16756 :       pp_set_prefix (pp, NULL);
     610        16756 :       pp_newline (pp);
     611        16756 :       diagnostic_show_locus (context,
     612        16756 :                              text_output.get_source_printing_options (),
     613        16756 :                              diagnostic->m_richloc, diagnostic->m_kind,
     614              :                              pp);
     615              :       /* If the caret line was shown, the prefix does not contain the
     616              :          locus.  */
     617        16756 :       pp_set_prefix (pp, kind_prefix);
     618              :     }
     619              : }
     620              : 
     621              : static void
     622            1 : gfc_diagnostic_start_span (const diagnostics::location_print_policy &loc_policy,
     623              :                            diagnostics::to_text &sink,
     624              :                            expanded_location exploc)
     625              : {
     626            1 :   pretty_printer *pp = diagnostics::get_printer (sink);
     627            1 :   const bool colorize = pp_show_color (pp);
     628            1 :   char *locus_prefix
     629            1 :     = gfc_diagnostic_build_locus_prefix (loc_policy, exploc, colorize);
     630            1 :   pp_verbatim (pp, "%s", locus_prefix);
     631            1 :   free (locus_prefix);
     632            1 :   pp_newline (pp);
     633              :   /* Fortran uses an empty line between locus and caret line.  */
     634            1 :   pp_newline (pp);
     635            1 : }
     636              : 
     637              : 
     638              : static void
     639      1229087 : gfc_diagnostic_text_finalizer (diagnostics::text_sink &text_output,
     640              :                                const diagnostics::diagnostic_info *,
     641              :                                enum diagnostics::kind orig_diag_kind ATTRIBUTE_UNUSED)
     642              : {
     643      1229087 :   pretty_printer *const pp = text_output.get_printer ();
     644      1229087 :   pp_destroy_prefix (pp);
     645      1229087 :   pp_newline_and_flush (pp);
     646      1229087 : }
     647              : 
     648              : /* Immediate warning (i.e. do not buffer the warning) with an explicit
     649              :    location.  */
     650              : 
     651              : bool
     652            3 : gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
     653              : {
     654            3 :   va_list argp;
     655            3 :   diagnostics::diagnostic_info diagnostic;
     656            3 :   rich_location rich_loc (line_table, loc);
     657            3 :   bool ret;
     658              : 
     659            3 :   va_start (argp, gmsgid);
     660            3 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     661              :                        diagnostics::kind::warning);
     662            3 :   diagnostic.m_option_id = opt;
     663            3 :   ret = gfc_report_diagnostic (&diagnostic);
     664            3 :   va_end (argp);
     665            6 :   return ret;
     666            3 : }
     667              : 
     668              : /* Immediate warning (i.e. do not buffer the warning).  */
     669              : 
     670              : bool
     671        27500 : gfc_warning_now (int opt, const char *gmsgid, ...)
     672              : {
     673        27500 :   va_list argp;
     674        27500 :   diagnostics::diagnostic_info diagnostic;
     675        27500 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     676        27500 :   bool ret;
     677              : 
     678        27500 :   va_start (argp, gmsgid);
     679        27500 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     680              :                        diagnostics::kind::warning);
     681        27500 :   diagnostic.m_option_id = opt;
     682        27500 :   ret = gfc_report_diagnostic (&diagnostic);
     683        27500 :   va_end (argp);
     684        55000 :   return ret;
     685        27500 : }
     686              : 
     687              : /* Internal warning, do not buffer.  */
     688              : 
     689              : bool
     690            0 : gfc_warning_internal (int opt, const char *gmsgid, ...)
     691              : {
     692            0 :   va_list argp;
     693            0 :   diagnostics::diagnostic_info diagnostic;
     694            0 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     695            0 :   bool ret;
     696              : 
     697            0 :   va_start (argp, gmsgid);
     698            0 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     699              :                        diagnostics::kind::warning);
     700            0 :   diagnostic.m_option_id = opt;
     701            0 :   ret = gfc_report_diagnostic (&diagnostic);
     702            0 :   va_end (argp);
     703            0 :   return ret;
     704            0 : }
     705              : 
     706              : /* Immediate error (i.e. do not buffer).  */
     707              : 
     708              : void
     709          466 : gfc_error_now (const char *gmsgid, ...)
     710              : {
     711          466 :   va_list argp;
     712          466 :   diagnostics::diagnostic_info diagnostic;
     713          466 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     714              : 
     715          466 :   error_buffer->flag = true;
     716              : 
     717          466 :   va_start (argp, gmsgid);
     718          466 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     719              :                        diagnostics::kind::error);
     720          466 :   gfc_report_diagnostic (&diagnostic);
     721          466 :   va_end (argp);
     722          466 : }
     723              : 
     724              : 
     725              : /* Fatal error, never returns.  */
     726              : 
     727              : void
     728           10 : gfc_fatal_error (const char *gmsgid, ...)
     729              : {
     730           10 :   va_list argp;
     731           10 :   diagnostics::diagnostic_info diagnostic;
     732           10 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     733              : 
     734           10 :   va_start (argp, gmsgid);
     735           10 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     736              :                        diagnostics::kind::fatal);
     737           10 :   gfc_report_diagnostic (&diagnostic);
     738            0 :   va_end (argp);
     739              : 
     740            0 :   gcc_unreachable ();
     741              : }
     742              : 
     743              : /* Clear the warning flag.  */
     744              : 
     745              : void
     746     13743333 : gfc_clear_warning (void)
     747              : {
     748     13743333 :   gfc_clear_diagnostic_buffer (pp_warning_buffer);
     749     13743333 : }
     750              : 
     751              : 
     752              : /* Check to see if any warnings have been saved.
     753              :    If so, print the warning.  */
     754              : 
     755              : void
     756      1401121 : gfc_warning_check (void)
     757              : {
     758      1401121 :   if (! pp_warning_buffer->empty_p ())
     759         4040 :     global_dc->flush_diagnostic_buffer (*pp_warning_buffer);
     760      1401121 : }
     761              : 
     762              : 
     763              : /* Issue an error.  */
     764              : 
     765              : static void
     766      1224912 : gfc_error_opt (int opt, const char *gmsgid, va_list ap)
     767              : {
     768      1224912 :   va_list argp;
     769      1224912 :   va_copy (argp, ap);
     770              : 
     771      1224912 :   if (warnings_not_errors)
     772              :     {
     773           43 :       gfc_warning (opt, gmsgid, argp);
     774           43 :       va_end (argp);
     775        18449 :       return;
     776              :     }
     777              : 
     778      1224869 :   if (suppress_errors)
     779              :     {
     780        18406 :       va_end (argp);
     781        18406 :       return;
     782              :     }
     783              : 
     784      1206463 :   diagnostics::diagnostic_info diagnostic;
     785      1206463 :   rich_location richloc (line_table, UNKNOWN_LOCATION);
     786      1206463 :   diagnostics::buffer *old_buffer = global_dc->get_diagnostic_buffer ();
     787      1206463 :   gcc_assert (!old_buffer);
     788              : 
     789      1206463 :   gfc_clear_diagnostic_buffer (pp_error_buffer);
     790              : 
     791      1206463 :   if (buffered_p)
     792      1199236 :     global_dc->set_diagnostic_buffer (pp_error_buffer);
     793              : 
     794      1206463 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc,
     795              :                        diagnostics::kind::error);
     796      1206463 :   gfc_report_diagnostic (&diagnostic);
     797              : 
     798      1206463 :   if (buffered_p)
     799      1199236 :     global_dc->set_diagnostic_buffer (old_buffer);
     800              : 
     801      1206463 :   va_end (argp);
     802      1206463 : }
     803              : 
     804              : 
     805              : void
     806          251 : gfc_error_opt (int opt, const char *gmsgid, ...)
     807              : {
     808          251 :   va_list argp;
     809          251 :   va_start (argp, gmsgid);
     810          251 :   gfc_error_opt (opt, gmsgid, argp);
     811          251 :   va_end (argp);
     812          251 : }
     813              : 
     814              : 
     815              : void
     816      1223918 : gfc_error (const char *gmsgid, ...)
     817              : {
     818      1223918 :   va_list argp;
     819      1223918 :   va_start (argp, gmsgid);
     820      1223918 :   gfc_error_opt (0, gmsgid, argp);
     821      1223918 :   va_end (argp);
     822      1223918 : }
     823              : 
     824              : 
     825              : /* This shouldn't happen... but sometimes does.  */
     826              : 
     827              : void
     828            0 : gfc_internal_error (const char *gmsgid, ...)
     829              : {
     830            0 :   int e, w;
     831            0 :   va_list argp;
     832            0 :   diagnostics::diagnostic_info diagnostic;
     833            0 :   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
     834              : 
     835            0 :   gfc_get_errors (&w, &e);
     836            0 :   if (e > 0)
     837            0 :     exit(EXIT_FAILURE);
     838              : 
     839            0 :   va_start (argp, gmsgid);
     840            0 :   diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
     841              :                        diagnostics::kind::ice);
     842            0 :   gfc_report_diagnostic (&diagnostic);
     843            0 :   va_end (argp);
     844              : 
     845            0 :   gcc_unreachable ();
     846              : }
     847              : 
     848              : 
     849              : /* Clear the error flag when we start to compile a source line.  */
     850              : 
     851              : void
     852      5058922 : gfc_clear_error (void)
     853              : {
     854      5058922 :   error_buffer->flag = false;
     855      5058922 :   warnings_not_errors = false;
     856      5058922 :   gfc_clear_diagnostic_buffer (pp_error_buffer);
     857      5058922 : }
     858              : 
     859              : 
     860              : /* Tests the state of error_flag.  */
     861              : 
     862              : bool
     863      1649146 : gfc_error_flag_test (void)
     864              : {
     865      1649146 :   return (error_buffer->flag
     866      1649146 :           || !pp_error_buffer->empty_p ());
     867              : }
     868              : 
     869              : 
     870              : /* Check to see if any errors have been saved.
     871              :    If so, print the error.  Returns the state of error_flag.  */
     872              : 
     873              : bool
     874         5496 : gfc_error_check (void)
     875              : {
     876         5496 :   if (error_buffer->flag
     877         5496 :       || ! pp_error_buffer->empty_p ())
     878              :     {
     879         3243 :       error_buffer->flag = false;
     880         3243 :       global_dc->flush_diagnostic_buffer (*pp_error_buffer);
     881         3243 :       return true;
     882              :     }
     883              : 
     884              :   return false;
     885              : }
     886              : 
     887              : /* Move the text buffered from FROM to TO, then clear
     888              :    FROM. Independently if there was text in FROM, TO is also
     889              :    cleared. */
     890              : 
     891              : static void
     892      3049288 : gfc_move_error_buffer_from_to (gfc_error_buffer * buffer_from,
     893              :                                gfc_error_buffer * buffer_to)
     894              : {
     895      3049288 :   diagnostics::buffer * from = &(buffer_from->buffer);
     896      3049288 :   diagnostics::buffer * to =  &(buffer_to->buffer);
     897              : 
     898      3049288 :   buffer_to->flag = buffer_from->flag;
     899      3049288 :   buffer_from->flag = false;
     900              : 
     901      3049288 :   gfc_clear_diagnostic_buffer (to);
     902              : 
     903      3049288 :   if (! from->empty_p ())
     904              :     {
     905       106002 :       from->move_to (*to);
     906       106002 :       gfc_clear_diagnostic_buffer (from);
     907              :     }
     908      3049288 : }
     909              : 
     910              : /* Save the existing error state.  */
     911              : 
     912              : void
     913      1562166 : gfc_push_error (gfc_error_buffer *err)
     914              : {
     915      1562166 :   gfc_move_error_buffer_from_to (error_buffer, err);
     916      1562166 : }
     917              : 
     918              : 
     919              : /* Restore a previous pushed error state.  */
     920              : 
     921              : void
     922      1487122 : gfc_pop_error (gfc_error_buffer *err)
     923              : {
     924      1487122 :   gfc_move_error_buffer_from_to (err, error_buffer);
     925      1487122 : }
     926              : 
     927              : 
     928              : /* Free a pushed error state, but keep the current error state.  */
     929              : 
     930              : void
     931        74877 : gfc_free_error (gfc_error_buffer *err)
     932              : {
     933        74877 :   gfc_clear_diagnostic_buffer (&(err->buffer));
     934        74877 : }
     935              : 
     936              : 
     937              : /* Report the number of warnings and errors that occurred to the caller.  */
     938              : 
     939              : void
     940       359496 : gfc_get_errors (int *w, int *e)
     941              : {
     942       359496 :   if (w != NULL)
     943       308293 :     *w = warningcount + werrorcount;
     944       359496 :   if (e != NULL)
     945       359496 :     *e = errorcount + sorrycount + werrorcount;
     946       359496 : }
     947              : 
     948              : 
     949              : /* Switch errors into warnings.  */
     950              : 
     951              : void
     952        49694 : gfc_errors_to_warnings (bool f)
     953              : {
     954        49694 :   warnings_not_errors = f;
     955        49694 : }
     956              : 
     957              : void
     958        31307 : gfc_diagnostics_init (void)
     959              : {
     960        31307 :   diagnostics::text_starter (global_dc) = gfc_diagnostic_text_starter;
     961        31307 :   diagnostics::start_span (global_dc) = gfc_diagnostic_start_span;
     962        31307 :   diagnostics::text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
     963        31307 :   global_dc->set_format_decoder (gfc_format_decoder);
     964        31307 :   auto &source_printing_opts = global_dc->get_source_printing_options ();
     965        31307 :   source_printing_opts.caret_chars[0] = '1';
     966        31307 :   source_printing_opts.caret_chars[1] = '2';
     967        31307 :   pp_warning_buffer = new diagnostics::buffer (*global_dc);
     968        31307 :   error_buffer = new gfc_error_buffer ();
     969        31307 :   pp_error_buffer = &(error_buffer->buffer);
     970        31307 : }
     971              : 
     972              : void
     973        31278 : gfc_diagnostics_finish (void)
     974              : {
     975        31278 :   tree_diagnostics_defaults (global_dc);
     976              :   /* We still want to use the gfc starter and finalizer, not the tree
     977              :      defaults.  */
     978        31278 :   diagnostics::text_starter (global_dc) = gfc_diagnostic_text_starter;
     979        31278 :   diagnostics::text_finalizer (global_dc) = gfc_diagnostic_text_finalizer;
     980        31278 :   auto &source_printing_opts = global_dc->get_source_printing_options ();
     981        31278 :   source_printing_opts.caret_chars[0] = '^';
     982        31278 :   source_printing_opts.caret_chars[1] = '^';
     983        62556 :   delete error_buffer;
     984        31278 :   error_buffer = nullptr;
     985        31278 :   pp_error_buffer = nullptr;
     986        31278 : }
        

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.