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