Home | History | Annotate | Line # | Download | only in gcc
      1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
      2    Copyright (C) 1999-2022 Free Software Foundation, Inc.
      3    Contributed by Gabriel Dos Reis <gdr (at) codesourcery.com>
      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 
     22 /* This file implements the language independent aspect of diagnostic
     23    message module.  */
     24 
     25 #include "config.h"
     26 #include "system.h"
     27 #include "coretypes.h"
     28 #include "version.h"
     29 #include "demangle.h"
     30 #include "intl.h"
     31 #include "backtrace.h"
     32 #include "diagnostic.h"
     33 #include "diagnostic-color.h"
     34 #include "diagnostic-url.h"
     35 #include "diagnostic-metadata.h"
     36 #include "diagnostic-path.h"
     37 #include "edit-context.h"
     38 #include "selftest.h"
     39 #include "selftest-diagnostic.h"
     40 #include "opts.h"
     41 #include "cpplib.h"
     42 
     43 #ifdef HAVE_TERMIOS_H
     44 # include <termios.h>
     45 #endif
     46 
     47 #ifdef GWINSZ_IN_SYS_IOCTL
     48 # include <sys/ioctl.h>
     49 #endif
     50 
     51 /* Disable warnings about quoting issues in the pp_xxx calls below
     52    that (intentionally) don't follow GCC diagnostic conventions.  */
     53 #if __GNUC__ >= 10
     54 #  pragma GCC diagnostic push
     55 #  pragma GCC diagnostic ignored "-Wformat-diag"
     56 #endif
     57 
     58 #define pedantic_warning_kind(DC)			\
     59   ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
     60 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
     61 #define permissive_error_option(DC) ((DC)->opt_permissive)
     62 
     63 /* Prototypes.  */
     64 static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
     65 			     int, const char *,
     66 			     va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
     67 static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
     68 			       int, unsigned HOST_WIDE_INT,
     69 			       const char *, const char *, va_list *,
     70 			       diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
     71 
     72 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
     73 static void real_abort (void) ATTRIBUTE_NORETURN;
     74 
     75 /* Name of program invoked, sans directories.  */
     76 
     77 const char *progname;
     78 
     79 /* A diagnostic_context surrogate for stderr.  */
     80 static diagnostic_context global_diagnostic_context;
     81 diagnostic_context *global_dc = &global_diagnostic_context;
     82 
     83 /* Return a malloc'd string containing MSG formatted a la printf.  The
     85    caller is responsible for freeing the memory.  */
     86 char *
     87 build_message_string (const char *msg, ...)
     88 {
     89   char *str;
     90   va_list ap;
     91 
     92   va_start (ap, msg);
     93   str = xvasprintf (msg, ap);
     94   va_end (ap);
     95 
     96   return str;
     97 }
     98 
     99 /* Same as diagnostic_build_prefix, but only the source FILE is given.  */
    100 char *
    101 file_name_as_prefix (diagnostic_context *context, const char *f)
    102 {
    103   const char *locus_cs
    104     = colorize_start (pp_show_color (context->printer), "locus");
    105   const char *locus_ce = colorize_stop (pp_show_color (context->printer));
    106   return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
    107 }
    108 
    109 
    110 
    111 /* Return the value of the getenv("COLUMNS") as an integer. If the
    113    value is not set to a positive integer, use ioctl to get the
    114    terminal width. If it fails, return INT_MAX.  */
    115 int
    116 get_terminal_width (void)
    117 {
    118   const char * s = getenv ("COLUMNS");
    119   if (s != NULL) {
    120     int n = atoi (s);
    121     if (n > 0)
    122       return n;
    123   }
    124 
    125 #ifdef TIOCGWINSZ
    126   struct winsize w;
    127   w.ws_col = 0;
    128   if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
    129     return w.ws_col;
    130 #endif
    131 
    132   return INT_MAX;
    133 }
    134 
    135 /* Set caret_max_width to value.  */
    136 void
    137 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
    138 {
    139   /* One minus to account for the leading empty space.  */
    140   value = value ? value - 1
    141     : (isatty (fileno (pp_buffer (context->printer)->stream))
    142        ? get_terminal_width () - 1: INT_MAX);
    143 
    144   if (value <= 0)
    145     value = INT_MAX;
    146 
    147   context->caret_max_width = value;
    148 }
    149 
    150 /* Default implementation of final_cb.  */
    151 
    152 static void
    153 default_diagnostic_final_cb (diagnostic_context *context)
    154 {
    155   /* Some of the errors may actually have been warnings.  */
    156   if (diagnostic_kind_count (context, DK_WERROR))
    157     {
    158       /* -Werror was given.  */
    159       if (context->warning_as_error_requested)
    160 	pp_verbatim (context->printer,
    161 		     _("%s: all warnings being treated as errors"),
    162 		     progname);
    163       /* At least one -Werror= was given.  */
    164       else
    165 	pp_verbatim (context->printer,
    166 		     _("%s: some warnings being treated as errors"),
    167 		     progname);
    168       pp_newline_and_flush (context->printer);
    169     }
    170 }
    171 
    172 /* Initialize the diagnostic message outputting machinery.  */
    173 void
    174 diagnostic_initialize (diagnostic_context *context, int n_opts)
    175 {
    176   int i;
    177 
    178   /* Allocate a basic pretty-printer.  Clients will replace this a
    179      much more elaborated pretty-printer if they wish.  */
    180   context->printer = XNEW (pretty_printer);
    181   new (context->printer) pretty_printer ();
    182 
    183   memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
    184   context->warning_as_error_requested = false;
    185   context->n_opts = n_opts;
    186   context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
    187   for (i = 0; i < n_opts; i++)
    188     context->classify_diagnostic[i] = DK_UNSPECIFIED;
    189   context->show_caret = false;
    190   diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
    191   for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
    192     context->caret_chars[i] = '^';
    193   context->show_cwe = false;
    194   context->path_format = DPF_NONE;
    195   context->show_path_depths = false;
    196   context->show_option_requested = false;
    197   context->abort_on_error = false;
    198   context->show_column = false;
    199   context->pedantic_errors = false;
    200   context->permissive = false;
    201   context->opt_permissive = 0;
    202   context->fatal_errors = false;
    203   context->dc_inhibit_warnings = false;
    204   context->dc_warn_system_headers = false;
    205   context->max_errors = 0;
    206   context->internal_error = NULL;
    207   diagnostic_starter (context) = default_diagnostic_starter;
    208   context->start_span = default_diagnostic_start_span_fn;
    209   diagnostic_finalizer (context) = default_diagnostic_finalizer;
    210   context->option_enabled = NULL;
    211   context->option_state = NULL;
    212   context->option_name = NULL;
    213   context->get_option_url = NULL;
    214   context->last_location = UNKNOWN_LOCATION;
    215   context->last_module = 0;
    216   context->x_data = NULL;
    217   context->lock = 0;
    218   context->inhibit_notes_p = false;
    219   context->colorize_source_p = false;
    220   context->show_labels_p = false;
    221   context->show_line_numbers_p = false;
    222   context->min_margin_width = 0;
    223   context->show_ruler_p = false;
    224   context->report_bug = false;
    225 
    226   if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
    227     {
    228       if (!strcmp (var, "fixits-v1"))
    229 	context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
    230       else if (!strcmp (var, "fixits-v2"))
    231 	context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
    232       /* Silently ignore unrecognized values.  */
    233     }
    234   context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
    235   context->column_origin = 1;
    236   context->tabstop = 8;
    237   context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
    238   context->edit_context_ptr = NULL;
    239   context->diagnostic_group_nesting_depth = 0;
    240   context->diagnostic_group_emission_count = 0;
    241   context->begin_group_cb = NULL;
    242   context->end_group_cb = NULL;
    243   context->final_cb = default_diagnostic_final_cb;
    244   context->includes_seen = NULL;
    245 }
    246 
    247 /* Maybe initialize the color support. We require clients to do this
    248    explicitly, since most clients don't want color.  When called
    249    without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT.  */
    250 
    251 void
    252 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
    253 {
    254   /* value == -1 is the default value.  */
    255   if (value < 0)
    256     {
    257       /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
    258 	 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
    259 	 otherwise default to -fdiagnostics-color=never, for other
    260 	 values default to that
    261 	 -fdiagnostics-color={never,auto,always}.  */
    262       if (DIAGNOSTICS_COLOR_DEFAULT == -1)
    263 	{
    264 	  if (!getenv ("GCC_COLORS"))
    265 	    return;
    266 	  value = DIAGNOSTICS_COLOR_AUTO;
    267 	}
    268       else
    269 	value = DIAGNOSTICS_COLOR_DEFAULT;
    270     }
    271   pp_show_color (context->printer)
    272     = colorize_init ((diagnostic_color_rule_t) value);
    273 }
    274 
    275 /* Initialize URL support within CONTEXT based on VALUE, handling "auto".  */
    276 
    277 void
    278 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
    279 {
    280   /* value == -1 is the default value.  */
    281   if (value < 0)
    282     {
    283       /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
    284 	 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
    285 	 environment, otherwise default to -fdiagnostics-urls=never,
    286 	 for other values default to that
    287 	 -fdiagnostics-urls={never,auto,always}.  */
    288       if (DIAGNOSTICS_URLS_DEFAULT == -1)
    289 	{
    290 	  if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
    291 	    return;
    292 	  value = DIAGNOSTICS_URL_AUTO;
    293 	}
    294       else
    295 	value = DIAGNOSTICS_URLS_DEFAULT;
    296     }
    297 
    298   context->printer->url_format
    299     = determine_url_format ((diagnostic_url_rule_t) value);
    300 }
    301 
    302 /* Create the file_cache, if not already created, and tell it how to
    303    translate files on input.  */
    304 void diagnostic_initialize_input_context (diagnostic_context *context,
    305 					  diagnostic_input_charset_callback ccb,
    306 					  bool should_skip_bom)
    307 {
    308   if (!context->m_file_cache)
    309     context->m_file_cache = new file_cache;
    310   context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
    311 }
    312 
    313 /* Do any cleaning up required after the last diagnostic is emitted.  */
    314 
    315 void
    316 diagnostic_finish (diagnostic_context *context)
    317 {
    318   if (context->final_cb)
    319     context->final_cb (context);
    320 
    321   diagnostic_file_cache_fini ();
    322 
    323   XDELETEVEC (context->classify_diagnostic);
    324   context->classify_diagnostic = NULL;
    325 
    326   /* diagnostic_initialize allocates context->printer using XNEW
    327      and placement-new.  */
    328   context->printer->~pretty_printer ();
    329   XDELETE (context->printer);
    330   context->printer = NULL;
    331 
    332   if (context->edit_context_ptr)
    333     {
    334       delete context->edit_context_ptr;
    335       context->edit_context_ptr = NULL;
    336     }
    337 
    338   if (context->includes_seen)
    339     {
    340       delete context->includes_seen;
    341       context->includes_seen = nullptr;
    342     }
    343 }
    344 
    345 /* Initialize DIAGNOSTIC, where the message MSG has already been
    346    translated.  */
    347 void
    348 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
    349 				va_list *args, rich_location *richloc,
    350 				diagnostic_t kind)
    351 {
    352   gcc_assert (richloc);
    353   diagnostic->message.err_no = errno;
    354   diagnostic->message.args_ptr = args;
    355   diagnostic->message.format_spec = msg;
    356   diagnostic->message.m_richloc = richloc;
    357   diagnostic->richloc = richloc;
    358   diagnostic->metadata = NULL;
    359   diagnostic->kind = kind;
    360   diagnostic->option_index = 0;
    361 }
    362 
    363 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
    364    translated.  */
    365 void
    366 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
    367 		     va_list *args, rich_location *richloc,
    368 		     diagnostic_t kind)
    369 {
    370   gcc_assert (richloc);
    371   diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
    372 }
    373 
    374 static const char *const diagnostic_kind_color[] = {
    375 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
    376 #include "diagnostic.def"
    377 #undef DEFINE_DIAGNOSTIC_KIND
    378   NULL
    379 };
    380 
    381 /* Get a color name for diagnostics of type KIND
    382    Result could be NULL.  */
    383 
    384 const char *
    385 diagnostic_get_color_for_kind (diagnostic_t kind)
    386 {
    387   return diagnostic_kind_color[kind];
    388 }
    389 
    390 /* Given an expanded_location, convert the column (which is in 1-based bytes)
    391    to the requested units, without converting the origin.
    392    Return -1 if the column is invalid (<= 0).  */
    393 
    394 static int
    395 convert_column_unit (enum diagnostics_column_unit column_unit,
    396 		     int tabstop,
    397 		     expanded_location s)
    398 {
    399   if (s.column <= 0)
    400     return -1;
    401 
    402   switch (column_unit)
    403     {
    404     default:
    405       gcc_unreachable ();
    406 
    407     case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
    408       {
    409 	cpp_char_column_policy policy (tabstop, cpp_wcwidth);
    410 	return location_compute_display_column (s, policy);
    411       }
    412 
    413     case DIAGNOSTICS_COLUMN_UNIT_BYTE:
    414       return s.column;
    415     }
    416 }
    417 
    418 /* Given an expanded_location, convert the column (which is in 1-based bytes)
    419    to the requested units and origin.  Return -1 if the column is
    420    invalid (<= 0).  */
    421 int
    422 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
    423 {
    424   int one_based_col
    425     = convert_column_unit (context->column_unit, context->tabstop, s);
    426   if (one_based_col <= 0)
    427     return -1;
    428   return one_based_col + (context->column_origin - 1);
    429 }
    430 
    431 /* Return a formatted line and column ':%line:%column'.  Elided if
    432    line == 0 or col < 0.  (A column of 0 may be valid due to the
    433    -fdiagnostics-column-origin option.)
    434    The result is a statically allocated buffer.  */
    435 
    436 static const char *
    437 maybe_line_and_column (int line, int col)
    438 {
    439   static char result[32];
    440 
    441   if (line)
    442     {
    443       size_t l
    444 	= snprintf (result, sizeof (result),
    445 		    col >= 0 ? ":%d:%d" : ":%d", line, col);
    446       gcc_checking_assert (l < sizeof (result));
    447     }
    448   else
    449     result[0] = 0;
    450   return result;
    451 }
    452 
    453 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
    454    The caller is responsible for freeing the memory.  */
    455 
    456 static char *
    457 diagnostic_get_location_text (diagnostic_context *context,
    458 			      expanded_location s)
    459 {
    460   pretty_printer *pp = context->printer;
    461   const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
    462   const char *locus_ce = colorize_stop (pp_show_color (pp));
    463   const char *file = s.file ? s.file : progname;
    464   int line = 0;
    465   int col = -1;
    466   if (strcmp (file, N_("<built-in>")))
    467     {
    468       line = s.line;
    469       if (context->show_column)
    470 	col = diagnostic_converted_column (context, s);
    471     }
    472 
    473   const char *line_col = maybe_line_and_column (line, col);
    474   return build_message_string ("%s%s%s:%s", locus_cs, file,
    475 			       line_col, locus_ce);
    476 }
    477 
    478 static const char *const diagnostic_kind_text[] = {
    479 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
    480 #include "diagnostic.def"
    481 #undef DEFINE_DIAGNOSTIC_KIND
    482   "must-not-happen"
    483 };
    484 
    485 /* Return a malloc'd string describing a location and the severity of the
    486    diagnostic, e.g. "foo.c:42:10: error: ".  The caller is responsible for
    487    freeing the memory.  */
    488 char *
    489 diagnostic_build_prefix (diagnostic_context *context,
    490 			 const diagnostic_info *diagnostic)
    491 {
    492   gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
    493 
    494   const char *text = _(diagnostic_kind_text[diagnostic->kind]);
    495   const char *text_cs = "", *text_ce = "";
    496   pretty_printer *pp = context->printer;
    497 
    498   if (diagnostic_kind_color[diagnostic->kind])
    499     {
    500       text_cs = colorize_start (pp_show_color (pp),
    501 				diagnostic_kind_color[diagnostic->kind]);
    502       text_ce = colorize_stop (pp_show_color (pp));
    503     }
    504 
    505   expanded_location s = diagnostic_expand_location (diagnostic);
    506   char *location_text = diagnostic_get_location_text (context, s);
    507 
    508   char *result = build_message_string ("%s %s%s%s", location_text,
    509 				       text_cs, text, text_ce);
    510   free (location_text);
    511   return result;
    512 }
    513 
    514 /* Functions at which to stop the backtrace print.  It's not
    515    particularly helpful to print the callers of these functions.  */
    516 
    517 static const char * const bt_stop[] =
    518 {
    519   "main",
    520   "toplev::main",
    521   "execute_one_pass",
    522   "compile_file",
    523 };
    524 
    525 /* A callback function passed to the backtrace_full function.  */
    526 
    527 static int
    528 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
    529 	     const char *function)
    530 {
    531   int *pcount = (int *) data;
    532 
    533   /* If we don't have any useful information, don't print
    534      anything.  */
    535   if (filename == NULL && function == NULL)
    536     return 0;
    537 
    538   /* Skip functions in diagnostic.cc.  */
    539   if (*pcount == 0
    540       && filename != NULL
    541       && strcmp (lbasename (filename), "diagnostic.cc") == 0)
    542     return 0;
    543 
    544   /* Print up to 20 functions.  We could make this a --param, but
    545      since this is only for debugging just use a constant for now.  */
    546   if (*pcount >= 20)
    547     {
    548       /* Returning a non-zero value stops the backtrace.  */
    549       return 1;
    550     }
    551   ++*pcount;
    552 
    553   char *alc = NULL;
    554   if (function != NULL)
    555     {
    556       char *str = cplus_demangle_v3 (function,
    557 				     (DMGL_VERBOSE | DMGL_ANSI
    558 				      | DMGL_GNU_V3 | DMGL_PARAMS));
    559       if (str != NULL)
    560 	{
    561 	  alc = str;
    562 	  function = str;
    563 	}
    564 
    565       for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
    566 	{
    567 	  size_t len = strlen (bt_stop[i]);
    568 	  if (strncmp (function, bt_stop[i], len) == 0
    569 	      && (function[len] == '\0' || function[len] == '('))
    570 	    {
    571 	      if (alc != NULL)
    572 		free (alc);
    573 	      /* Returning a non-zero value stops the backtrace.  */
    574 	      return 1;
    575 	    }
    576 	}
    577     }
    578 
    579   fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
    580 	   (unsigned long) pc,
    581 	   function == NULL ? "???" : function,
    582 	   filename == NULL ? "???" : filename,
    583 	   lineno);
    584 
    585   if (alc != NULL)
    586     free (alc);
    587 
    588   return 0;
    589 }
    590 
    591 /* A callback function passed to the backtrace_full function.  This is
    592    called if backtrace_full has an error.  */
    593 
    594 static void
    595 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
    596 {
    597   if (errnum < 0)
    598     {
    599       /* This means that no debug info was available.  Just quietly
    600 	 skip printing backtrace info.  */
    601       return;
    602     }
    603   fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
    604 	   errnum == 0 ? "" : xstrerror (errnum));
    605 }
    606 
    607 /* Check if we've met the maximum error limit, and if so fatally exit
    608    with a message.  CONTEXT is the context to check, and FLUSH
    609    indicates whether a diagnostic_finish call is needed.  */
    610 
    611 void
    612 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
    613 {
    614   if (!context->max_errors)
    615     return;
    616 
    617   int count = (diagnostic_kind_count (context, DK_ERROR)
    618 	       + diagnostic_kind_count (context, DK_SORRY)
    619 	       + diagnostic_kind_count (context, DK_WERROR));
    620 
    621   if (count >= context->max_errors)
    622     {
    623       fnotice (stderr,
    624 	       "compilation terminated due to -fmax-errors=%u.\n",
    625 	       context->max_errors);
    626       if (flush)
    627 	diagnostic_finish (context);
    628       exit (FATAL_EXIT_CODE);
    629     }
    630 }
    631 
    632 /* Take any action which is expected to happen after the diagnostic
    633    is written out.  This function does not always return.  */
    634 void
    635 diagnostic_action_after_output (diagnostic_context *context,
    636 				diagnostic_t diag_kind)
    637 {
    638   switch (diag_kind)
    639     {
    640     case DK_DEBUG:
    641     case DK_NOTE:
    642     case DK_ANACHRONISM:
    643     case DK_WARNING:
    644       break;
    645 
    646     case DK_ERROR:
    647     case DK_SORRY:
    648       if (context->abort_on_error)
    649 	real_abort ();
    650       if (context->fatal_errors)
    651 	{
    652 	  fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
    653 	  diagnostic_finish (context);
    654 	  exit (FATAL_EXIT_CODE);
    655 	}
    656       break;
    657 
    658     case DK_ICE:
    659     case DK_ICE_NOBT:
    660       {
    661 	struct backtrace_state *state = NULL;
    662 	if (diag_kind == DK_ICE)
    663 	  state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
    664 	int count = 0;
    665 	if (state != NULL)
    666 	  backtrace_full (state, 2, bt_callback, bt_err_callback,
    667 			  (void *) &count);
    668 
    669 	if (context->abort_on_error)
    670 	  real_abort ();
    671 
    672 	if (context->report_bug)
    673 	  fnotice (stderr, "Please submit a full bug report, "
    674 		   "with preprocessed source.\n");
    675 	else
    676 	  fnotice (stderr, "Please submit a full bug report, "
    677 		   "with preprocessed source (by using -freport-bug).\n");
    678 
    679 	if (count > 0)
    680 	  fnotice (stderr, "Please include the complete backtrace "
    681 		   "with any bug report.\n");
    682 	fnotice (stderr, "See %s for instructions.\n", bug_report_url);
    683 
    684 	exit (ICE_EXIT_CODE);
    685       }
    686 
    687     case DK_FATAL:
    688       if (context->abort_on_error)
    689 	real_abort ();
    690       diagnostic_finish (context);
    691       fnotice (stderr, "compilation terminated.\n");
    692       exit (FATAL_EXIT_CODE);
    693 
    694     default:
    695       gcc_unreachable ();
    696     }
    697 }
    698 
    699 /* True if the last module or file in which a diagnostic was reported is
    700    different from the current one.  */
    701 
    702 static bool
    703 last_module_changed_p (diagnostic_context *context,
    704 		       const line_map_ordinary *map)
    705 {
    706   return context->last_module != map;
    707 }
    708 
    709 /* Remember the current module or file as being the last one in which we
    710    report a diagnostic.  */
    711 
    712 static void
    713 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
    714 {
    715   context->last_module = map;
    716 }
    717 
    718 /* Only dump the "In file included from..." stack once for each file.  */
    719 
    720 static bool
    721 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
    722 {
    723   /* No include path for main.  */
    724   if (MAIN_FILE_P (map))
    725     return true;
    726 
    727   /* Always identify C++ modules, at least for now.  */
    728   auto probe = map;
    729   if (linemap_check_ordinary (map)->reason == LC_RENAME)
    730     /* The module source file shows up as LC_RENAME inside LC_MODULE.  */
    731     probe = linemap_included_from_linemap (line_table, map);
    732   if (MAP_MODULE_P (probe))
    733     return false;
    734 
    735   if (!context->includes_seen)
    736     context->includes_seen = new hash_set<location_t, false, location_hash>;
    737 
    738   /* Hash the location of the #include directive to better handle files
    739      that are included multiple times with different macros defined.  */
    740   return context->includes_seen->add (linemap_included_from (map));
    741 }
    742 
    743 void
    744 diagnostic_report_current_module (diagnostic_context *context, location_t where)
    745 {
    746   const line_map_ordinary *map = NULL;
    747 
    748   if (pp_needs_newline (context->printer))
    749     {
    750       pp_newline (context->printer);
    751       pp_needs_newline (context->printer) = false;
    752     }
    753 
    754   if (where <= BUILTINS_LOCATION)
    755     return;
    756 
    757   linemap_resolve_location (line_table, where,
    758 			    LRK_MACRO_DEFINITION_LOCATION,
    759 			    &map);
    760 
    761   if (map && last_module_changed_p (context, map))
    762     {
    763       set_last_module (context, map);
    764       if (!includes_seen (context, map))
    765 	{
    766 	  bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
    767 	  expanded_location s = {};
    768 	  do
    769 	    {
    770 	      where = linemap_included_from (map);
    771 	      map = linemap_included_from_linemap (line_table, map);
    772 	      bool is_module = MAP_MODULE_P (map);
    773 	      s.file = LINEMAP_FILE (map);
    774 	      s.line = SOURCE_LINE (map, where);
    775 	      int col = -1;
    776 	      if (first && context->show_column)
    777 		{
    778 		  s.column = SOURCE_COLUMN (map, where);
    779 		  col = diagnostic_converted_column (context, s);
    780 		}
    781 	      const char *line_col = maybe_line_and_column (s.line, col);
    782 	      static const char *const msgs[] =
    783 		{
    784 		 NULL,
    785 		 N_("                 from"),
    786 		 N_("In file included from"),	/* 2 */
    787 		 N_("        included from"),
    788 		 N_("In module"),		/* 4 */
    789 		 N_("of module"),
    790 		 N_("In module imported at"),	/* 6 */
    791 		 N_("imported at"),
    792 		};
    793 
    794 	      unsigned index = (was_module ? 6 : is_module ? 4
    795 				: need_inc ? 2 : 0) + !first;
    796 
    797 	      pp_verbatim (context->printer, "%s%s %r%s%s%R",
    798 			   first ? "" : was_module ? ", " : ",\n",
    799 			   _(msgs[index]),
    800 			   "locus", s.file, line_col);
    801 	      first = false, need_inc = was_module, was_module = is_module;
    802 	    }
    803 	  while (!includes_seen (context, map));
    804 	  pp_verbatim (context->printer, ":");
    805 	  pp_newline (context->printer);
    806 	}
    807     }
    808 }
    809 
    810 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
    811    print the path.  */
    812 
    813 void
    814 diagnostic_show_any_path (diagnostic_context *context,
    815 			  diagnostic_info *diagnostic)
    816 {
    817   const diagnostic_path *path = diagnostic->richloc->get_path ();
    818   if (!path)
    819     return;
    820 
    821   if (context->print_path)
    822     context->print_path (context, path);
    823 }
    824 
    825 /* Return true if the events in this path involve more than one
    826    function, or false if it is purely intraprocedural.  */
    827 
    828 bool
    829 diagnostic_path::interprocedural_p () const
    830 {
    831   const unsigned num = num_events ();
    832   for (unsigned i = 0; i < num; i++)
    833     {
    834       if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
    835 	return true;
    836       if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
    837 	return true;
    838     }
    839   return false;
    840 }
    841 
    842 void
    843 default_diagnostic_starter (diagnostic_context *context,
    844 			    diagnostic_info *diagnostic)
    845 {
    846   diagnostic_report_current_module (context, diagnostic_location (diagnostic));
    847   pp_set_prefix (context->printer, diagnostic_build_prefix (context,
    848 							    diagnostic));
    849 }
    850 
    851 void
    852 default_diagnostic_start_span_fn (diagnostic_context *context,
    853 				  expanded_location exploc)
    854 {
    855   char *text = diagnostic_get_location_text (context, exploc);
    856   pp_string (context->printer, text);
    857   free (text);
    858   pp_newline (context->printer);
    859 }
    860 
    861 void
    862 default_diagnostic_finalizer (diagnostic_context *context,
    863 			      diagnostic_info *diagnostic,
    864 			      diagnostic_t)
    865 {
    866   char *saved_prefix = pp_take_prefix (context->printer);
    867   pp_set_prefix (context->printer, NULL);
    868   pp_newline (context->printer);
    869   diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
    870   pp_set_prefix (context->printer, saved_prefix);
    871   pp_flush (context->printer);
    872 }
    873 
    874 /* Interface to specify diagnostic kind overrides.  Returns the
    875    previous setting, or DK_UNSPECIFIED if the parameters are out of
    876    range.  If OPTION_INDEX is zero, the new setting is for all the
    877    diagnostics.  */
    878 diagnostic_t
    879 diagnostic_classify_diagnostic (diagnostic_context *context,
    880 				int option_index,
    881 				diagnostic_t new_kind,
    882 				location_t where)
    883 {
    884   diagnostic_t old_kind;
    885 
    886   if (option_index < 0
    887       || option_index >= context->n_opts
    888       || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
    889     return DK_UNSPECIFIED;
    890 
    891   old_kind = context->classify_diagnostic[option_index];
    892 
    893   /* Handle pragmas separately, since we need to keep track of *where*
    894      the pragmas were.  */
    895   if (where != UNKNOWN_LOCATION)
    896     {
    897       int i;
    898 
    899       /* Record the command-line status, so we can reset it back on DK_POP. */
    900       if (old_kind == DK_UNSPECIFIED)
    901 	{
    902 	  old_kind = !context->option_enabled (option_index,
    903 					       context->lang_mask,
    904 					       context->option_state)
    905 	    ? DK_IGNORED : (context->warning_as_error_requested
    906 			    ? DK_ERROR : DK_WARNING);
    907 	  context->classify_diagnostic[option_index] = old_kind;
    908 	}
    909 
    910       for (i = context->n_classification_history - 1; i >= 0; i --)
    911 	if (context->classification_history[i].option == option_index)
    912 	  {
    913 	    old_kind = context->classification_history[i].kind;
    914 	    break;
    915 	  }
    916 
    917       i = context->n_classification_history;
    918       context->classification_history =
    919 	(diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
    920 							 * sizeof (diagnostic_classification_change_t));
    921       context->classification_history[i].location = where;
    922       context->classification_history[i].option = option_index;
    923       context->classification_history[i].kind = new_kind;
    924       context->n_classification_history ++;
    925     }
    926   else
    927     context->classify_diagnostic[option_index] = new_kind;
    928 
    929   return old_kind;
    930 }
    931 
    932 /* Save all diagnostic classifications in a stack.  */
    933 void
    934 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
    935 {
    936   context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
    937   context->push_list[context->n_push ++] = context->n_classification_history;
    938 }
    939 
    940 /* Restore the topmost classification set off the stack.  If the stack
    941    is empty, revert to the state based on command line parameters.  */
    942 void
    943 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
    944 {
    945   int jump_to;
    946   int i;
    947 
    948   if (context->n_push)
    949     jump_to = context->push_list [-- context->n_push];
    950   else
    951     jump_to = 0;
    952 
    953   i = context->n_classification_history;
    954   context->classification_history =
    955     (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
    956 						     * sizeof (diagnostic_classification_change_t));
    957   context->classification_history[i].location = where;
    958   context->classification_history[i].option = jump_to;
    959   context->classification_history[i].kind = DK_POP;
    960   context->n_classification_history ++;
    961 }
    962 
    963 /* Helper function for print_parseable_fixits.  Print TEXT to PP, obeying the
    964    escaping rules for -fdiagnostics-parseable-fixits.  */
    965 
    966 static void
    967 print_escaped_string (pretty_printer *pp, const char *text)
    968 {
    969   gcc_assert (pp);
    970   gcc_assert (text);
    971 
    972   pp_character (pp, '"');
    973   for (const char *ch = text; *ch; ch++)
    974     {
    975       switch (*ch)
    976 	{
    977 	case '\\':
    978 	  /* Escape backslash as two backslashes.  */
    979 	  pp_string (pp, "\\\\");
    980 	  break;
    981 	case '\t':
    982 	  /* Escape tab as "\t".  */
    983 	  pp_string (pp, "\\t");
    984 	  break;
    985 	case '\n':
    986 	  /* Escape newline as "\n".  */
    987 	  pp_string (pp, "\\n");
    988 	  break;
    989 	case '"':
    990 	  /* Escape doublequotes as \".  */
    991 	  pp_string (pp, "\\\"");
    992 	  break;
    993 	default:
    994 	  if (ISPRINT (*ch))
    995 	    pp_character (pp, *ch);
    996 	  else
    997 	    /* Use octal for non-printable chars.  */
    998 	    {
    999 	      unsigned char c = (*ch & 0xff);
   1000 	      pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
   1001 	    }
   1002 	  break;
   1003 	}
   1004     }
   1005   pp_character (pp, '"');
   1006 }
   1007 
   1008 /* Implementation of -fdiagnostics-parseable-fixits and
   1009    GCC_EXTRA_DIAGNOSTIC_OUTPUT.
   1010    Print a machine-parseable version of all fixits in RICHLOC to PP,
   1011    using COLUMN_UNIT to express columns.
   1012    Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY.  */
   1013 
   1014 static void
   1015 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
   1016 			enum diagnostics_column_unit column_unit,
   1017 			int tabstop)
   1018 {
   1019   gcc_assert (pp);
   1020   gcc_assert (richloc);
   1021 
   1022   char *saved_prefix = pp_take_prefix (pp);
   1023   pp_set_prefix (pp, NULL);
   1024 
   1025   for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
   1026     {
   1027       const fixit_hint *hint = richloc->get_fixit_hint (i);
   1028       location_t start_loc = hint->get_start_loc ();
   1029       expanded_location start_exploc = expand_location (start_loc);
   1030       pp_string (pp, "fix-it:");
   1031       print_escaped_string (pp, start_exploc.file);
   1032       /* For compatibility with clang, print as a half-open range.  */
   1033       location_t next_loc = hint->get_next_loc ();
   1034       expanded_location next_exploc = expand_location (next_loc);
   1035       int start_col
   1036 	= convert_column_unit (column_unit, tabstop, start_exploc);
   1037       int next_col
   1038 	= convert_column_unit (column_unit, tabstop, next_exploc);
   1039       pp_printf (pp, ":{%i:%i-%i:%i}:",
   1040 		 start_exploc.line, start_col,
   1041 		 next_exploc.line, next_col);
   1042       print_escaped_string (pp, hint->get_string ());
   1043       pp_newline (pp);
   1044     }
   1045 
   1046   pp_set_prefix (pp, saved_prefix);
   1047 }
   1048 
   1049 /* Update the inlining info in CONTEXT for a DIAGNOSTIC.  */
   1050 
   1051 static void
   1052 get_any_inlining_info (diagnostic_context *context,
   1053 		       diagnostic_info *diagnostic)
   1054 {
   1055   auto &ilocs = diagnostic->m_iinfo.m_ilocs;
   1056 
   1057   if (context->set_locations_cb)
   1058     /* Retrieve the locations into which the expression about to be
   1059        diagnosed has been inlined, including those of all the callers
   1060        all the way down the inlining stack.  */
   1061     context->set_locations_cb (context, diagnostic);
   1062   else
   1063     {
   1064       /* When there's no callback use just the one location provided
   1065 	 by the caller of the diagnostic function.  */
   1066       location_t loc = diagnostic_location (diagnostic);
   1067       ilocs.safe_push (loc);
   1068       diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
   1069     }
   1070 }
   1071 
   1072 /* Update the kind of DIAGNOSTIC based on its location(s), including
   1073    any of those in its inlining stack, relative to any
   1074      #pragma GCC diagnostic
   1075    directives recorded within CONTEXT.
   1076 
   1077    Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
   1078    otherwise.  */
   1079 
   1080 static diagnostic_t
   1081 update_effective_level_from_pragmas (diagnostic_context *context,
   1082 				     diagnostic_info *diagnostic)
   1083 {
   1084   if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
   1085     {
   1086       /* Ignore the diagnostic if all the inlined locations are
   1087 	 in system headers and -Wno-system-headers is in effect.  */
   1088       diagnostic->kind = DK_IGNORED;
   1089       return DK_IGNORED;
   1090     }
   1091 
   1092   if (context->n_classification_history <= 0)
   1093     return DK_UNSPECIFIED;
   1094 
   1095   /* Iterate over the locations, checking the diagnostic disposition
   1096      for the diagnostic at each.  If it's explicitly set as opposed
   1097      to unspecified, update the disposition for this instance of
   1098      the diagnostic and return it.  */
   1099   for (location_t loc: diagnostic->m_iinfo.m_ilocs)
   1100     {
   1101       /* FIXME: Stupid search.  Optimize later. */
   1102       for (int i = context->n_classification_history - 1; i >= 0; i --)
   1103 	{
   1104 	  const diagnostic_classification_change_t &hist
   1105 	    = context->classification_history[i];
   1106 
   1107 	  location_t pragloc = hist.location;
   1108 	  if (!linemap_location_before_p (line_table, pragloc, loc))
   1109 	    continue;
   1110 
   1111 	  if (hist.kind == (int) DK_POP)
   1112 	    {
   1113 	      /* Move on to the next region.  */
   1114 	      i = hist.option;
   1115 	      continue;
   1116 	    }
   1117 
   1118 	  int option = hist.option;
   1119 	  /* The option 0 is for all the diagnostics.  */
   1120 	  if (option == 0 || option == diagnostic->option_index)
   1121 	    {
   1122 	      diagnostic_t kind = hist.kind;
   1123 	      if (kind != DK_UNSPECIFIED)
   1124 		diagnostic->kind = kind;
   1125 	      return kind;
   1126 	    }
   1127 	}
   1128     }
   1129 
   1130   return DK_UNSPECIFIED;
   1131 }
   1132 
   1133 /* Generate a URL string describing CWE.  The caller is responsible for
   1134    freeing the string.  */
   1135 
   1136 static char *
   1137 get_cwe_url (int cwe)
   1138 {
   1139   return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
   1140 }
   1141 
   1142 /* If DIAGNOSTIC has a CWE identifier, print it.
   1143 
   1144    For example, if the diagnostic metadata associates it with CWE-119,
   1145    " [CWE-119]" will be printed, suitably colorized, and with a URL of a
   1146    description of the security issue.  */
   1147 
   1148 static void
   1149 print_any_cwe (diagnostic_context *context,
   1150 		    const diagnostic_info *diagnostic)
   1151 {
   1152   if (diagnostic->metadata == NULL)
   1153     return;
   1154 
   1155   int cwe = diagnostic->metadata->get_cwe ();
   1156   if (cwe)
   1157     {
   1158       pretty_printer *pp = context->printer;
   1159       char *saved_prefix = pp_take_prefix (context->printer);
   1160       pp_string (pp, " [");
   1161       pp_string (pp, colorize_start (pp_show_color (pp),
   1162 				     diagnostic_kind_color[diagnostic->kind]));
   1163       if (pp->url_format != URL_FORMAT_NONE)
   1164 	{
   1165 	  char *cwe_url = get_cwe_url (cwe);
   1166 	  pp_begin_url (pp, cwe_url);
   1167 	  free (cwe_url);
   1168 	}
   1169       pp_printf (pp, "CWE-%i", cwe);
   1170       pp_set_prefix (context->printer, saved_prefix);
   1171       if (pp->url_format != URL_FORMAT_NONE)
   1172 	pp_end_url (pp);
   1173       pp_string (pp, colorize_stop (pp_show_color (pp)));
   1174       pp_character (pp, ']');
   1175     }
   1176 }
   1177 
   1178 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
   1179    printer, e.g. " [-Werror=uninitialized]".
   1180    Subroutine of diagnostic_report_diagnostic.  */
   1181 
   1182 static void
   1183 print_option_information (diagnostic_context *context,
   1184 			  const diagnostic_info *diagnostic,
   1185 			  diagnostic_t orig_diag_kind)
   1186 {
   1187   char *option_text;
   1188 
   1189   option_text = context->option_name (context, diagnostic->option_index,
   1190 				      orig_diag_kind, diagnostic->kind);
   1191 
   1192   if (option_text)
   1193     {
   1194       char *option_url = NULL;
   1195       if (context->get_option_url
   1196 	  && context->printer->url_format != URL_FORMAT_NONE)
   1197 	option_url = context->get_option_url (context,
   1198 					      diagnostic->option_index);
   1199       pretty_printer *pp = context->printer;
   1200       pp_string (pp, " [");
   1201       pp_string (pp, colorize_start (pp_show_color (pp),
   1202 				     diagnostic_kind_color[diagnostic->kind]));
   1203       if (option_url)
   1204 	pp_begin_url (pp, option_url);
   1205       pp_string (pp, option_text);
   1206       if (option_url)
   1207 	{
   1208 	  pp_end_url (pp);
   1209 	  free (option_url);
   1210 	}
   1211       pp_string (pp, colorize_stop (pp_show_color (pp)));
   1212       pp_character (pp, ']');
   1213       free (option_text);
   1214     }
   1215 }
   1216 
   1217 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
   1218    as appropriate for #pragma GCC diagnostic and -Werror=foo.  */
   1219 
   1220 static bool
   1221 diagnostic_enabled (diagnostic_context *context,
   1222 		    diagnostic_info *diagnostic)
   1223 {
   1224   /* Update the inlining stack for this diagnostic.  */
   1225   get_any_inlining_info (context, diagnostic);
   1226 
   1227   /* Diagnostics with no option or -fpermissive are always enabled.  */
   1228   if (!diagnostic->option_index
   1229       || diagnostic->option_index == permissive_error_option (context))
   1230     return true;
   1231 
   1232   /* This tests if the user provided the appropriate -Wfoo or
   1233      -Wno-foo option.  */
   1234   if (! context->option_enabled (diagnostic->option_index,
   1235 				 context->lang_mask,
   1236 				 context->option_state))
   1237     return false;
   1238 
   1239   /* This tests for #pragma diagnostic changes.  */
   1240   diagnostic_t diag_class
   1241     = update_effective_level_from_pragmas (context, diagnostic);
   1242 
   1243   /* This tests if the user provided the appropriate -Werror=foo
   1244      option.  */
   1245   if (diag_class == DK_UNSPECIFIED
   1246       && (context->classify_diagnostic[diagnostic->option_index]
   1247 	  != DK_UNSPECIFIED))
   1248     diagnostic->kind
   1249       = context->classify_diagnostic[diagnostic->option_index];
   1250 
   1251   /* This allows for future extensions, like temporarily disabling
   1252      warnings for ranges of source code.  */
   1253   if (diagnostic->kind == DK_IGNORED)
   1254     return false;
   1255 
   1256   return true;
   1257 }
   1258 
   1259 /* Returns whether warning OPT is enabled at LOC.  */
   1260 
   1261 bool
   1262 warning_enabled_at (location_t loc, int opt)
   1263 {
   1264   if (!diagnostic_report_warnings_p (global_dc, loc))
   1265     return false;
   1266 
   1267   rich_location richloc (line_table, loc);
   1268   diagnostic_info diagnostic = {};
   1269   diagnostic.option_index = opt;
   1270   diagnostic.richloc = &richloc;
   1271   diagnostic.message.m_richloc = &richloc;
   1272   diagnostic.kind = DK_WARNING;
   1273   return diagnostic_enabled (global_dc, &diagnostic);
   1274 }
   1275 
   1276 /* Report a diagnostic message (an error or a warning) as specified by
   1277    DC.  This function is *the* subroutine in terms of which front-ends
   1278    should implement their specific diagnostic handling modules.  The
   1279    front-end independent format specifiers are exactly those described
   1280    in the documentation of output_format.
   1281    Return true if a diagnostic was printed, false otherwise.  */
   1282 
   1283 bool
   1284 diagnostic_report_diagnostic (diagnostic_context *context,
   1285 			      diagnostic_info *diagnostic)
   1286 {
   1287   location_t location = diagnostic_location (diagnostic);
   1288   diagnostic_t orig_diag_kind = diagnostic->kind;
   1289 
   1290   /* Give preference to being able to inhibit warnings, before they
   1291      get reclassified to something else.  */
   1292   bool report_warning_p = true;
   1293   if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
   1294     {
   1295       if (context->dc_inhibit_warnings)
   1296 	return false;
   1297       /* Remember the result of the overall system header warning setting
   1298 	 but proceed to also check the inlining context.  */
   1299       report_warning_p = diagnostic_report_warnings_p (context, location);
   1300       if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
   1301 	return false;
   1302     }
   1303 
   1304   if (diagnostic->kind == DK_PEDWARN)
   1305     {
   1306       diagnostic->kind = pedantic_warning_kind (context);
   1307       /* We do this to avoid giving the message for -pedantic-errors.  */
   1308       orig_diag_kind = diagnostic->kind;
   1309     }
   1310 
   1311   if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
   1312     return false;
   1313 
   1314   if (context->lock > 0)
   1315     {
   1316       /* If we're reporting an ICE in the middle of some other error,
   1317 	 try to flush out the previous error, then let this one
   1318 	 through.  Don't do this more than once.  */
   1319       if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
   1320 	  && context->lock == 1)
   1321 	pp_newline_and_flush (context->printer);
   1322       else
   1323 	error_recursion (context);
   1324     }
   1325 
   1326   /* If the user requested that warnings be treated as errors, so be
   1327      it.  Note that we do this before the next block so that
   1328      individual warnings can be overridden back to warnings with
   1329      -Wno-error=*.  */
   1330   if (context->warning_as_error_requested
   1331       && diagnostic->kind == DK_WARNING)
   1332     diagnostic->kind = DK_ERROR;
   1333 
   1334   diagnostic->message.x_data = &diagnostic->x_data;
   1335 
   1336   /* Check to see if the diagnostic is enabled at the location and
   1337      not disabled by #pragma GCC diagnostic anywhere along the inlining
   1338      stack.  .  */
   1339   if (!diagnostic_enabled (context, diagnostic))
   1340     return false;
   1341 
   1342   if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
   1343     /* Bail if the warning is not to be reported because all locations
   1344        in the inlining stack (if there is one) are in system headers.  */
   1345     return false;
   1346 
   1347   if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
   1348     diagnostic_check_max_errors (context);
   1349 
   1350   context->lock++;
   1351 
   1352   if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
   1353     {
   1354       /* When not checking, ICEs are converted to fatal errors when an
   1355 	 error has already occurred.  This is counteracted by
   1356 	 abort_on_error.  */
   1357       if (!CHECKING_P
   1358 	  && (diagnostic_kind_count (context, DK_ERROR) > 0
   1359 	      || diagnostic_kind_count (context, DK_SORRY) > 0)
   1360 	  && !context->abort_on_error)
   1361 	{
   1362 	  expanded_location s
   1363 	    = expand_location (diagnostic_location (diagnostic));
   1364 	  fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
   1365 		   s.file, s.line);
   1366 	  exit (ICE_EXIT_CODE);
   1367 	}
   1368       if (context->internal_error)
   1369 	(*context->internal_error) (context,
   1370 				    diagnostic->message.format_spec,
   1371 				    diagnostic->message.args_ptr);
   1372     }
   1373   if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
   1374     ++diagnostic_kind_count (context, DK_WERROR);
   1375   else
   1376     ++diagnostic_kind_count (context, diagnostic->kind);
   1377 
   1378   /* Is this the initial diagnostic within the stack of groups?  */
   1379   if (context->diagnostic_group_emission_count == 0)
   1380     {
   1381       if (context->begin_group_cb)
   1382 	context->begin_group_cb (context);
   1383     }
   1384   context->diagnostic_group_emission_count++;
   1385 
   1386   pp_format (context->printer, &diagnostic->message);
   1387   (*diagnostic_starter (context)) (context, diagnostic);
   1388   pp_output_formatted_text (context->printer);
   1389   if (context->show_cwe)
   1390     print_any_cwe (context, diagnostic);
   1391   if (context->show_option_requested)
   1392     print_option_information (context, diagnostic, orig_diag_kind);
   1393   (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
   1394   switch (context->extra_output_kind)
   1395     {
   1396     default:
   1397       break;
   1398     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
   1399       print_parseable_fixits (context->printer, diagnostic->richloc,
   1400 			      DIAGNOSTICS_COLUMN_UNIT_BYTE,
   1401 			      context->tabstop);
   1402       pp_flush (context->printer);
   1403       break;
   1404     case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
   1405       print_parseable_fixits (context->printer, diagnostic->richloc,
   1406 			      DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
   1407 			      context->tabstop);
   1408       pp_flush (context->printer);
   1409       break;
   1410     }
   1411   diagnostic_action_after_output (context, diagnostic->kind);
   1412   diagnostic->x_data = NULL;
   1413 
   1414   if (context->edit_context_ptr)
   1415     if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
   1416       context->edit_context_ptr->add_fixits (diagnostic->richloc);
   1417 
   1418   context->lock--;
   1419 
   1420   diagnostic_show_any_path (context, diagnostic);
   1421 
   1422   return true;
   1423 }
   1424 
   1425 /* Get the number of digits in the decimal representation of VALUE.  */
   1426 
   1427 int
   1428 num_digits (int value)
   1429 {
   1430   /* Perhaps simpler to use log10 for this, but doing it this way avoids
   1431      using floating point.  */
   1432   gcc_assert (value >= 0);
   1433 
   1434   if (value == 0)
   1435     return 1;
   1436 
   1437   int digits = 0;
   1438   while (value > 0)
   1439     {
   1440       digits++;
   1441       value /= 10;
   1442     }
   1443   return digits;
   1444 }
   1445 
   1446 /* Given a partial pathname as input, return another pathname that
   1447    shares no directory elements with the pathname of __FILE__.  This
   1448    is used by fancy_abort() to print `internal compiler error in expr.cc'
   1449    instead of `internal compiler error in ../../GCC/gcc/expr.cc'.  */
   1450 
   1451 const char *
   1452 trim_filename (const char *name)
   1453 {
   1454   static const char this_file[] = __FILE__;
   1455   const char *p = name, *q = this_file;
   1456 
   1457   /* First skip any "../" in each filename.  This allows us to give a proper
   1458      reference to a file in a subdirectory.  */
   1459   while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
   1460     p += 3;
   1461 
   1462   while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
   1463     q += 3;
   1464 
   1465   /* Now skip any parts the two filenames have in common.  */
   1466   while (*p == *q && *p != 0 && *q != 0)
   1467     p++, q++;
   1468 
   1469   /* Now go backwards until the previous directory separator.  */
   1470   while (p > name && !IS_DIR_SEPARATOR (p[-1]))
   1471     p--;
   1472 
   1473   return p;
   1474 }
   1475 
   1476 /* Standard error reporting routines in increasing order of severity.
   1478    All of these take arguments like printf.  */
   1479 
   1480 /* Text to be emitted verbatim to the error message stream; this
   1481    produces no prefix and disables line-wrapping.  Use rarely.  */
   1482 void
   1483 verbatim (const char *gmsgid, ...)
   1484 {
   1485   text_info text;
   1486   va_list ap;
   1487 
   1488   va_start (ap, gmsgid);
   1489   text.err_no = errno;
   1490   text.args_ptr = &ap;
   1491   text.format_spec = _(gmsgid);
   1492   text.x_data = NULL;
   1493   pp_format_verbatim (global_dc->printer, &text);
   1494   pp_newline_and_flush (global_dc->printer);
   1495   va_end (ap);
   1496 }
   1497 
   1498 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT.  */
   1499 void
   1500 diagnostic_append_note (diagnostic_context *context,
   1501                         location_t location,
   1502                         const char * gmsgid, ...)
   1503 {
   1504   diagnostic_info diagnostic;
   1505   va_list ap;
   1506   rich_location richloc (line_table, location);
   1507 
   1508   va_start (ap, gmsgid);
   1509   diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
   1510   if (context->inhibit_notes_p)
   1511     {
   1512       va_end (ap);
   1513       return;
   1514     }
   1515   char *saved_prefix = pp_take_prefix (context->printer);
   1516   pp_set_prefix (context->printer,
   1517                  diagnostic_build_prefix (context, &diagnostic));
   1518   pp_format (context->printer, &diagnostic.message);
   1519   pp_output_formatted_text (context->printer);
   1520   pp_destroy_prefix (context->printer);
   1521   pp_set_prefix (context->printer, saved_prefix);
   1522   pp_newline (context->printer);
   1523   diagnostic_show_locus (context, &richloc, DK_NOTE);
   1524   va_end (ap);
   1525 }
   1526 
   1527 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
   1528    permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
   1529    and internal_error_no_backtrace, as documented and defined below.  */
   1530 static bool
   1531 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
   1532 		 int opt, const char *gmsgid,
   1533 		 va_list *ap, diagnostic_t kind)
   1534 {
   1535   diagnostic_info diagnostic;
   1536   if (kind == DK_PERMERROR)
   1537     {
   1538       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
   1539 			   permissive_error_kind (global_dc));
   1540       diagnostic.option_index = permissive_error_option (global_dc);
   1541     }
   1542   else
   1543     {
   1544       diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
   1545       if (kind == DK_WARNING || kind == DK_PEDWARN)
   1546 	diagnostic.option_index = opt;
   1547     }
   1548   diagnostic.metadata = metadata;
   1549   return diagnostic_report_diagnostic (global_dc, &diagnostic);
   1550 }
   1551 
   1552 /* Implement inform_n, warning_n, and error_n, as documented and
   1553    defined below.  */
   1554 static bool
   1555 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
   1556 		   int opt, unsigned HOST_WIDE_INT n,
   1557 		   const char *singular_gmsgid,
   1558 		   const char *plural_gmsgid,
   1559 		   va_list *ap, diagnostic_t kind)
   1560 {
   1561   diagnostic_info diagnostic;
   1562   unsigned long gtn;
   1563 
   1564   if (sizeof n <= sizeof gtn)
   1565     gtn = n;
   1566   else
   1567     /* Use the largest number ngettext can handle, otherwise
   1568        preserve the six least significant decimal digits for
   1569        languages where the plural form depends on them.  */
   1570     gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
   1571 
   1572   const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
   1573   diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
   1574   if (kind == DK_WARNING)
   1575     diagnostic.option_index = opt;
   1576   diagnostic.metadata = metadata;
   1577   return diagnostic_report_diagnostic (global_dc, &diagnostic);
   1578 }
   1579 
   1580 /* Wrapper around diagnostic_impl taking a variable argument list.  */
   1581 
   1582 bool
   1583 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
   1584 		 const char *gmsgid, ...)
   1585 {
   1586   auto_diagnostic_group d;
   1587   va_list ap;
   1588   va_start (ap, gmsgid);
   1589   rich_location richloc (line_table, location);
   1590   bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
   1591   va_end (ap);
   1592   return ret;
   1593 }
   1594 
   1595 /* As above, but for rich_location *.  */
   1596 
   1597 bool
   1598 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
   1599 		 const char *gmsgid, ...)
   1600 {
   1601   auto_diagnostic_group d;
   1602   va_list ap;
   1603   va_start (ap, gmsgid);
   1604   bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
   1605   va_end (ap);
   1606   return ret;
   1607 }
   1608 
   1609 /* Wrapper around diagnostic_impl taking a va_list parameter.  */
   1610 
   1611 bool
   1612 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
   1613 			const char *gmsgid, va_list *ap)
   1614 {
   1615   rich_location richloc (line_table, location);
   1616   return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
   1617 }
   1618 
   1619 /* An informative note at LOCATION.  Use this for additional details on an error
   1620    message.  */
   1621 void
   1622 inform (location_t location, const char *gmsgid, ...)
   1623 {
   1624   auto_diagnostic_group d;
   1625   va_list ap;
   1626   va_start (ap, gmsgid);
   1627   rich_location richloc (line_table, location);
   1628   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
   1629   va_end (ap);
   1630 }
   1631 
   1632 /* Same as "inform" above, but at RICHLOC.  */
   1633 void
   1634 inform (rich_location *richloc, const char *gmsgid, ...)
   1635 {
   1636   gcc_assert (richloc);
   1637 
   1638   auto_diagnostic_group d;
   1639   va_list ap;
   1640   va_start (ap, gmsgid);
   1641   diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
   1642   va_end (ap);
   1643 }
   1644 
   1645 /* An informative note at LOCATION.  Use this for additional details on an
   1646    error message.  */
   1647 void
   1648 inform_n (location_t location, unsigned HOST_WIDE_INT n,
   1649 	  const char *singular_gmsgid, const char *plural_gmsgid, ...)
   1650 {
   1651   va_list ap;
   1652   va_start (ap, plural_gmsgid);
   1653   auto_diagnostic_group d;
   1654   rich_location richloc (line_table, location);
   1655   diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
   1656 		     &ap, DK_NOTE);
   1657   va_end (ap);
   1658 }
   1659 
   1660 /* A warning at INPUT_LOCATION.  Use this for code which is correct according
   1661    to the relevant language specification but is likely to be buggy anyway.
   1662    Returns true if the warning was printed, false if it was inhibited.  */
   1663 bool
   1664 warning (int opt, const char *gmsgid, ...)
   1665 {
   1666   auto_diagnostic_group d;
   1667   va_list ap;
   1668   va_start (ap, gmsgid);
   1669   rich_location richloc (line_table, input_location);
   1670   bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
   1671   va_end (ap);
   1672   return ret;
   1673 }
   1674 
   1675 /* A warning at LOCATION.  Use this for code which is correct according to the
   1676    relevant language specification but is likely to be buggy anyway.
   1677    Returns true if the warning was printed, false if it was inhibited.  */
   1678 
   1679 bool
   1680 warning_at (location_t location, int opt, const char *gmsgid, ...)
   1681 {
   1682   auto_diagnostic_group d;
   1683   va_list ap;
   1684   va_start (ap, gmsgid);
   1685   rich_location richloc (line_table, location);
   1686   bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
   1687   va_end (ap);
   1688   return ret;
   1689 }
   1690 
   1691 /* Same as "warning at" above, but using RICHLOC.  */
   1692 
   1693 bool
   1694 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
   1695 {
   1696   gcc_assert (richloc);
   1697 
   1698   auto_diagnostic_group d;
   1699   va_list ap;
   1700   va_start (ap, gmsgid);
   1701   bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
   1702   va_end (ap);
   1703   return ret;
   1704 }
   1705 
   1706 /* Same as "warning at" above, but using METADATA.  */
   1707 
   1708 bool
   1709 warning_meta (rich_location *richloc,
   1710 	      const diagnostic_metadata &metadata,
   1711 	      int opt, const char *gmsgid, ...)
   1712 {
   1713   gcc_assert (richloc);
   1714 
   1715   auto_diagnostic_group d;
   1716   va_list ap;
   1717   va_start (ap, gmsgid);
   1718   bool ret
   1719     = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
   1720 		       DK_WARNING);
   1721   va_end (ap);
   1722   return ret;
   1723 }
   1724 
   1725 /* Same as warning_n plural variant below, but using RICHLOC.  */
   1726 
   1727 bool
   1728 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
   1729 	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
   1730 {
   1731   gcc_assert (richloc);
   1732 
   1733   auto_diagnostic_group d;
   1734   va_list ap;
   1735   va_start (ap, plural_gmsgid);
   1736   bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
   1737 				singular_gmsgid, plural_gmsgid,
   1738 				&ap, DK_WARNING);
   1739   va_end (ap);
   1740   return ret;
   1741 }
   1742 
   1743 /* A warning at LOCATION.  Use this for code which is correct according to the
   1744    relevant language specification but is likely to be buggy anyway.
   1745    Returns true if the warning was printed, false if it was inhibited.  */
   1746 
   1747 bool
   1748 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
   1749 	   const char *singular_gmsgid, const char *plural_gmsgid, ...)
   1750 {
   1751   auto_diagnostic_group d;
   1752   va_list ap;
   1753   va_start (ap, plural_gmsgid);
   1754   rich_location richloc (line_table, location);
   1755   bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
   1756 				singular_gmsgid, plural_gmsgid,
   1757 				&ap, DK_WARNING);
   1758   va_end (ap);
   1759   return ret;
   1760 }
   1761 
   1762 /* A "pedantic" warning at LOCATION: issues a warning unless
   1763    -pedantic-errors was given on the command line, in which case it
   1764    issues an error.  Use this for diagnostics required by the relevant
   1765    language standard, if you have chosen not to make them errors.
   1766 
   1767    Note that these diagnostics are issued independent of the setting
   1768    of the -Wpedantic command-line switch.  To get a warning enabled
   1769    only with that switch, use either "if (pedantic) pedwarn
   1770    (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)".  To get a
   1771    pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
   1772 
   1773    Returns true if the warning was printed, false if it was inhibited.  */
   1774 
   1775 bool
   1776 pedwarn (location_t location, int opt, const char *gmsgid, ...)
   1777 {
   1778   auto_diagnostic_group d;
   1779   va_list ap;
   1780   va_start (ap, gmsgid);
   1781   rich_location richloc (line_table, location);
   1782   bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
   1783   va_end (ap);
   1784   return ret;
   1785 }
   1786 
   1787 /* Same as pedwarn above, but using RICHLOC.  */
   1788 
   1789 bool
   1790 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
   1791 {
   1792   gcc_assert (richloc);
   1793 
   1794   auto_diagnostic_group d;
   1795   va_list ap;
   1796   va_start (ap, gmsgid);
   1797   bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
   1798   va_end (ap);
   1799   return ret;
   1800 }
   1801 
   1802 /* A "permissive" error at LOCATION: issues an error unless
   1803    -fpermissive was given on the command line, in which case it issues
   1804    a warning.  Use this for things that really should be errors but we
   1805    want to support legacy code.
   1806 
   1807    Returns true if the warning was printed, false if it was inhibited.  */
   1808 
   1809 bool
   1810 permerror (location_t location, const char *gmsgid, ...)
   1811 {
   1812   auto_diagnostic_group d;
   1813   va_list ap;
   1814   va_start (ap, gmsgid);
   1815   rich_location richloc (line_table, location);
   1816   bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
   1817   va_end (ap);
   1818   return ret;
   1819 }
   1820 
   1821 /* Same as "permerror" above, but at RICHLOC.  */
   1822 
   1823 bool
   1824 permerror (rich_location *richloc, const char *gmsgid, ...)
   1825 {
   1826   gcc_assert (richloc);
   1827 
   1828   auto_diagnostic_group d;
   1829   va_list ap;
   1830   va_start (ap, gmsgid);
   1831   bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
   1832   va_end (ap);
   1833   return ret;
   1834 }
   1835 
   1836 /* A hard error: the code is definitely ill-formed, and an object file
   1837    will not be produced.  */
   1838 void
   1839 error (const char *gmsgid, ...)
   1840 {
   1841   auto_diagnostic_group d;
   1842   va_list ap;
   1843   va_start (ap, gmsgid);
   1844   rich_location richloc (line_table, input_location);
   1845   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
   1846   va_end (ap);
   1847 }
   1848 
   1849 /* A hard error: the code is definitely ill-formed, and an object file
   1850    will not be produced.  */
   1851 void
   1852 error_n (location_t location, unsigned HOST_WIDE_INT n,
   1853 	 const char *singular_gmsgid, const char *plural_gmsgid, ...)
   1854 {
   1855   auto_diagnostic_group d;
   1856   va_list ap;
   1857   va_start (ap, plural_gmsgid);
   1858   rich_location richloc (line_table, location);
   1859   diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
   1860 		     &ap, DK_ERROR);
   1861   va_end (ap);
   1862 }
   1863 
   1864 /* Same as above, but use location LOC instead of input_location.  */
   1865 void
   1866 error_at (location_t loc, const char *gmsgid, ...)
   1867 {
   1868   auto_diagnostic_group d;
   1869   va_list ap;
   1870   va_start (ap, gmsgid);
   1871   rich_location richloc (line_table, loc);
   1872   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
   1873   va_end (ap);
   1874 }
   1875 
   1876 /* Same as above, but use RICH_LOC.  */
   1877 
   1878 void
   1879 error_at (rich_location *richloc, const char *gmsgid, ...)
   1880 {
   1881   gcc_assert (richloc);
   1882 
   1883   auto_diagnostic_group d;
   1884   va_list ap;
   1885   va_start (ap, gmsgid);
   1886   diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
   1887   va_end (ap);
   1888 }
   1889 
   1890 /* "Sorry, not implemented."  Use for a language feature which is
   1891    required by the relevant specification but not implemented by GCC.
   1892    An object file will not be produced.  */
   1893 void
   1894 sorry (const char *gmsgid, ...)
   1895 {
   1896   auto_diagnostic_group d;
   1897   va_list ap;
   1898   va_start (ap, gmsgid);
   1899   rich_location richloc (line_table, input_location);
   1900   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
   1901   va_end (ap);
   1902 }
   1903 
   1904 /* Same as above, but use location LOC instead of input_location.  */
   1905 void
   1906 sorry_at (location_t loc, const char *gmsgid, ...)
   1907 {
   1908   auto_diagnostic_group d;
   1909   va_list ap;
   1910   va_start (ap, gmsgid);
   1911   rich_location richloc (line_table, loc);
   1912   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
   1913   va_end (ap);
   1914 }
   1915 
   1916 /* Return true if an error or a "sorry" has been seen.  Various
   1917    processing is disabled after errors.  */
   1918 bool
   1919 seen_error (void)
   1920 {
   1921   return errorcount || sorrycount;
   1922 }
   1923 
   1924 /* An error which is severe enough that we make no attempt to
   1925    continue.  Do not use this for internal consistency checks; that's
   1926    internal_error.  Use of this function should be rare.  */
   1927 void
   1928 fatal_error (location_t loc, const char *gmsgid, ...)
   1929 {
   1930   auto_diagnostic_group d;
   1931   va_list ap;
   1932   va_start (ap, gmsgid);
   1933   rich_location richloc (line_table, loc);
   1934   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
   1935   va_end (ap);
   1936 
   1937   gcc_unreachable ();
   1938 }
   1939 
   1940 /* An internal consistency check has failed.  We make no attempt to
   1941    continue.  Note that unless there is debugging value to be had from
   1942    a more specific message, or some other good reason, you should use
   1943    abort () instead of calling this function directly.  */
   1944 void
   1945 internal_error (const char *gmsgid, ...)
   1946 {
   1947   auto_diagnostic_group d;
   1948   va_list ap;
   1949   va_start (ap, gmsgid);
   1950   rich_location richloc (line_table, input_location);
   1951   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
   1952   va_end (ap);
   1953 
   1954   gcc_unreachable ();
   1955 }
   1956 
   1957 /* Like internal_error, but no backtrace will be printed.  Used when
   1958    the internal error does not happen at the current location, but happened
   1959    somewhere else.  */
   1960 void
   1961 internal_error_no_backtrace (const char *gmsgid, ...)
   1962 {
   1963   auto_diagnostic_group d;
   1964   va_list ap;
   1965   va_start (ap, gmsgid);
   1966   rich_location richloc (line_table, input_location);
   1967   diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
   1968   va_end (ap);
   1969 
   1970   gcc_unreachable ();
   1971 }
   1972 
   1973 /* Special case error functions.  Most are implemented in terms of the
   1975    above, or should be.  */
   1976 
   1977 /* Print a diagnostic MSGID on FILE.  This is just fprintf, except it
   1978    runs its second argument through gettext.  */
   1979 void
   1980 fnotice (FILE *file, const char *cmsgid, ...)
   1981 {
   1982   va_list ap;
   1983 
   1984   va_start (ap, cmsgid);
   1985   vfprintf (file, _(cmsgid), ap);
   1986   va_end (ap);
   1987 }
   1988 
   1989 /* Inform the user that an error occurred while trying to report some
   1990    other error.  This indicates catastrophic internal inconsistencies,
   1991    so give up now.  But do try to flush out the previous error.
   1992    This mustn't use internal_error, that will cause infinite recursion.  */
   1993 
   1994 static void
   1995 error_recursion (diagnostic_context *context)
   1996 {
   1997   if (context->lock < 3)
   1998     pp_newline_and_flush (context->printer);
   1999 
   2000   fnotice (stderr,
   2001 	   "internal compiler error: error reporting routines re-entered.\n");
   2002 
   2003   /* Call diagnostic_action_after_output to get the "please submit a bug
   2004      report" message.  */
   2005   diagnostic_action_after_output (context, DK_ICE);
   2006 
   2007   /* Do not use gcc_unreachable here; that goes through internal_error
   2008      and therefore would cause infinite recursion.  */
   2009   real_abort ();
   2010 }
   2011 
   2012 /* Report an internal compiler error in a friendly manner.  This is
   2013    the function that gets called upon use of abort() in the source
   2014    code generally, thanks to a special macro.  */
   2015 
   2016 void
   2017 fancy_abort (const char *file, int line, const char *function)
   2018 {
   2019   /* If fancy_abort is called before the diagnostic subsystem is initialized,
   2020      internal_error will crash internally in a way that prevents a
   2021      useful message reaching the user.
   2022      This can happen with libgccjit in the case of gcc_assert failures
   2023      that occur outside of the libgccjit mutex that guards the rest of
   2024      gcc's state, including global_dc (when global_dc may not be
   2025      initialized yet, or might be in use by another thread).
   2026      Handle such cases as gracefully as possible by falling back to a
   2027      minimal abort handler that only relies on i18n.  */
   2028   if (global_dc->printer == NULL)
   2029     {
   2030       /* Print the error message.  */
   2031       fnotice (stderr, diagnostic_kind_text[DK_ICE]);
   2032       fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
   2033       fputc ('\n', stderr);
   2034 
   2035       /* Attempt to print a backtrace.  */
   2036       struct backtrace_state *state
   2037 	= backtrace_create_state (NULL, 0, bt_err_callback, NULL);
   2038       int count = 0;
   2039       if (state != NULL)
   2040 	backtrace_full (state, 2, bt_callback, bt_err_callback,
   2041 			(void *) &count);
   2042 
   2043       /* We can't call warn_if_plugins or emergency_dump_function as these
   2044 	 rely on GCC state that might not be initialized, or might be in
   2045 	 use by another thread.  */
   2046 
   2047       /* Abort the process.  */
   2048       real_abort ();
   2049     }
   2050 
   2051   internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
   2052 }
   2053 
   2054 /* class auto_diagnostic_group.  */
   2055 
   2056 /* Constructor: "push" this group into global_dc.  */
   2057 
   2058 auto_diagnostic_group::auto_diagnostic_group ()
   2059 {
   2060   global_dc->diagnostic_group_nesting_depth++;
   2061 }
   2062 
   2063 /* Destructor: "pop" this group from global_dc.  */
   2064 
   2065 auto_diagnostic_group::~auto_diagnostic_group ()
   2066 {
   2067   if (--global_dc->diagnostic_group_nesting_depth == 0)
   2068     {
   2069       /* Handle the case where we've popped the final diagnostic group.
   2070 	 If any diagnostics were emitted, give the context a chance
   2071 	 to do something.  */
   2072       if (global_dc->diagnostic_group_emission_count > 0)
   2073 	{
   2074 	  if (global_dc->end_group_cb)
   2075 	    global_dc->end_group_cb (global_dc);
   2076 	}
   2077       global_dc->diagnostic_group_emission_count = 0;
   2078     }
   2079 }
   2080 
   2081 /* Implementation of diagnostic_path::num_events vfunc for
   2082    simple_diagnostic_path: simply get the number of events in the vec.  */
   2083 
   2084 unsigned
   2085 simple_diagnostic_path::num_events () const
   2086 {
   2087   return m_events.length ();
   2088 }
   2089 
   2090 /* Implementation of diagnostic_path::get_event vfunc for
   2091    simple_diagnostic_path: simply return the event in the vec.  */
   2092 
   2093 const diagnostic_event &
   2094 simple_diagnostic_path::get_event (int idx) const
   2095 {
   2096   return *m_events[idx];
   2097 }
   2098 
   2099 /* Add an event to this path at LOC within function FNDECL at
   2100    stack depth DEPTH.
   2101 
   2102    Use m_context's printer to format FMT, as the text of the new
   2103    event.
   2104 
   2105    Return the id of the new event.  */
   2106 
   2107 diagnostic_event_id_t
   2108 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
   2109 				   const char *fmt, ...)
   2110 {
   2111   pretty_printer *pp = m_event_pp;
   2112   pp_clear_output_area (pp);
   2113 
   2114   text_info ti;
   2115   rich_location rich_loc (line_table, UNKNOWN_LOCATION);
   2116 
   2117   va_list ap;
   2118 
   2119   va_start (ap, fmt);
   2120 
   2121   ti.format_spec = _(fmt);
   2122   ti.args_ptr = &ap;
   2123   ti.err_no = 0;
   2124   ti.x_data = NULL;
   2125   ti.m_richloc = &rich_loc;
   2126 
   2127   pp_format (pp, &ti);
   2128   pp_output_formatted_text (pp);
   2129 
   2130   va_end (ap);
   2131 
   2132   simple_diagnostic_event *new_event
   2133     = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
   2134   m_events.safe_push (new_event);
   2135 
   2136   pp_clear_output_area (pp);
   2137 
   2138   return diagnostic_event_id_t (m_events.length () - 1);
   2139 }
   2140 
   2141 /* struct simple_diagnostic_event.  */
   2142 
   2143 /* simple_diagnostic_event's ctor.  */
   2144 
   2145 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
   2146 						  tree fndecl,
   2147 						  int depth,
   2148 						  const char *desc)
   2149 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
   2150 {
   2151 }
   2152 
   2153 /* simple_diagnostic_event's dtor.  */
   2154 
   2155 simple_diagnostic_event::~simple_diagnostic_event ()
   2156 {
   2157   free (m_desc);
   2158 }
   2159 
   2160 /* Print PATH by emitting a dummy "note" associated with it.  */
   2161 
   2162 DEBUG_FUNCTION
   2163 void debug (diagnostic_path *path)
   2164 {
   2165   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2166   richloc.set_path (path);
   2167   inform (&richloc, "debug path");
   2168 }
   2169 
   2170 /* Really call the system 'abort'.  This has to go right at the end of
   2171    this file, so that there are no functions after it that call abort
   2172    and get the system abort instead of our macro.  */
   2173 #undef abort
   2174 static void
   2175 real_abort (void)
   2176 {
   2177   abort ();
   2178 }
   2179 
   2180 #if CHECKING_P
   2181 
   2182 namespace selftest {
   2183 
   2184 /* Helper function for test_print_escaped_string.  */
   2185 
   2186 static void
   2187 assert_print_escaped_string (const location &loc, const char *expected_output,
   2188 			     const char *input)
   2189 {
   2190   pretty_printer pp;
   2191   print_escaped_string (&pp, input);
   2192   ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
   2193 }
   2194 
   2195 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
   2196     assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
   2197 
   2198 /* Tests of print_escaped_string.  */
   2199 
   2200 static void
   2201 test_print_escaped_string ()
   2202 {
   2203   /* Empty string.  */
   2204   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
   2205 
   2206   /* Non-empty string.  */
   2207   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
   2208 
   2209   /* Various things that need to be escaped:  */
   2210   /* Backslash.  */
   2211   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
   2212 				     "before\\after");
   2213   /* Tab.  */
   2214   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
   2215 				     "before\tafter");
   2216   /* Newline.  */
   2217   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
   2218 				     "before\nafter");
   2219   /* Double quote.  */
   2220   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
   2221 				     "before\"after");
   2222 
   2223   /* Non-printable characters: BEL: '\a': 0x07 */
   2224   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
   2225 				     "before\aafter");
   2226   /* Non-printable characters: vertical tab: '\v': 0x0b */
   2227   ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
   2228 				     "before\vafter");
   2229 }
   2230 
   2231 /* Tests of print_parseable_fixits.  */
   2232 
   2233 /* Verify that print_parseable_fixits emits the empty string if there
   2234    are no fixits.  */
   2235 
   2236 static void
   2237 test_print_parseable_fixits_none ()
   2238 {
   2239   pretty_printer pp;
   2240   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2241 
   2242   print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   2243   ASSERT_STREQ ("", pp_formatted_text (&pp));
   2244 }
   2245 
   2246 /* Verify that print_parseable_fixits does the right thing if there
   2247    is an insertion fixit hint.  */
   2248 
   2249 static void
   2250 test_print_parseable_fixits_insert ()
   2251 {
   2252   pretty_printer pp;
   2253   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2254 
   2255   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
   2256   linemap_line_start (line_table, 5, 100);
   2257   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
   2258   location_t where = linemap_position_for_column (line_table, 10);
   2259   richloc.add_fixit_insert_before (where, "added content");
   2260 
   2261   print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   2262   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
   2263 		pp_formatted_text (&pp));
   2264 }
   2265 
   2266 /* Verify that print_parseable_fixits does the right thing if there
   2267    is an removal fixit hint.  */
   2268 
   2269 static void
   2270 test_print_parseable_fixits_remove ()
   2271 {
   2272   pretty_printer pp;
   2273   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2274 
   2275   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
   2276   linemap_line_start (line_table, 5, 100);
   2277   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
   2278   source_range where;
   2279   where.m_start = linemap_position_for_column (line_table, 10);
   2280   where.m_finish = linemap_position_for_column (line_table, 20);
   2281   richloc.add_fixit_remove (where);
   2282 
   2283   print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   2284   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
   2285 		pp_formatted_text (&pp));
   2286 }
   2287 
   2288 /* Verify that print_parseable_fixits does the right thing if there
   2289    is an replacement fixit hint.  */
   2290 
   2291 static void
   2292 test_print_parseable_fixits_replace ()
   2293 {
   2294   pretty_printer pp;
   2295   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2296 
   2297   linemap_add (line_table, LC_ENTER, false, "test.c", 0);
   2298   linemap_line_start (line_table, 5, 100);
   2299   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
   2300   source_range where;
   2301   where.m_start = linemap_position_for_column (line_table, 10);
   2302   where.m_finish = linemap_position_for_column (line_table, 20);
   2303   richloc.add_fixit_replace (where, "replacement");
   2304 
   2305   print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
   2306   ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
   2307 		pp_formatted_text (&pp));
   2308 }
   2309 
   2310 /* Verify that print_parseable_fixits correctly handles
   2311    DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN.  */
   2312 
   2313 static void
   2314 test_print_parseable_fixits_bytes_vs_display_columns ()
   2315 {
   2316   line_table_test ltt;
   2317   rich_location richloc (line_table, UNKNOWN_LOCATION);
   2318 
   2319   /* 1-based byte offsets:     12345677778888999900001234567.  */
   2320   const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
   2321   /* 1-based display cols:     123456[......7-8.....]9012345.  */
   2322   const int tabstop = 8;
   2323 
   2324   temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
   2325   const char *const fname = tmp.get_filename ();
   2326 
   2327   linemap_add (line_table, LC_ENTER, false, fname, 0);
   2328   linemap_line_start (line_table, 1, 100);
   2329   linemap_add (line_table, LC_LEAVE, false, NULL, 0);
   2330   source_range where;
   2331   where.m_start = linemap_position_for_column (line_table, 12);
   2332   where.m_finish = linemap_position_for_column (line_table, 17);
   2333   richloc.add_fixit_replace (where, "color");
   2334 
   2335   /* Escape fname.  */
   2336   pretty_printer tmp_pp;
   2337   print_escaped_string (&tmp_pp, fname);
   2338   char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
   2339 
   2340   const int buf_len = strlen (escaped_fname) + 100;
   2341   char *const expected = XNEWVEC (char, buf_len);
   2342 
   2343   {
   2344     pretty_printer pp;
   2345     print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
   2346 			    tabstop);
   2347     snprintf (expected, buf_len,
   2348 	      "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
   2349     ASSERT_STREQ (expected, pp_formatted_text (&pp));
   2350   }
   2351   {
   2352     pretty_printer pp;
   2353     print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
   2354 			    tabstop);
   2355     snprintf (expected, buf_len,
   2356 	      "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
   2357     ASSERT_STREQ (expected, pp_formatted_text (&pp));
   2358   }
   2359 
   2360   XDELETEVEC (expected);
   2361   free (escaped_fname);
   2362 }
   2363 
   2364 /* Verify that
   2365      diagnostic_get_location_text (..., SHOW_COLUMN)
   2366    generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
   2367    colorization disabled.  */
   2368 
   2369 static void
   2370 assert_location_text (const char *expected_loc_text,
   2371 		      const char *filename, int line, int column,
   2372 		      bool show_column,
   2373 		      int origin = 1,
   2374 		      enum diagnostics_column_unit column_unit
   2375 			= DIAGNOSTICS_COLUMN_UNIT_BYTE)
   2376 {
   2377   test_diagnostic_context dc;
   2378   dc.show_column = show_column;
   2379   dc.column_unit = column_unit;
   2380   dc.column_origin = origin;
   2381 
   2382   expanded_location xloc;
   2383   xloc.file = filename;
   2384   xloc.line = line;
   2385   xloc.column = column;
   2386   xloc.data = NULL;
   2387   xloc.sysp = false;
   2388 
   2389   char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
   2390   ASSERT_STREQ (expected_loc_text, actual_loc_text);
   2391   free (actual_loc_text);
   2392 }
   2393 
   2394 /* Verify that diagnostic_get_location_text works as expected.  */
   2395 
   2396 static void
   2397 test_diagnostic_get_location_text ()
   2398 {
   2399   const char *old_progname = progname;
   2400   progname = "PROGNAME";
   2401   assert_location_text ("PROGNAME:", NULL, 0, 0, true);
   2402   assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
   2403   assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
   2404   assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
   2405   assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
   2406   for (int origin = 0; origin != 2; ++origin)
   2407     assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
   2408   assert_location_text ("foo.c:", "foo.c", 0, 10, true);
   2409   assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
   2410   assert_location_text ("foo.c:", "foo.c", 0, 10, false);
   2411 
   2412   maybe_line_and_column (INT_MAX, INT_MAX);
   2413   maybe_line_and_column (INT_MIN, INT_MIN);
   2414 
   2415   {
   2416     /* In order to test display columns vs byte columns, we need to create a
   2417        file for location_get_source_line() to read.  */
   2418 
   2419     const char *const content = "smile \xf0\x9f\x98\x82\n";
   2420     const int line_bytes = strlen (content) - 1;
   2421     const int def_tabstop = 8;
   2422     const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
   2423     const int display_width = cpp_display_width (content, line_bytes, policy);
   2424     ASSERT_EQ (line_bytes - 2, display_width);
   2425     temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
   2426     const char *const fname = tmp.get_filename ();
   2427     const int buf_len = strlen (fname) + 16;
   2428     char *const expected = XNEWVEC (char, buf_len);
   2429 
   2430     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
   2431     assert_location_text (expected, fname, 1, line_bytes, true,
   2432 			  1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
   2433 
   2434     snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
   2435     assert_location_text (expected, fname, 1, line_bytes, true,
   2436 			  0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
   2437 
   2438     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
   2439     assert_location_text (expected, fname, 1, line_bytes, true,
   2440 			  1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
   2441 
   2442     snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
   2443     assert_location_text (expected, fname, 1, line_bytes, true,
   2444 			  0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
   2445 
   2446     XDELETEVEC (expected);
   2447   }
   2448 
   2449 
   2450   progname = old_progname;
   2451 }
   2452 
   2453 /* Selftest for num_digits.  */
   2454 
   2455 static void
   2456 test_num_digits ()
   2457 {
   2458   ASSERT_EQ (1, num_digits (0));
   2459   ASSERT_EQ (1, num_digits (9));
   2460   ASSERT_EQ (2, num_digits (10));
   2461   ASSERT_EQ (2, num_digits (99));
   2462   ASSERT_EQ (3, num_digits (100));
   2463   ASSERT_EQ (3, num_digits (999));
   2464   ASSERT_EQ (4, num_digits (1000));
   2465   ASSERT_EQ (4, num_digits (9999));
   2466   ASSERT_EQ (5, num_digits (10000));
   2467   ASSERT_EQ (5, num_digits (99999));
   2468   ASSERT_EQ (6, num_digits (100000));
   2469   ASSERT_EQ (6, num_digits (999999));
   2470   ASSERT_EQ (7, num_digits (1000000));
   2471   ASSERT_EQ (7, num_digits (9999999));
   2472   ASSERT_EQ (8, num_digits (10000000));
   2473   ASSERT_EQ (8, num_digits (99999999));
   2474 }
   2475 
   2476 /* Run all of the selftests within this file.  */
   2477 
   2478 void
   2479 c_diagnostic_cc_tests ()
   2480 {
   2481   test_print_escaped_string ();
   2482   test_print_parseable_fixits_none ();
   2483   test_print_parseable_fixits_insert ();
   2484   test_print_parseable_fixits_remove ();
   2485   test_print_parseable_fixits_replace ();
   2486   test_print_parseable_fixits_bytes_vs_display_columns ();
   2487   test_diagnostic_get_location_text ();
   2488   test_num_digits ();
   2489 
   2490 }
   2491 
   2492 } // namespace selftest
   2493 
   2494 #endif /* #if CHECKING_P */
   2495 
   2496 #if __GNUC__ >= 10
   2497 #  pragma GCC diagnostic pop
   2498 #endif
   2499