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