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