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
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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.  */
63static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
64			     int, const char *,
65			     va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
66static 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
71static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
72static void real_abort (void) ATTRIBUTE_NORETURN;
73
74/* Name of program invoked, sans directories.  */
75
76const char *progname;
77
78/* A diagnostic_context surrogate for stderr.  */
79static diagnostic_context global_diagnostic_context;
80diagnostic_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.  */
84char *
85build_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.  */
98char *
99file_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.  */
112int
113get_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.  */
133void
134diagnostic_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
149static void
150default_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.  */
170void
171diagnostic_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
234void
235diagnostic_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
260void
261diagnostic_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
287void
288diagnostic_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.  */
313void
314diagnostic_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.  */
331void
332diagnostic_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
340static 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
350const char *
351diagnostic_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
359static const char *
360maybe_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
378static char *
379diagnostic_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.  */
397char *
398diagnostic_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
432static 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
442static int
443bt_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
509static void
510bt_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
526void
527diagnostic_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.  */
549void
550diagnostic_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
613static bool
614last_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
623static void
624set_last_module (diagnostic_context *context, const line_map_ordinary *map)
625{
626  context->last_module = map;
627}
628
629void
630diagnostic_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
682void
683diagnostic_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
697bool
698diagnostic_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
711void
712default_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
720void
721default_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
730void
731default_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.  */
747diagnostic_t
748diagnostic_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.  */
802void
803diagnostic_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.  */
811void
812diagnostic_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
835static void
836print_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
880static void
881print_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
917static diagnostic_t
918update_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
959static char *
960get_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
971static void
972print_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
1005static void
1006print_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
1047bool
1048diagnostic_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
1188int
1189num_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
1212const char *
1213trim_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.  */
1242void
1243verbatim (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.  */
1259void
1260diagnostic_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.  */
1290static bool
1291diagnostic_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.  */
1314static bool
1315diagnostic_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
1342bool
1343emit_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
1357bool
1358emit_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
1371bool
1372emit_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.  */
1381void
1382inform (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.  */
1393void
1394inform (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.  */
1407void
1408inform_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.  */
1423bool
1424warning (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
1439bool
1440warning_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
1453bool
1454warning_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
1468bool
1469warning_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
1487bool
1488warning_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
1507bool
1508warning_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
1535bool
1536pedwarn (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
1549bool
1550pedwarn (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
1569bool
1570permerror (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
1583bool
1584permerror (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.  */
1598void
1599error (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.  */
1611void
1612error_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.  */
1625void
1626error_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
1638void
1639error_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.  */
1653void
1654sorry (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.  */
1665void
1666sorry_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.  */
1678bool
1679seen_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.  */
1687void
1688fatal_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.  */
1704void
1705internal_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.  */
1720void
1721internal_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.  */
1738void
1739fnotice (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
1753static void
1754error_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
1775void
1776fancy_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
1785auto_diagnostic_group::auto_diagnostic_group ()
1786{
1787  global_dc->diagnostic_group_nesting_depth++;
1788}
1789
1790/* Destructor: "pop" this group from global_dc.  */
1791
1792auto_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
1811unsigned
1812simple_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
1820const diagnostic_event &
1821simple_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
1834diagnostic_event_id_t
1835simple_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
1872simple_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
1882simple_diagnostic_event::~simple_diagnostic_event ()
1883{
1884  free (m_desc);
1885}
1886
1887/* Print PATH by emitting a dummy "note" associated with it.  */
1888
1889DEBUG_FUNCTION
1890void 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
1901static void
1902real_abort (void)
1903{
1904  abort ();
1905}
1906
1907#if CHECKING_P
1908
1909namespace selftest {
1910
1911/* Helper function for test_print_escaped_string.  */
1912
1913static void
1914assert_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
1927static void
1928test_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
1963static void
1964test_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
1976static void
1977test_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
1996static void
1997test_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
2018static void
2019test_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
2042static void
2043assert_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
2064static void
2065test_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
2085static void
2086test_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
2108void
2109diagnostic_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