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