target/112280 - properly guard permute query
[official-gcc.git] / gcc / diagnostic.cc
blobf5411b1ede0d00a24e6dc9f60d3f9ff3d55704c1
1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2024 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
5 This file is part of GCC.
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.
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.
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/>. */
22 /* This file implements the language independent aspect of diagnostic
23 message module. */
25 #include "config.h"
26 #define INCLUDE_VECTOR
27 #include "system.h"
28 #include "coretypes.h"
29 #include "version.h"
30 #include "demangle.h"
31 #include "intl.h"
32 #include "backtrace.h"
33 #include "diagnostic.h"
34 #include "diagnostic-color.h"
35 #include "diagnostic-url.h"
36 #include "diagnostic-metadata.h"
37 #include "diagnostic-path.h"
38 #include "diagnostic-client-data-hooks.h"
39 #include "diagnostic-diagram.h"
40 #include "edit-context.h"
41 #include "selftest.h"
42 #include "selftest-diagnostic.h"
43 #include "opts.h"
44 #include "cpplib.h"
45 #include "text-art/theme.h"
46 #include "pretty-print-urlifier.h"
48 #ifdef HAVE_TERMIOS_H
49 # include <termios.h>
50 #endif
52 #ifdef GWINSZ_IN_SYS_IOCTL
53 # include <sys/ioctl.h>
54 #endif
56 /* Disable warnings about quoting issues in the pp_xxx calls below
57 that (intentionally) don't follow GCC diagnostic conventions. */
58 #if __GNUC__ >= 10
59 # pragma GCC diagnostic push
60 # pragma GCC diagnostic ignored "-Wformat-diag"
61 #endif
63 #define pedantic_warning_kind(DC) \
64 ((DC)->m_pedantic_errors ? DK_ERROR : DK_WARNING)
65 #define permissive_error_kind(DC) ((DC)->m_permissive ? DK_WARNING : DK_ERROR)
66 #define permissive_error_option(DC) ((DC)->m_opt_permissive)
68 /* Prototypes. */
69 static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
70 int, const char *,
71 va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
72 static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
73 int, unsigned HOST_WIDE_INT,
74 const char *, const char *, va_list *,
75 diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
77 static void real_abort (void) ATTRIBUTE_NORETURN;
79 /* Name of program invoked, sans directories. */
81 const char *progname;
83 /* A diagnostic_context surrogate for stderr. */
84 static diagnostic_context global_diagnostic_context;
85 diagnostic_context *global_dc = &global_diagnostic_context;
87 /* Return a malloc'd string containing MSG formatted a la printf. The
88 caller is responsible for freeing the memory. */
89 char *
90 build_message_string (const char *msg, ...)
92 char *str;
93 va_list ap;
95 va_start (ap, msg);
96 str = xvasprintf (msg, ap);
97 va_end (ap);
99 return str;
102 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
103 char *
104 file_name_as_prefix (diagnostic_context *context, const char *f)
106 const char *locus_cs
107 = colorize_start (pp_show_color (context->printer), "locus");
108 const char *locus_ce = colorize_stop (pp_show_color (context->printer));
109 return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
114 /* Return the value of the getenv("COLUMNS") as an integer. If the
115 value is not set to a positive integer, use ioctl to get the
116 terminal width. If it fails, return INT_MAX. */
118 get_terminal_width (void)
120 const char * s = getenv ("COLUMNS");
121 if (s != NULL) {
122 int n = atoi (s);
123 if (n > 0)
124 return n;
127 #ifdef TIOCGWINSZ
128 struct winsize w;
129 w.ws_col = 0;
130 if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
131 return w.ws_col;
132 #endif
134 return INT_MAX;
137 /* Set caret_max_width to value. */
138 void
139 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
141 /* One minus to account for the leading empty space. */
142 value = value ? value - 1
143 : (isatty (fileno (pp_buffer (context->printer)->stream))
144 ? get_terminal_width () - 1: INT_MAX);
146 if (value <= 0)
147 value = INT_MAX;
149 context->m_source_printing.max_width = value;
152 void
153 diagnostic_option_classifier::init (int n_opts)
155 m_n_opts = n_opts;
156 m_classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
157 for (int i = 0; i < n_opts; i++)
158 m_classify_diagnostic[i] = DK_UNSPECIFIED;
159 m_push_list = nullptr;
160 m_n_push = 0;
163 void
164 diagnostic_option_classifier::fini ()
166 XDELETEVEC (m_classify_diagnostic);
167 m_classify_diagnostic = nullptr;
168 free (m_push_list);
169 m_n_push = 0;
172 /* Save all diagnostic classifications in a stack. */
174 void
175 diagnostic_option_classifier::push ()
177 m_push_list = (int *) xrealloc (m_push_list, (m_n_push + 1) * sizeof (int));
178 m_push_list[m_n_push ++] = m_n_classification_history;
181 /* Restore the topmost classification set off the stack. If the stack
182 is empty, revert to the state based on command line parameters. */
184 void
185 diagnostic_option_classifier::pop (location_t where)
187 int jump_to;
189 if (m_n_push)
190 jump_to = m_push_list [-- m_n_push];
191 else
192 jump_to = 0;
194 const int i = m_n_classification_history;
195 m_classification_history =
196 (diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
197 * sizeof (diagnostic_classification_change_t));
198 m_classification_history[i].location = where;
199 m_classification_history[i].option = jump_to;
200 m_classification_history[i].kind = DK_POP;
201 m_n_classification_history ++;
204 /* Initialize the diagnostic message outputting machinery. */
206 void
207 diagnostic_context::initialize (int n_opts)
209 /* Allocate a basic pretty-printer. Clients will replace this a
210 much more elaborated pretty-printer if they wish. */
211 this->printer = XNEW (pretty_printer);
212 new (this->printer) pretty_printer ();
214 m_file_cache = new file_cache ();
215 memset (m_diagnostic_count, 0, sizeof m_diagnostic_count);
216 m_warning_as_error_requested = false;
217 m_n_opts = n_opts;
218 m_option_classifier.init (n_opts);
219 m_source_printing.enabled = false;
220 diagnostic_set_caret_max_width (this, pp_line_cutoff (this->printer));
221 for (int i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
222 m_source_printing.caret_chars[i] = '^';
223 m_show_cwe = false;
224 m_show_rules = false;
225 m_path_format = DPF_NONE;
226 m_show_path_depths = false;
227 m_show_option_requested = false;
228 m_abort_on_error = false;
229 m_show_column = false;
230 m_pedantic_errors = false;
231 m_permissive = false;
232 m_opt_permissive = 0;
233 m_fatal_errors = false;
234 m_inhibit_warnings = false;
235 m_warn_system_headers = false;
236 m_max_errors = 0;
237 m_internal_error = nullptr;
238 m_text_callbacks.m_begin_diagnostic = default_diagnostic_starter;
239 m_text_callbacks.m_start_span = default_diagnostic_start_span_fn;
240 m_text_callbacks.m_end_diagnostic = default_diagnostic_finalizer;
241 m_option_callbacks.m_option_enabled_cb = nullptr;
242 m_option_callbacks.m_option_state = nullptr;
243 m_option_callbacks.m_make_option_name_cb = nullptr;
244 m_option_callbacks.m_make_option_url_cb = nullptr;
245 m_urlifier = nullptr;
246 m_last_location = UNKNOWN_LOCATION;
247 m_last_module = nullptr;
248 m_client_aux_data = nullptr;
249 m_lock = 0;
250 m_inhibit_notes_p = false;
251 m_source_printing.colorize_source_p = false;
252 m_source_printing.show_labels_p = false;
253 m_source_printing.show_line_numbers_p = false;
254 m_source_printing.min_margin_width = 0;
255 m_source_printing.show_ruler_p = false;
256 m_report_bug = false;
257 m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
258 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
260 if (!strcmp (var, "fixits-v1"))
261 m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
262 else if (!strcmp (var, "fixits-v2"))
263 m_extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
264 /* Silently ignore unrecognized values. */
266 m_column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
267 m_column_origin = 1;
268 m_tabstop = 8;
269 m_escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
270 m_edit_context_ptr = nullptr;
271 m_diagnostic_groups.m_nesting_depth = 0;
272 m_diagnostic_groups.m_emission_count = 0;
273 m_output_format = new diagnostic_text_output_format (*this);
274 m_set_locations_cb = nullptr;
275 m_ice_handler_cb = nullptr;
276 m_includes_seen = nullptr;
277 m_client_data_hooks = nullptr;
278 m_diagrams.m_theme = nullptr;
280 enum diagnostic_text_art_charset text_art_charset
281 = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI;
282 if (const char *lang = getenv ("LANG"))
284 /* For LANG=C, don't assume the terminal supports anything
285 other than ASCII. */
286 if (!strcmp (lang, "C"))
287 text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII;
289 set_text_art_charset (text_art_charset);
292 /* Maybe initialize the color support. We require clients to do this
293 explicitly, since most clients don't want color. When called
294 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
296 void
297 diagnostic_context::color_init (int value)
299 /* value == -1 is the default value. */
300 if (value < 0)
302 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
303 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
304 otherwise default to -fdiagnostics-color=never, for other
305 values default to that
306 -fdiagnostics-color={never,auto,always}. */
307 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
309 if (!getenv ("GCC_COLORS"))
310 return;
311 value = DIAGNOSTICS_COLOR_AUTO;
313 else
314 value = DIAGNOSTICS_COLOR_DEFAULT;
316 pp_show_color (this->printer)
317 = colorize_init ((diagnostic_color_rule_t) value);
320 /* Initialize URL support within this context based on VALUE,
321 handling "auto". */
323 void
324 diagnostic_context::urls_init (int value)
326 /* value == -1 is the default value. */
327 if (value < 0)
329 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
330 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
331 environment, otherwise default to -fdiagnostics-urls=never,
332 for other values default to that
333 -fdiagnostics-urls={never,auto,always}. */
334 if (DIAGNOSTICS_URLS_DEFAULT == -1)
336 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
337 return;
338 value = DIAGNOSTICS_URL_AUTO;
340 else
341 value = DIAGNOSTICS_URLS_DEFAULT;
344 this->printer->url_format
345 = determine_url_format ((diagnostic_url_rule_t) value);
348 /* Create the file_cache, if not already created, and tell it how to
349 translate files on input. */
350 void
351 diagnostic_context::
352 initialize_input_context (diagnostic_input_charset_callback ccb,
353 bool should_skip_bom)
355 m_file_cache->initialize_input_context (ccb, should_skip_bom);
358 /* Do any cleaning up required after the last diagnostic is emitted. */
360 void
361 diagnostic_context::finish ()
363 delete m_output_format;
364 m_output_format= nullptr;
366 if (m_diagrams.m_theme)
368 delete m_diagrams.m_theme;
369 m_diagrams.m_theme = nullptr;
372 delete m_file_cache;
373 m_file_cache = nullptr;
375 m_option_classifier.fini ();
377 /* diagnostic_context::initialize allocates this->printer using XNEW
378 and placement-new. */
379 this->printer->~pretty_printer ();
380 XDELETE (this->printer);
381 this->printer = nullptr;
383 if (m_edit_context_ptr)
385 delete m_edit_context_ptr;
386 m_edit_context_ptr = nullptr;
389 if (m_includes_seen)
391 delete m_includes_seen;
392 m_includes_seen = nullptr;
395 if (m_client_data_hooks)
397 delete m_client_data_hooks;
398 m_client_data_hooks = nullptr;
401 delete m_urlifier;
402 m_urlifier = nullptr;
405 void
406 diagnostic_context::set_output_format (diagnostic_output_format *output_format)
408 /* Ideally we'd use a std::unique_ptr here. */
409 delete m_output_format;
410 m_output_format = output_format;
413 void
414 diagnostic_context::set_client_data_hooks (diagnostic_client_data_hooks *hooks)
416 /* Ideally we'd use a std::unique_ptr here. */
417 delete m_client_data_hooks;
418 m_client_data_hooks = hooks;
421 void
422 diagnostic_context::
423 set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb,
424 void *option_state,
425 diagnostic_make_option_name_cb make_option_name_cb,
426 diagnostic_make_option_url_cb make_option_url_cb,
427 unsigned lang_mask)
429 m_option_callbacks.m_option_enabled_cb = option_enabled_cb;
430 m_option_callbacks.m_option_state = option_state;
431 m_option_callbacks.m_make_option_name_cb = make_option_name_cb;
432 m_option_callbacks.m_make_option_url_cb = make_option_url_cb;
433 m_option_callbacks.m_lang_mask = lang_mask;
436 void
437 diagnostic_context::set_urlifier (urlifier *urlifier)
439 /* Ideally we'd use a std::unique_ptr here. */
440 delete m_urlifier;
441 m_urlifier = urlifier;
444 void
445 diagnostic_context::create_edit_context ()
447 delete m_edit_context_ptr;
448 gcc_assert (m_file_cache);
449 m_edit_context_ptr = new edit_context (*m_file_cache);
452 /* Initialize DIAGNOSTIC, where the message MSG has already been
453 translated. */
454 void
455 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
456 va_list *args, rich_location *richloc,
457 diagnostic_t kind)
459 gcc_assert (richloc);
460 diagnostic->message.m_err_no = errno;
461 diagnostic->message.m_args_ptr = args;
462 diagnostic->message.m_format_spec = msg;
463 diagnostic->message.m_richloc = richloc;
464 diagnostic->richloc = richloc;
465 diagnostic->metadata = NULL;
466 diagnostic->kind = kind;
467 diagnostic->option_index = 0;
470 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
471 translated. */
472 void
473 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
474 va_list *args, rich_location *richloc,
475 diagnostic_t kind)
477 gcc_assert (richloc);
478 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
481 static const char *const diagnostic_kind_color[] = {
482 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
483 #include "diagnostic.def"
484 #undef DEFINE_DIAGNOSTIC_KIND
485 NULL
488 /* Get a color name for diagnostics of type KIND
489 Result could be NULL. */
491 const char *
492 diagnostic_get_color_for_kind (diagnostic_t kind)
494 return diagnostic_kind_color[kind];
497 /* Given an expanded_location, convert the column (which is in 1-based bytes)
498 to the requested units, without converting the origin.
499 Return -1 if the column is invalid (<= 0). */
501 static int
502 convert_column_unit (file_cache &fc,
503 enum diagnostics_column_unit column_unit,
504 int tabstop,
505 expanded_location s)
507 if (s.column <= 0)
508 return -1;
510 switch (column_unit)
512 default:
513 gcc_unreachable ();
515 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
517 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
518 return location_compute_display_column (fc, s, policy);
521 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
522 return s.column;
526 /* Given an expanded_location, convert the column (which is in 1-based bytes)
527 to the requested units and origin. Return -1 if the column is
528 invalid (<= 0). */
530 diagnostic_context::converted_column (expanded_location s) const
532 int one_based_col = convert_column_unit (get_file_cache (),
533 m_column_unit, m_tabstop, s);
534 if (one_based_col <= 0)
535 return -1;
536 return one_based_col + (m_column_origin - 1);
539 /* Return a formatted line and column ':%line:%column'. Elided if
540 line == 0 or col < 0. (A column of 0 may be valid due to the
541 -fdiagnostics-column-origin option.)
542 The result is a statically allocated buffer. */
544 static const char *
545 maybe_line_and_column (int line, int col)
547 static char result[32];
549 if (line)
551 size_t l
552 = snprintf (result, sizeof (result),
553 col >= 0 ? ":%d:%d" : ":%d", line, col);
554 gcc_checking_assert (l < sizeof (result));
556 else
557 result[0] = 0;
558 return result;
561 /* Return a string describing a location e.g. "foo.c:42:10". */
563 label_text
564 diagnostic_context::get_location_text (const expanded_location &s) const
566 pretty_printer *pp = this->printer;
567 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
568 const char *locus_ce = colorize_stop (pp_show_color (pp));
569 const char *file = s.file ? s.file : progname;
570 int line = 0;
571 int col = -1;
572 if (strcmp (file, special_fname_builtin ()))
574 line = s.line;
575 if (m_show_column)
576 col = this->converted_column (s);
579 const char *line_col = maybe_line_and_column (line, col);
580 return label_text::take (build_message_string ("%s%s%s:%s", locus_cs, file,
581 line_col, locus_ce));
584 static const char *const diagnostic_kind_text[] = {
585 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
586 #include "diagnostic.def"
587 #undef DEFINE_DIAGNOSTIC_KIND
588 "must-not-happen"
591 /* Return a malloc'd string describing a location and the severity of the
592 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
593 freeing the memory. */
594 char *
595 diagnostic_build_prefix (diagnostic_context *context,
596 const diagnostic_info *diagnostic)
598 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
600 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
601 const char *text_cs = "", *text_ce = "";
602 pretty_printer *pp = context->printer;
604 if (diagnostic_kind_color[diagnostic->kind])
606 text_cs = colorize_start (pp_show_color (pp),
607 diagnostic_kind_color[diagnostic->kind]);
608 text_ce = colorize_stop (pp_show_color (pp));
611 const expanded_location s = diagnostic_expand_location (diagnostic);
612 label_text location_text = context->get_location_text (s);
614 char *result = build_message_string ("%s %s%s%s", location_text.get (),
615 text_cs, text, text_ce);
616 return result;
619 /* Functions at which to stop the backtrace print. It's not
620 particularly helpful to print the callers of these functions. */
622 static const char * const bt_stop[] =
624 "main",
625 "toplev::main",
626 "execute_one_pass",
627 "compile_file",
630 /* A callback function passed to the backtrace_full function. */
632 static int
633 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
634 const char *function)
636 int *pcount = (int *) data;
638 /* If we don't have any useful information, don't print
639 anything. */
640 if (filename == NULL && function == NULL)
641 return 0;
643 /* Skip functions in diagnostic.cc. */
644 if (*pcount == 0
645 && filename != NULL
646 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
647 return 0;
649 /* Print up to 20 functions. We could make this a --param, but
650 since this is only for debugging just use a constant for now. */
651 if (*pcount >= 20)
653 /* Returning a non-zero value stops the backtrace. */
654 return 1;
656 ++*pcount;
658 char *alc = NULL;
659 if (function != NULL)
661 char *str = cplus_demangle_v3 (function,
662 (DMGL_VERBOSE | DMGL_ANSI
663 | DMGL_GNU_V3 | DMGL_PARAMS));
664 if (str != NULL)
666 alc = str;
667 function = str;
670 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
672 size_t len = strlen (bt_stop[i]);
673 if (strncmp (function, bt_stop[i], len) == 0
674 && (function[len] == '\0' || function[len] == '('))
676 if (alc != NULL)
677 free (alc);
678 /* Returning a non-zero value stops the backtrace. */
679 return 1;
684 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
685 (unsigned long) pc,
686 function == NULL ? "???" : function,
687 filename == NULL ? "???" : filename,
688 lineno);
690 if (alc != NULL)
691 free (alc);
693 return 0;
696 /* A callback function passed to the backtrace_full function. This is
697 called if backtrace_full has an error. */
699 static void
700 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
702 if (errnum < 0)
704 /* This means that no debug info was available. Just quietly
705 skip printing backtrace info. */
706 return;
708 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
709 errnum == 0 ? "" : xstrerror (errnum));
712 /* Check if we've met the maximum error limit, and if so fatally exit
713 with a message.
714 FLUSH indicates whether a diagnostic_context::finish call is needed. */
716 void
717 diagnostic_context::check_max_errors (bool flush)
719 if (!m_max_errors)
720 return;
722 int count = (m_diagnostic_count[DK_ERROR]
723 + m_diagnostic_count[DK_SORRY]
724 + m_diagnostic_count[DK_WERROR]);
726 if (count >= m_max_errors)
728 fnotice (stderr,
729 "compilation terminated due to -fmax-errors=%u.\n",
730 m_max_errors);
731 if (flush)
732 finish ();
733 exit (FATAL_EXIT_CODE);
737 /* Take any action which is expected to happen after the diagnostic
738 is written out. This function does not always return. */
739 void
740 diagnostic_context::action_after_output (diagnostic_t diag_kind)
742 switch (diag_kind)
744 case DK_DEBUG:
745 case DK_NOTE:
746 case DK_ANACHRONISM:
747 case DK_WARNING:
748 break;
750 case DK_ERROR:
751 case DK_SORRY:
752 if (m_abort_on_error)
753 real_abort ();
754 if (m_fatal_errors)
756 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
757 finish ();
758 exit (FATAL_EXIT_CODE);
760 break;
762 case DK_ICE:
763 case DK_ICE_NOBT:
765 /* Optional callback for attempting to handle ICEs gracefully. */
766 if (void (*ice_handler_cb) (diagnostic_context *) = m_ice_handler_cb)
768 /* Clear the callback, to avoid potentially re-entering
769 the routine if there's a crash within the handler. */
770 m_ice_handler_cb = NULL;
771 ice_handler_cb (this);
773 /* The context might have had diagnostic_finish called on
774 it at this point. */
776 struct backtrace_state *state = NULL;
777 if (diag_kind == DK_ICE)
778 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
779 int count = 0;
780 if (state != NULL)
781 backtrace_full (state, 2, bt_callback, bt_err_callback,
782 (void *) &count);
784 if (m_abort_on_error)
785 real_abort ();
787 if (m_report_bug)
788 fnotice (stderr, "Please submit a full bug report, "
789 "with preprocessed source.\n");
790 else
791 fnotice (stderr, "Please submit a full bug report, "
792 "with preprocessed source (by using -freport-bug).\n");
794 if (count > 0)
795 fnotice (stderr, "Please include the complete backtrace "
796 "with any bug report.\n");
797 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
799 exit (ICE_EXIT_CODE);
802 case DK_FATAL:
803 if (m_abort_on_error)
804 real_abort ();
805 finish ();
806 fnotice (stderr, "compilation terminated.\n");
807 exit (FATAL_EXIT_CODE);
809 default:
810 gcc_unreachable ();
814 /* Only dump the "In file included from..." stack once for each file. */
816 bool
817 diagnostic_context::includes_seen_p (const line_map_ordinary *map)
819 /* No include path for main. */
820 if (MAIN_FILE_P (map))
821 return true;
823 /* Always identify C++ modules, at least for now. */
824 auto probe = map;
825 if (linemap_check_ordinary (map)->reason == LC_RENAME)
826 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
827 probe = linemap_included_from_linemap (line_table, map);
828 if (MAP_MODULE_P (probe))
829 return false;
831 if (!m_includes_seen)
832 m_includes_seen = new hash_set<location_t, false, location_hash>;
834 /* Hash the location of the #include directive to better handle files
835 that are included multiple times with different macros defined. */
836 return m_includes_seen->add (linemap_included_from (map));
839 void
840 diagnostic_context::report_current_module (location_t where)
842 const line_map_ordinary *map = NULL;
844 if (pp_needs_newline (this->printer))
846 pp_newline (this->printer);
847 pp_needs_newline (this->printer) = false;
850 if (where <= BUILTINS_LOCATION)
851 return;
853 linemap_resolve_location (line_table, where,
854 LRK_MACRO_DEFINITION_LOCATION,
855 &map);
857 if (map && m_last_module != map)
859 m_last_module = map;
860 if (!includes_seen_p (map))
862 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
863 expanded_location s = {};
866 where = linemap_included_from (map);
867 map = linemap_included_from_linemap (line_table, map);
868 bool is_module = MAP_MODULE_P (map);
869 s.file = LINEMAP_FILE (map);
870 s.line = SOURCE_LINE (map, where);
871 int col = -1;
872 if (first && m_show_column)
874 s.column = SOURCE_COLUMN (map, where);
875 col = converted_column (s);
877 const char *line_col = maybe_line_and_column (s.line, col);
878 static const char *const msgs[] =
880 NULL,
881 N_(" from"),
882 N_("In file included from"), /* 2 */
883 N_(" included from"),
884 N_("In module"), /* 4 */
885 N_("of module"),
886 N_("In module imported at"), /* 6 */
887 N_("imported at"),
890 unsigned index = (was_module ? 6 : is_module ? 4
891 : need_inc ? 2 : 0) + !first;
893 pp_verbatim (this->printer, "%s%s %r%s%s%R",
894 first ? "" : was_module ? ", " : ",\n",
895 _(msgs[index]),
896 "locus", s.file, line_col);
897 first = false, need_inc = was_module, was_module = is_module;
899 while (!includes_seen_p (map));
900 pp_verbatim (this->printer, ":");
901 pp_newline (this->printer);
906 /* If DIAGNOSTIC has a diagnostic_path and this context supports
907 printing paths, print the path. */
909 void
910 diagnostic_context::show_any_path (const diagnostic_info &diagnostic)
912 const diagnostic_path *path = diagnostic.richloc->get_path ();
913 if (!path)
914 return;
916 if (m_print_path)
917 m_print_path (this, path);
920 /* class diagnostic_event. */
922 /* struct diagnostic_event::meaning. */
924 void
925 diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
927 bool need_comma = false;
928 pp_character (pp, '{');
929 if (const char *verb_str = maybe_get_verb_str (m_verb))
931 pp_printf (pp, "verb: %qs", verb_str);
932 need_comma = true;
934 if (const char *noun_str = maybe_get_noun_str (m_noun))
936 if (need_comma)
937 pp_string (pp, ", ");
938 pp_printf (pp, "noun: %qs", noun_str);
939 need_comma = true;
941 if (const char *property_str = maybe_get_property_str (m_property))
943 if (need_comma)
944 pp_string (pp, ", ");
945 pp_printf (pp, "property: %qs", property_str);
946 need_comma = true;
948 pp_character (pp, '}');
951 /* Get a string (or NULL) for V suitable for use within a SARIF
952 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
954 const char *
955 diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
957 switch (v)
959 default:
960 gcc_unreachable ();
961 case VERB_unknown:
962 return NULL;
963 case VERB_acquire:
964 return "acquire";
965 case VERB_release:
966 return "release";
967 case VERB_enter:
968 return "enter";
969 case VERB_exit:
970 return "exit";
971 case VERB_call:
972 return "call";
973 case VERB_return:
974 return "return";
975 case VERB_branch:
976 return "branch";
977 case VERB_danger:
978 return "danger";
982 /* Get a string (or NULL) for N suitable for use within a SARIF
983 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
985 const char *
986 diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
988 switch (n)
990 default:
991 gcc_unreachable ();
992 case NOUN_unknown:
993 return NULL;
994 case NOUN_taint:
995 return "taint";
996 case NOUN_sensitive:
997 return "sensitive";
998 case NOUN_function:
999 return "function";
1000 case NOUN_lock:
1001 return "lock";
1002 case NOUN_memory:
1003 return "memory";
1004 case NOUN_resource:
1005 return "resource";
1009 /* Get a string (or NULL) for P suitable for use within a SARIF
1010 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
1012 const char *
1013 diagnostic_event::meaning::maybe_get_property_str (enum property p)
1015 switch (p)
1017 default:
1018 gcc_unreachable ();
1019 case PROPERTY_unknown:
1020 return NULL;
1021 case PROPERTY_true:
1022 return "true";
1023 case PROPERTY_false:
1024 return "false";
1028 /* class diagnostic_path. */
1030 /* Subroutint of diagnostic_path::interprocedural_p.
1031 Look for the first event in this path that is within a function
1032 i.e. has a non-NULL fndecl, and a non-zero stack depth.
1033 If found, write its index to *OUT_IDX and return true.
1034 Otherwise return false. */
1036 bool
1037 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
1039 const unsigned num = num_events ();
1040 for (unsigned i = 0; i < num; i++)
1042 if (!(get_event (i).get_fndecl () == NULL
1043 && get_event (i).get_stack_depth () == 0))
1045 *out_idx = i;
1046 return true;
1049 return false;
1052 /* Return true if the events in this path involve more than one
1053 function, or false if it is purely intraprocedural. */
1055 bool
1056 diagnostic_path::interprocedural_p () const
1058 /* Ignore leading events that are outside of any function. */
1059 unsigned first_fn_event_idx;
1060 if (!get_first_event_in_a_function (&first_fn_event_idx))
1061 return false;
1063 const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
1064 tree first_fndecl = first_fn_event.get_fndecl ();
1065 int first_fn_stack_depth = first_fn_event.get_stack_depth ();
1067 const unsigned num = num_events ();
1068 for (unsigned i = first_fn_event_idx + 1; i < num; i++)
1070 if (get_event (i).get_fndecl () != first_fndecl)
1071 return true;
1072 if (get_event (i).get_stack_depth () != first_fn_stack_depth)
1073 return true;
1075 return false;
1078 void
1079 default_diagnostic_starter (diagnostic_context *context,
1080 const diagnostic_info *diagnostic)
1082 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
1083 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
1084 diagnostic));
1087 void
1088 default_diagnostic_start_span_fn (diagnostic_context *context,
1089 expanded_location exploc)
1091 label_text text = context->get_location_text (exploc);
1092 pp_string (context->printer, text.get ());
1093 pp_newline (context->printer);
1096 void
1097 default_diagnostic_finalizer (diagnostic_context *context,
1098 const diagnostic_info *diagnostic,
1099 diagnostic_t)
1101 char *saved_prefix = pp_take_prefix (context->printer);
1102 pp_set_prefix (context->printer, NULL);
1103 pp_newline (context->printer);
1104 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
1105 pp_set_prefix (context->printer, saved_prefix);
1106 pp_flush (context->printer);
1109 /* Interface to specify diagnostic kind overrides. Returns the
1110 previous setting, or DK_UNSPECIFIED if the parameters are out of
1111 range. If OPTION_INDEX is zero, the new setting is for all the
1112 diagnostics. */
1113 diagnostic_t
1114 diagnostic_option_classifier::
1115 classify_diagnostic (const diagnostic_context *context,
1116 int option_index,
1117 diagnostic_t new_kind,
1118 location_t where)
1120 diagnostic_t old_kind;
1122 if (option_index < 0
1123 || option_index >= m_n_opts
1124 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1125 return DK_UNSPECIFIED;
1127 old_kind = m_classify_diagnostic[option_index];
1129 /* Handle pragmas separately, since we need to keep track of *where*
1130 the pragmas were. */
1131 if (where != UNKNOWN_LOCATION)
1133 int i;
1135 /* Record the command-line status, so we can reset it back on DK_POP. */
1136 if (old_kind == DK_UNSPECIFIED)
1138 old_kind = !context->option_enabled_p (option_index)
1139 ? DK_IGNORED : (context->warning_as_error_requested_p ()
1140 ? DK_ERROR : DK_WARNING);
1141 m_classify_diagnostic[option_index] = old_kind;
1144 for (i = m_n_classification_history - 1; i >= 0; i --)
1145 if (m_classification_history[i].option == option_index)
1147 old_kind = m_classification_history[i].kind;
1148 break;
1151 i = m_n_classification_history;
1152 m_classification_history =
1153 (diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
1154 * sizeof (diagnostic_classification_change_t));
1155 m_classification_history[i].location = where;
1156 m_classification_history[i].option = option_index;
1157 m_classification_history[i].kind = new_kind;
1158 m_n_classification_history ++;
1160 else
1161 m_classify_diagnostic[option_index] = new_kind;
1163 return old_kind;
1166 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1167 escaping rules for -fdiagnostics-parseable-fixits. */
1169 static void
1170 print_escaped_string (pretty_printer *pp, const char *text)
1172 gcc_assert (pp);
1173 gcc_assert (text);
1175 pp_character (pp, '"');
1176 for (const char *ch = text; *ch; ch++)
1178 switch (*ch)
1180 case '\\':
1181 /* Escape backslash as two backslashes. */
1182 pp_string (pp, "\\\\");
1183 break;
1184 case '\t':
1185 /* Escape tab as "\t". */
1186 pp_string (pp, "\\t");
1187 break;
1188 case '\n':
1189 /* Escape newline as "\n". */
1190 pp_string (pp, "\\n");
1191 break;
1192 case '"':
1193 /* Escape doublequotes as \". */
1194 pp_string (pp, "\\\"");
1195 break;
1196 default:
1197 if (ISPRINT (*ch))
1198 pp_character (pp, *ch);
1199 else
1200 /* Use octal for non-printable chars. */
1202 unsigned char c = (*ch & 0xff);
1203 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1205 break;
1208 pp_character (pp, '"');
1211 /* Implementation of -fdiagnostics-parseable-fixits and
1212 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1213 Print a machine-parseable version of all fixits in RICHLOC to PP,
1214 using COLUMN_UNIT to express columns.
1215 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1217 static void
1218 print_parseable_fixits (file_cache &fc,
1219 pretty_printer *pp, rich_location *richloc,
1220 enum diagnostics_column_unit column_unit,
1221 int tabstop)
1223 gcc_assert (pp);
1224 gcc_assert (richloc);
1226 char *saved_prefix = pp_take_prefix (pp);
1227 pp_set_prefix (pp, NULL);
1229 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1231 const fixit_hint *hint = richloc->get_fixit_hint (i);
1232 location_t start_loc = hint->get_start_loc ();
1233 expanded_location start_exploc = expand_location (start_loc);
1234 pp_string (pp, "fix-it:");
1235 print_escaped_string (pp, start_exploc.file);
1236 /* For compatibility with clang, print as a half-open range. */
1237 location_t next_loc = hint->get_next_loc ();
1238 expanded_location next_exploc = expand_location (next_loc);
1239 int start_col
1240 = convert_column_unit (fc, column_unit, tabstop, start_exploc);
1241 int next_col
1242 = convert_column_unit (fc, column_unit, tabstop, next_exploc);
1243 pp_printf (pp, ":{%i:%i-%i:%i}:",
1244 start_exploc.line, start_col,
1245 next_exploc.line, next_col);
1246 print_escaped_string (pp, hint->get_string ());
1247 pp_newline (pp);
1250 pp_set_prefix (pp, saved_prefix);
1253 /* Update the inlining info in this context for a DIAGNOSTIC. */
1255 void
1256 diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
1258 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1260 if (m_set_locations_cb)
1261 /* Retrieve the locations into which the expression about to be
1262 diagnosed has been inlined, including those of all the callers
1263 all the way down the inlining stack. */
1264 m_set_locations_cb (this, diagnostic);
1265 else
1267 /* When there's no callback use just the one location provided
1268 by the caller of the diagnostic function. */
1269 location_t loc = diagnostic_location (diagnostic);
1270 ilocs.safe_push (loc);
1271 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1275 /* Update the kind of DIAGNOSTIC based on its location(s), including
1276 any of those in its inlining stack, relative to any
1277 #pragma GCC diagnostic
1278 directives recorded within this object.
1280 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1281 otherwise. */
1283 diagnostic_t
1284 diagnostic_option_classifier::
1285 update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
1287 if (m_n_classification_history <= 0)
1288 return DK_UNSPECIFIED;
1290 /* Iterate over the locations, checking the diagnostic disposition
1291 for the diagnostic at each. If it's explicitly set as opposed
1292 to unspecified, update the disposition for this instance of
1293 the diagnostic and return it. */
1294 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1296 /* FIXME: Stupid search. Optimize later. */
1297 for (int i = m_n_classification_history - 1; i >= 0; i --)
1299 const diagnostic_classification_change_t &hist
1300 = m_classification_history[i];
1302 location_t pragloc = hist.location;
1303 if (!linemap_location_before_p (line_table, pragloc, loc))
1304 continue;
1306 if (hist.kind == (int) DK_POP)
1308 /* Move on to the next region. */
1309 i = hist.option;
1310 continue;
1313 int option = hist.option;
1314 /* The option 0 is for all the diagnostics. */
1315 if (option == 0 || option == diagnostic->option_index)
1317 diagnostic_t kind = hist.kind;
1318 if (kind != DK_UNSPECIFIED)
1319 diagnostic->kind = kind;
1320 return kind;
1325 return DK_UNSPECIFIED;
1328 /* Generate a URL string describing CWE. The caller is responsible for
1329 freeing the string. */
1331 char *
1332 get_cwe_url (int cwe)
1334 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1337 /* If DIAGNOSTIC has a CWE identifier, print it.
1339 For example, if the diagnostic metadata associates it with CWE-119,
1340 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1341 description of the security issue. */
1343 void
1344 diagnostic_context::print_any_cwe (const diagnostic_info &diagnostic)
1346 if (diagnostic.metadata == NULL)
1347 return;
1349 int cwe = diagnostic.metadata->get_cwe ();
1350 if (cwe)
1352 pretty_printer * const pp = this->printer;
1353 char *saved_prefix = pp_take_prefix (pp);
1354 pp_string (pp, " [");
1355 pp_string (pp, colorize_start (pp_show_color (pp),
1356 diagnostic_kind_color[diagnostic.kind]));
1357 if (pp->url_format != URL_FORMAT_NONE)
1359 char *cwe_url = get_cwe_url (cwe);
1360 pp_begin_url (pp, cwe_url);
1361 free (cwe_url);
1363 pp_printf (pp, "CWE-%i", cwe);
1364 pp_set_prefix (pp, saved_prefix);
1365 if (pp->url_format != URL_FORMAT_NONE)
1366 pp_end_url (pp);
1367 pp_string (pp, colorize_stop (pp_show_color (pp)));
1368 pp_character (pp, ']');
1372 /* If DIAGNOSTIC has any rules associated with it, print them.
1374 For example, if the diagnostic metadata associates it with a rule
1375 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1376 with any URL provided by the rule. */
1378 void
1379 diagnostic_context::print_any_rules (const diagnostic_info &diagnostic)
1381 if (diagnostic.metadata == NULL)
1382 return;
1384 for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
1386 const diagnostic_metadata::rule &rule
1387 = diagnostic.metadata->get_rule (idx);
1388 if (char *desc = rule.make_description ())
1390 pretty_printer * const pp = this->printer;
1391 char *saved_prefix = pp_take_prefix (pp);
1392 pp_string (pp, " [");
1393 pp_string (pp,
1394 colorize_start (pp_show_color (pp),
1395 diagnostic_kind_color[diagnostic.kind]));
1396 char *url = NULL;
1397 if (pp->url_format != URL_FORMAT_NONE)
1399 url = rule.make_url ();
1400 if (url)
1401 pp_begin_url (pp, url);
1403 pp_string (pp, desc);
1404 pp_set_prefix (pp, saved_prefix);
1405 if (pp->url_format != URL_FORMAT_NONE)
1406 if (url)
1407 pp_end_url (pp);
1408 free (url);
1409 pp_string (pp, colorize_stop (pp_show_color (pp)));
1410 pp_character (pp, ']');
1411 free (desc);
1416 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1417 printer, e.g. " [-Werror=uninitialized]".
1418 Subroutine of diagnostic_context::report_diagnostic. */
1420 void
1421 diagnostic_context::print_option_information (const diagnostic_info &diagnostic,
1422 diagnostic_t orig_diag_kind)
1424 if (char *option_text = make_option_name (diagnostic.option_index,
1425 orig_diag_kind, diagnostic.kind))
1427 char *option_url = nullptr;
1428 if (this->printer->url_format != URL_FORMAT_NONE)
1429 option_url = make_option_url (diagnostic.option_index);
1430 pretty_printer * const pp = this->printer;
1431 pp_string (pp, " [");
1432 pp_string (pp, colorize_start (pp_show_color (pp),
1433 diagnostic_kind_color[diagnostic.kind]));
1434 if (option_url)
1435 pp_begin_url (pp, option_url);
1436 pp_string (pp, option_text);
1437 if (option_url)
1439 pp_end_url (pp);
1440 free (option_url);
1442 pp_string (pp, colorize_stop (pp_show_color (pp)));
1443 pp_character (pp, ']');
1444 free (option_text);
1448 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1449 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1451 bool
1452 diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
1454 /* Update the inlining stack for this diagnostic. */
1455 get_any_inlining_info (diagnostic);
1457 /* Diagnostics with no option or -fpermissive are always enabled. */
1458 if (!diagnostic->option_index
1459 || diagnostic->option_index == permissive_error_option (this))
1460 return true;
1462 /* This tests if the user provided the appropriate -Wfoo or
1463 -Wno-foo option. */
1464 if (!option_enabled_p (diagnostic->option_index))
1465 return false;
1467 /* This tests for #pragma diagnostic changes. */
1468 diagnostic_t diag_class
1469 = m_option_classifier.update_effective_level_from_pragmas (diagnostic);
1471 /* This tests if the user provided the appropriate -Werror=foo
1472 option. */
1473 if (diag_class == DK_UNSPECIFIED
1474 && !option_unspecified_p (diagnostic->option_index))
1475 diagnostic->kind = m_option_classifier.get_current_override (diagnostic->option_index);
1477 /* This allows for future extensions, like temporarily disabling
1478 warnings for ranges of source code. */
1479 if (diagnostic->kind == DK_IGNORED)
1480 return false;
1482 return true;
1485 /* Returns whether warning OPT is enabled at LOC. */
1487 bool
1488 diagnostic_context::warning_enabled_at (location_t loc, int opt)
1490 if (!diagnostic_report_warnings_p (this, loc))
1491 return false;
1493 rich_location richloc (line_table, loc);
1494 diagnostic_info diagnostic = {};
1495 diagnostic.option_index = opt;
1496 diagnostic.richloc = &richloc;
1497 diagnostic.message.m_richloc = &richloc;
1498 diagnostic.kind = DK_WARNING;
1499 return diagnostic_enabled (&diagnostic);
1502 /* Report a diagnostic message (an error or a warning) as specified by
1503 this diagnostic_context.
1504 front-end independent format specifiers are exactly those described
1505 in the documentation of output_format.
1506 Return true if a diagnostic was printed, false otherwise. */
1508 bool
1509 diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
1511 diagnostic_t orig_diag_kind = diagnostic->kind;
1513 gcc_assert (m_output_format);
1515 /* Give preference to being able to inhibit warnings, before they
1516 get reclassified to something else. */
1517 bool was_warning = (diagnostic->kind == DK_WARNING
1518 || diagnostic->kind == DK_PEDWARN);
1519 if (was_warning && m_inhibit_warnings)
1520 return false;
1522 if (diagnostic->kind == DK_PEDWARN)
1524 diagnostic->kind = pedantic_warning_kind (this);
1525 /* We do this to avoid giving the message for -pedantic-errors. */
1526 orig_diag_kind = diagnostic->kind;
1529 if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p)
1530 return false;
1532 if (m_lock > 0)
1534 /* If we're reporting an ICE in the middle of some other error,
1535 try to flush out the previous error, then let this one
1536 through. Don't do this more than once. */
1537 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1538 && m_lock == 1)
1539 pp_newline_and_flush (this->printer);
1540 else
1541 error_recursion ();
1544 /* If the user requested that warnings be treated as errors, so be
1545 it. Note that we do this before the next block so that
1546 individual warnings can be overridden back to warnings with
1547 -Wno-error=*. */
1548 if (m_warning_as_error_requested
1549 && diagnostic->kind == DK_WARNING)
1550 diagnostic->kind = DK_ERROR;
1552 diagnostic->message.m_data = &diagnostic->x_data;
1554 /* Check to see if the diagnostic is enabled at the location and
1555 not disabled by #pragma GCC diagnostic anywhere along the inlining
1556 stack. . */
1557 if (!diagnostic_enabled (diagnostic))
1558 return false;
1560 if ((was_warning || diagnostic->kind == DK_WARNING)
1561 && ((!m_warn_system_headers
1562 && diagnostic->m_iinfo.m_allsyslocs)
1563 || m_inhibit_warnings))
1564 /* Bail if the warning is not to be reported because all locations in the
1565 inlining stack (if there is one) are in system headers. */
1566 return false;
1568 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1569 diagnostic_check_max_errors (this);
1571 m_lock++;
1573 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1575 /* When not checking, ICEs are converted to fatal errors when an
1576 error has already occurred. This is counteracted by
1577 abort_on_error. */
1578 if (!CHECKING_P
1579 && (m_diagnostic_count[DK_ERROR] > 0
1580 || m_diagnostic_count[DK_SORRY] > 0)
1581 && !m_abort_on_error)
1583 expanded_location s
1584 = expand_location (diagnostic_location (diagnostic));
1585 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1586 s.file, s.line);
1587 exit (ICE_EXIT_CODE);
1589 if (m_internal_error)
1590 (*m_internal_error) (this,
1591 diagnostic->message.m_format_spec,
1592 diagnostic->message.m_args_ptr);
1594 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1595 ++m_diagnostic_count[DK_WERROR];
1596 else
1597 ++m_diagnostic_count[diagnostic->kind];
1599 /* Is this the initial diagnostic within the stack of groups? */
1600 if (m_diagnostic_groups.m_emission_count == 0)
1601 m_output_format->on_begin_group ();
1602 m_diagnostic_groups.m_emission_count++;
1604 pp_format (this->printer, &diagnostic->message, m_urlifier);
1605 m_output_format->on_begin_diagnostic (*diagnostic);
1606 pp_output_formatted_text (this->printer, m_urlifier);
1607 if (m_show_cwe)
1608 print_any_cwe (*diagnostic);
1609 if (m_show_rules)
1610 print_any_rules (*diagnostic);
1611 if (m_show_option_requested)
1612 print_option_information (*diagnostic, orig_diag_kind);
1613 m_output_format->on_end_diagnostic (*diagnostic, orig_diag_kind);
1614 switch (m_extra_output_kind)
1616 default:
1617 break;
1618 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1619 print_parseable_fixits (get_file_cache (),
1620 this->printer, diagnostic->richloc,
1621 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1622 m_tabstop);
1623 pp_flush (this->printer);
1624 break;
1625 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1626 print_parseable_fixits (get_file_cache (),
1627 this->printer, diagnostic->richloc,
1628 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1629 m_tabstop);
1630 pp_flush (this->printer);
1631 break;
1633 diagnostic_action_after_output (this, diagnostic->kind);
1634 diagnostic->x_data = NULL;
1636 if (m_edit_context_ptr)
1637 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1638 m_edit_context_ptr->add_fixits (diagnostic->richloc);
1640 m_lock--;
1642 show_any_path (*diagnostic);
1644 return true;
1647 /* Get the number of digits in the decimal representation of VALUE. */
1650 num_digits (int value)
1652 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1653 using floating point. */
1654 gcc_assert (value >= 0);
1656 if (value == 0)
1657 return 1;
1659 int digits = 0;
1660 while (value > 0)
1662 digits++;
1663 value /= 10;
1665 return digits;
1668 /* Given a partial pathname as input, return another pathname that
1669 shares no directory elements with the pathname of __FILE__. This
1670 is used by fancy_abort() to print `internal compiler error in expr.cc'
1671 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1673 const char *
1674 trim_filename (const char *name)
1676 static const char this_file[] = __FILE__;
1677 const char *p = name, *q = this_file;
1679 /* First skip any "../" in each filename. This allows us to give a proper
1680 reference to a file in a subdirectory. */
1681 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1682 p += 3;
1684 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1685 q += 3;
1687 /* Now skip any parts the two filenames have in common. */
1688 while (*p == *q && *p != 0 && *q != 0)
1689 p++, q++;
1691 /* Now go backwards until the previous directory separator. */
1692 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1693 p--;
1695 return p;
1698 /* Standard error reporting routines in increasing order of severity.
1699 All of these take arguments like printf. */
1701 /* Text to be emitted verbatim to the error message stream; this
1702 produces no prefix and disables line-wrapping. Use rarely. */
1703 void
1704 verbatim (const char *gmsgid, ...)
1706 va_list ap;
1708 va_start (ap, gmsgid);
1709 text_info text (_(gmsgid), &ap, errno);
1710 pp_format_verbatim (global_dc->printer, &text);
1711 pp_newline_and_flush (global_dc->printer);
1712 va_end (ap);
1715 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1716 void
1717 diagnostic_append_note (diagnostic_context *context,
1718 location_t location,
1719 const char * gmsgid, ...)
1721 diagnostic_info diagnostic;
1722 va_list ap;
1723 rich_location richloc (line_table, location);
1725 va_start (ap, gmsgid);
1726 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1727 if (context->m_inhibit_notes_p)
1729 va_end (ap);
1730 return;
1732 char *saved_prefix = pp_take_prefix (context->printer);
1733 pp_set_prefix (context->printer,
1734 diagnostic_build_prefix (context, &diagnostic));
1735 pp_format (context->printer, &diagnostic.message);
1736 pp_output_formatted_text (context->printer);
1737 pp_destroy_prefix (context->printer);
1738 pp_set_prefix (context->printer, saved_prefix);
1739 pp_newline (context->printer);
1740 diagnostic_show_locus (context, &richloc, DK_NOTE);
1741 va_end (ap);
1744 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1745 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1746 and internal_error_no_backtrace, as documented and defined below. */
1747 static bool
1748 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1749 int opt, const char *gmsgid,
1750 va_list *ap, diagnostic_t kind)
1752 diagnostic_info diagnostic;
1753 if (kind == DK_PERMERROR)
1755 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1756 permissive_error_kind (global_dc));
1757 diagnostic.option_index = (opt != -1 ? opt
1758 : permissive_error_option (global_dc));
1760 else
1762 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1763 if (kind == DK_WARNING || kind == DK_PEDWARN)
1764 diagnostic.option_index = opt;
1766 diagnostic.metadata = metadata;
1767 return global_dc->report_diagnostic (&diagnostic);
1770 /* Implement inform_n, warning_n, and error_n, as documented and
1771 defined below. */
1772 static bool
1773 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1774 int opt, unsigned HOST_WIDE_INT n,
1775 const char *singular_gmsgid,
1776 const char *plural_gmsgid,
1777 va_list *ap, diagnostic_t kind)
1779 diagnostic_info diagnostic;
1780 unsigned long gtn;
1782 if (sizeof n <= sizeof gtn)
1783 gtn = n;
1784 else
1785 /* Use the largest number ngettext can handle, otherwise
1786 preserve the six least significant decimal digits for
1787 languages where the plural form depends on them. */
1788 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1790 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1791 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1792 if (kind == DK_WARNING)
1793 diagnostic.option_index = opt;
1794 diagnostic.metadata = metadata;
1795 return global_dc->report_diagnostic (&diagnostic);
1798 /* Wrapper around diagnostic_impl taking a variable argument list. */
1800 bool
1801 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1802 const char *gmsgid, ...)
1804 auto_diagnostic_group d;
1805 va_list ap;
1806 va_start (ap, gmsgid);
1807 rich_location richloc (line_table, location);
1808 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1809 va_end (ap);
1810 return ret;
1813 /* As above, but for rich_location *. */
1815 bool
1816 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1817 const char *gmsgid, ...)
1819 auto_diagnostic_group d;
1820 va_list ap;
1821 va_start (ap, gmsgid);
1822 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1823 va_end (ap);
1824 return ret;
1827 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1829 bool
1830 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1831 const char *gmsgid, va_list *ap)
1833 rich_location richloc (line_table, location);
1834 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1837 /* As above, but with rich_location and metadata. */
1839 bool
1840 emit_diagnostic_valist (diagnostic_t kind,
1841 rich_location *richloc,
1842 const diagnostic_metadata *metadata,
1843 int opt,
1844 const char *gmsgid, va_list *ap)
1846 return diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind);
1849 /* An informative note at LOCATION. Use this for additional details on an error
1850 message. */
1851 void
1852 inform (location_t location, const char *gmsgid, ...)
1854 auto_diagnostic_group d;
1855 va_list ap;
1856 va_start (ap, gmsgid);
1857 rich_location richloc (line_table, location);
1858 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1859 va_end (ap);
1862 /* Same as "inform" above, but at RICHLOC. */
1863 void
1864 inform (rich_location *richloc, const char *gmsgid, ...)
1866 gcc_assert (richloc);
1868 auto_diagnostic_group d;
1869 va_list ap;
1870 va_start (ap, gmsgid);
1871 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1872 va_end (ap);
1875 /* An informative note at LOCATION. Use this for additional details on an
1876 error message. */
1877 void
1878 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1879 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1881 va_list ap;
1882 va_start (ap, plural_gmsgid);
1883 auto_diagnostic_group d;
1884 rich_location richloc (line_table, location);
1885 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1886 &ap, DK_NOTE);
1887 va_end (ap);
1890 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1891 to the relevant language specification but is likely to be buggy anyway.
1892 Returns true if the warning was printed, false if it was inhibited. */
1893 bool
1894 warning (int opt, const char *gmsgid, ...)
1896 auto_diagnostic_group d;
1897 va_list ap;
1898 va_start (ap, gmsgid);
1899 rich_location richloc (line_table, input_location);
1900 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1901 va_end (ap);
1902 return ret;
1905 /* A warning at LOCATION. Use this for code which is correct according to the
1906 relevant language specification but is likely to be buggy anyway.
1907 Returns true if the warning was printed, false if it was inhibited. */
1909 bool
1910 warning_at (location_t location, int opt, const char *gmsgid, ...)
1912 auto_diagnostic_group d;
1913 va_list ap;
1914 va_start (ap, gmsgid);
1915 rich_location richloc (line_table, location);
1916 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1917 va_end (ap);
1918 return ret;
1921 /* Same as "warning at" above, but using RICHLOC. */
1923 bool
1924 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1926 gcc_assert (richloc);
1928 auto_diagnostic_group d;
1929 va_list ap;
1930 va_start (ap, gmsgid);
1931 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1932 va_end (ap);
1933 return ret;
1936 /* Same as "warning at" above, but using METADATA. */
1938 bool
1939 warning_meta (rich_location *richloc,
1940 const diagnostic_metadata &metadata,
1941 int opt, const char *gmsgid, ...)
1943 gcc_assert (richloc);
1945 auto_diagnostic_group d;
1946 va_list ap;
1947 va_start (ap, gmsgid);
1948 bool ret
1949 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1950 DK_WARNING);
1951 va_end (ap);
1952 return ret;
1955 /* Same as warning_n plural variant below, but using RICHLOC. */
1957 bool
1958 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1959 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1961 gcc_assert (richloc);
1963 auto_diagnostic_group d;
1964 va_list ap;
1965 va_start (ap, plural_gmsgid);
1966 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1967 singular_gmsgid, plural_gmsgid,
1968 &ap, DK_WARNING);
1969 va_end (ap);
1970 return ret;
1973 /* A warning at LOCATION. Use this for code which is correct according to the
1974 relevant language specification but is likely to be buggy anyway.
1975 Returns true if the warning was printed, false if it was inhibited. */
1977 bool
1978 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1979 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1981 auto_diagnostic_group d;
1982 va_list ap;
1983 va_start (ap, plural_gmsgid);
1984 rich_location richloc (line_table, location);
1985 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1986 singular_gmsgid, plural_gmsgid,
1987 &ap, DK_WARNING);
1988 va_end (ap);
1989 return ret;
1992 /* A "pedantic" warning at LOCATION: issues a warning unless
1993 -pedantic-errors was given on the command line, in which case it
1994 issues an error. Use this for diagnostics required by the relevant
1995 language standard, if you have chosen not to make them errors.
1997 Note that these diagnostics are issued independent of the setting
1998 of the -Wpedantic command-line switch. To get a warning enabled
1999 only with that switch, use either "if (pedantic) pedwarn
2000 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
2001 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
2003 Returns true if the warning was printed, false if it was inhibited. */
2005 bool
2006 pedwarn (location_t location, int opt, const char *gmsgid, ...)
2008 auto_diagnostic_group d;
2009 va_list ap;
2010 va_start (ap, gmsgid);
2011 rich_location richloc (line_table, location);
2012 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2013 va_end (ap);
2014 return ret;
2017 /* Same as pedwarn above, but using RICHLOC. */
2019 bool
2020 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
2022 gcc_assert (richloc);
2024 auto_diagnostic_group d;
2025 va_list ap;
2026 va_start (ap, gmsgid);
2027 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2028 va_end (ap);
2029 return ret;
2032 /* A "permissive" error at LOCATION: issues an error unless
2033 -fpermissive was given on the command line, in which case it issues
2034 a warning. Use this for things that really should be errors but we
2035 want to support legacy code.
2037 Returns true if the warning was printed, false if it was inhibited. */
2039 bool
2040 permerror (location_t location, const char *gmsgid, ...)
2042 auto_diagnostic_group d;
2043 va_list ap;
2044 va_start (ap, gmsgid);
2045 rich_location richloc (line_table, location);
2046 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2047 va_end (ap);
2048 return ret;
2051 /* Same as "permerror" above, but at RICHLOC. */
2053 bool
2054 permerror (rich_location *richloc, const char *gmsgid, ...)
2056 gcc_assert (richloc);
2058 auto_diagnostic_group d;
2059 va_list ap;
2060 va_start (ap, gmsgid);
2061 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2062 va_end (ap);
2063 return ret;
2066 /* Similar to the above, but controlled by a flag other than -fpermissive.
2067 As above, an error by default or a warning with -fpermissive, but this
2068 diagnostic can also be downgraded by -Wno-error=opt. */
2070 bool
2071 permerror_opt (location_t location, int opt, const char *gmsgid, ...)
2073 auto_diagnostic_group d;
2074 va_list ap;
2075 va_start (ap, gmsgid);
2076 rich_location richloc (line_table, location);
2077 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2078 va_end (ap);
2079 return ret;
2082 /* Same as "permerror" above, but at RICHLOC. */
2084 bool
2085 permerror_opt (rich_location *richloc, int opt, const char *gmsgid, ...)
2087 gcc_assert (richloc);
2089 auto_diagnostic_group d;
2090 va_list ap;
2091 va_start (ap, gmsgid);
2092 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2093 va_end (ap);
2094 return ret;
2097 /* A hard error: the code is definitely ill-formed, and an object file
2098 will not be produced. */
2099 void
2100 error (const char *gmsgid, ...)
2102 auto_diagnostic_group d;
2103 va_list ap;
2104 va_start (ap, gmsgid);
2105 rich_location richloc (line_table, input_location);
2106 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2107 va_end (ap);
2110 /* A hard error: the code is definitely ill-formed, and an object file
2111 will not be produced. */
2112 void
2113 error_n (location_t location, unsigned HOST_WIDE_INT n,
2114 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2116 auto_diagnostic_group d;
2117 va_list ap;
2118 va_start (ap, plural_gmsgid);
2119 rich_location richloc (line_table, location);
2120 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2121 &ap, DK_ERROR);
2122 va_end (ap);
2125 /* Same as above, but use location LOC instead of input_location. */
2126 void
2127 error_at (location_t loc, const char *gmsgid, ...)
2129 auto_diagnostic_group d;
2130 va_list ap;
2131 va_start (ap, gmsgid);
2132 rich_location richloc (line_table, loc);
2133 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2134 va_end (ap);
2137 /* Same as above, but use RICH_LOC. */
2139 void
2140 error_at (rich_location *richloc, const char *gmsgid, ...)
2142 gcc_assert (richloc);
2144 auto_diagnostic_group d;
2145 va_list ap;
2146 va_start (ap, gmsgid);
2147 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2148 va_end (ap);
2151 /* Same as above, but with metadata. */
2153 void
2154 error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
2155 const char *gmsgid, ...)
2157 gcc_assert (richloc);
2159 auto_diagnostic_group d;
2160 va_list ap;
2161 va_start (ap, gmsgid);
2162 diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
2163 va_end (ap);
2166 /* "Sorry, not implemented." Use for a language feature which is
2167 required by the relevant specification but not implemented by GCC.
2168 An object file will not be produced. */
2169 void
2170 sorry (const char *gmsgid, ...)
2172 auto_diagnostic_group d;
2173 va_list ap;
2174 va_start (ap, gmsgid);
2175 rich_location richloc (line_table, input_location);
2176 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2177 va_end (ap);
2180 /* Same as above, but use location LOC instead of input_location. */
2181 void
2182 sorry_at (location_t loc, const char *gmsgid, ...)
2184 auto_diagnostic_group d;
2185 va_list ap;
2186 va_start (ap, gmsgid);
2187 rich_location richloc (line_table, loc);
2188 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2189 va_end (ap);
2192 /* Return true if an error or a "sorry" has been seen. Various
2193 processing is disabled after errors. */
2194 bool
2195 seen_error (void)
2197 return errorcount || sorrycount;
2200 /* An error which is severe enough that we make no attempt to
2201 continue. Do not use this for internal consistency checks; that's
2202 internal_error. Use of this function should be rare. */
2203 void
2204 fatal_error (location_t loc, const char *gmsgid, ...)
2206 auto_diagnostic_group d;
2207 va_list ap;
2208 va_start (ap, gmsgid);
2209 rich_location richloc (line_table, loc);
2210 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2211 va_end (ap);
2213 gcc_unreachable ();
2216 /* An internal consistency check has failed. We make no attempt to
2217 continue. */
2218 void
2219 internal_error (const char *gmsgid, ...)
2221 auto_diagnostic_group d;
2222 va_list ap;
2223 va_start (ap, gmsgid);
2224 rich_location richloc (line_table, input_location);
2225 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2226 va_end (ap);
2228 gcc_unreachable ();
2231 /* Like internal_error, but no backtrace will be printed. Used when
2232 the internal error does not happen at the current location, but happened
2233 somewhere else. */
2234 void
2235 internal_error_no_backtrace (const char *gmsgid, ...)
2237 auto_diagnostic_group d;
2238 va_list ap;
2239 va_start (ap, gmsgid);
2240 rich_location richloc (line_table, input_location);
2241 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2242 va_end (ap);
2244 gcc_unreachable ();
2247 /* Emit DIAGRAM to this context, respecting the output format. */
2249 void
2250 diagnostic_context::emit_diagram (const diagnostic_diagram &diagram)
2252 if (m_diagrams.m_theme == nullptr)
2253 return;
2255 gcc_assert (m_output_format);
2256 m_output_format->on_diagram (diagram);
2259 /* Special case error functions. Most are implemented in terms of the
2260 above, or should be. */
2262 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2263 runs its second argument through gettext. */
2264 void
2265 fnotice (FILE *file, const char *cmsgid, ...)
2267 va_list ap;
2269 va_start (ap, cmsgid);
2270 vfprintf (file, _(cmsgid), ap);
2271 va_end (ap);
2274 /* Inform the user that an error occurred while trying to report some
2275 other error. This indicates catastrophic internal inconsistencies,
2276 so give up now. But do try to flush out the previous error.
2277 This mustn't use internal_error, that will cause infinite recursion. */
2279 void
2280 diagnostic_context::error_recursion ()
2282 if (m_lock < 3)
2283 pp_newline_and_flush (this->printer);
2285 fnotice (stderr,
2286 "internal compiler error: error reporting routines re-entered.\n");
2288 /* Call diagnostic_action_after_output to get the "please submit a bug
2289 report" message. */
2290 diagnostic_action_after_output (this, DK_ICE);
2292 /* Do not use gcc_unreachable here; that goes through internal_error
2293 and therefore would cause infinite recursion. */
2294 real_abort ();
2297 /* Report an internal compiler error in a friendly manner. This is
2298 the function that gets called upon use of abort() in the source
2299 code generally, thanks to a special macro. */
2301 void
2302 fancy_abort (const char *file, int line, const char *function)
2304 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2305 internal_error will crash internally in a way that prevents a
2306 useful message reaching the user.
2307 This can happen with libgccjit in the case of gcc_assert failures
2308 that occur outside of the libgccjit mutex that guards the rest of
2309 gcc's state, including global_dc (when global_dc may not be
2310 initialized yet, or might be in use by another thread).
2311 Handle such cases as gracefully as possible by falling back to a
2312 minimal abort handler that only relies on i18n. */
2313 if (global_dc->printer == NULL)
2315 /* Print the error message. */
2316 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2317 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2318 fputc ('\n', stderr);
2320 /* Attempt to print a backtrace. */
2321 struct backtrace_state *state
2322 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2323 int count = 0;
2324 if (state != NULL)
2325 backtrace_full (state, 2, bt_callback, bt_err_callback,
2326 (void *) &count);
2328 /* We can't call warn_if_plugins or emergency_dump_function as these
2329 rely on GCC state that might not be initialized, or might be in
2330 use by another thread. */
2332 /* Abort the process. */
2333 real_abort ();
2336 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2339 /* class diagnostic_context. */
2341 void
2342 diagnostic_context::begin_group ()
2344 m_diagnostic_groups.m_nesting_depth++;
2347 void
2348 diagnostic_context::end_group ()
2350 if (--m_diagnostic_groups.m_nesting_depth == 0)
2352 /* Handle the case where we've popped the final diagnostic group.
2353 If any diagnostics were emitted, give the context a chance
2354 to do something. */
2355 if (m_diagnostic_groups.m_emission_count > 0)
2356 m_output_format->on_end_group ();
2357 m_diagnostic_groups.m_emission_count = 0;
2361 /* class auto_diagnostic_group. */
2363 /* Constructor: "push" this group into global_dc. */
2365 auto_diagnostic_group::auto_diagnostic_group ()
2367 global_dc->begin_group ();
2370 /* Destructor: "pop" this group from global_dc. */
2372 auto_diagnostic_group::~auto_diagnostic_group ()
2374 global_dc->end_group ();
2377 /* class diagnostic_text_output_format : public diagnostic_output_format. */
2379 diagnostic_text_output_format::~diagnostic_text_output_format ()
2381 /* Some of the errors may actually have been warnings. */
2382 if (m_context.diagnostic_count (DK_WERROR))
2384 /* -Werror was given. */
2385 if (m_context.warning_as_error_requested_p ())
2386 pp_verbatim (m_context.printer,
2387 _("%s: all warnings being treated as errors"),
2388 progname);
2389 /* At least one -Werror= was given. */
2390 else
2391 pp_verbatim (m_context.printer,
2392 _("%s: some warnings being treated as errors"),
2393 progname);
2394 pp_newline_and_flush (m_context.printer);
2398 void
2399 diagnostic_text_output_format::on_begin_diagnostic (const diagnostic_info &diagnostic)
2401 (*diagnostic_starter (&m_context)) (&m_context, &diagnostic);
2404 void
2405 diagnostic_text_output_format::on_end_diagnostic (const diagnostic_info &diagnostic,
2406 diagnostic_t orig_diag_kind)
2408 (*diagnostic_finalizer (&m_context)) (&m_context, &diagnostic,
2409 orig_diag_kind);
2412 void
2413 diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
2415 char *saved_prefix = pp_take_prefix (m_context.printer);
2416 pp_set_prefix (m_context.printer, NULL);
2417 /* Use a newline before and after and a two-space indent
2418 to make the diagram stand out a little from the wall of text. */
2419 pp_newline (m_context.printer);
2420 diagram.get_canvas ().print_to_pp (m_context.printer, " ");
2421 pp_newline (m_context.printer);
2422 pp_set_prefix (m_context.printer, saved_prefix);
2423 pp_flush (m_context.printer);
2426 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2427 file-based output formats. */
2429 void
2430 diagnostic_output_format_init (diagnostic_context *context,
2431 const char *base_file_name,
2432 enum diagnostics_output_format format,
2433 bool json_formatting)
2435 switch (format)
2437 default:
2438 gcc_unreachable ();
2439 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2440 /* The default; do nothing. */
2441 break;
2443 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2444 diagnostic_output_format_init_json_stderr (context,
2445 json_formatting);
2446 break;
2448 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2449 diagnostic_output_format_init_json_file (context,
2450 json_formatting,
2451 base_file_name);
2452 break;
2454 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2455 diagnostic_output_format_init_sarif_stderr (context,
2456 json_formatting);
2457 break;
2459 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2460 diagnostic_output_format_init_sarif_file (context,
2461 json_formatting,
2462 base_file_name);
2463 break;
2467 /* Initialize this context's m_diagrams based on CHARSET.
2468 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2469 (or NULL for "no diagrams"). */
2471 void
2472 diagnostic_context::
2473 set_text_art_charset (enum diagnostic_text_art_charset charset)
2475 delete m_diagrams.m_theme;
2476 switch (charset)
2478 default:
2479 gcc_unreachable ();
2481 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
2482 m_diagrams.m_theme = nullptr;
2483 break;
2485 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
2486 m_diagrams.m_theme = new text_art::ascii_theme ();
2487 break;
2489 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
2490 m_diagrams.m_theme = new text_art::unicode_theme ();
2491 break;
2493 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
2494 m_diagrams.m_theme = new text_art::emoji_theme ();
2495 break;
2499 /* class simple_diagnostic_path : public diagnostic_path. */
2501 simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
2502 : m_event_pp (event_pp)
2504 add_thread ("main");
2507 /* Implementation of diagnostic_path::num_events vfunc for
2508 simple_diagnostic_path: simply get the number of events in the vec. */
2510 unsigned
2511 simple_diagnostic_path::num_events () const
2513 return m_events.length ();
2516 /* Implementation of diagnostic_path::get_event vfunc for
2517 simple_diagnostic_path: simply return the event in the vec. */
2519 const diagnostic_event &
2520 simple_diagnostic_path::get_event (int idx) const
2522 return *m_events[idx];
2525 unsigned
2526 simple_diagnostic_path::num_threads () const
2528 return m_threads.length ();
2531 const diagnostic_thread &
2532 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
2534 return *m_threads[idx];
2537 diagnostic_thread_id_t
2538 simple_diagnostic_path::add_thread (const char *name)
2540 m_threads.safe_push (new simple_diagnostic_thread (name));
2541 return m_threads.length () - 1;
2544 /* Add an event to this path at LOC within function FNDECL at
2545 stack depth DEPTH.
2547 Use m_context's printer to format FMT, as the text of the new
2548 event.
2550 Return the id of the new event. */
2552 diagnostic_event_id_t
2553 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2554 const char *fmt, ...)
2556 pretty_printer *pp = m_event_pp;
2557 pp_clear_output_area (pp);
2559 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2561 va_list ap;
2563 va_start (ap, fmt);
2565 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2566 pp_format (pp, &ti);
2567 pp_output_formatted_text (pp);
2569 va_end (ap);
2571 simple_diagnostic_event *new_event
2572 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2573 m_events.safe_push (new_event);
2575 pp_clear_output_area (pp);
2577 return diagnostic_event_id_t (m_events.length () - 1);
2580 diagnostic_event_id_t
2581 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
2582 location_t loc,
2583 tree fndecl,
2584 int depth,
2585 const char *fmt, ...)
2587 pretty_printer *pp = m_event_pp;
2588 pp_clear_output_area (pp);
2590 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2592 va_list ap;
2594 va_start (ap, fmt);
2596 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2598 pp_format (pp, &ti);
2599 pp_output_formatted_text (pp);
2601 va_end (ap);
2603 simple_diagnostic_event *new_event
2604 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
2605 thread_id);
2606 m_events.safe_push (new_event);
2608 pp_clear_output_area (pp);
2610 return diagnostic_event_id_t (m_events.length () - 1);
2613 /* struct simple_diagnostic_event. */
2615 /* simple_diagnostic_event's ctor. */
2617 simple_diagnostic_event::
2618 simple_diagnostic_event (location_t loc,
2619 tree fndecl,
2620 int depth,
2621 const char *desc,
2622 diagnostic_thread_id_t thread_id)
2623 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
2624 m_thread_id (thread_id)
2628 /* simple_diagnostic_event's dtor. */
2630 simple_diagnostic_event::~simple_diagnostic_event ()
2632 free (m_desc);
2635 /* Print PATH by emitting a dummy "note" associated with it. */
2637 DEBUG_FUNCTION
2638 void debug (diagnostic_path *path)
2640 rich_location richloc (line_table, UNKNOWN_LOCATION);
2641 richloc.set_path (path);
2642 inform (&richloc, "debug path");
2645 /* Really call the system 'abort'. This has to go right at the end of
2646 this file, so that there are no functions after it that call abort
2647 and get the system abort instead of our macro. */
2648 #undef abort
2649 static void
2650 real_abort (void)
2652 abort ();
2655 #if CHECKING_P
2657 namespace selftest {
2659 /* Helper function for test_print_escaped_string. */
2661 static void
2662 assert_print_escaped_string (const location &loc, const char *expected_output,
2663 const char *input)
2665 pretty_printer pp;
2666 print_escaped_string (&pp, input);
2667 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2670 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2671 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2673 /* Tests of print_escaped_string. */
2675 static void
2676 test_print_escaped_string ()
2678 /* Empty string. */
2679 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2681 /* Non-empty string. */
2682 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2684 /* Various things that need to be escaped: */
2685 /* Backslash. */
2686 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2687 "before\\after");
2688 /* Tab. */
2689 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2690 "before\tafter");
2691 /* Newline. */
2692 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2693 "before\nafter");
2694 /* Double quote. */
2695 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2696 "before\"after");
2698 /* Non-printable characters: BEL: '\a': 0x07 */
2699 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2700 "before\aafter");
2701 /* Non-printable characters: vertical tab: '\v': 0x0b */
2702 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2703 "before\vafter");
2706 /* Tests of print_parseable_fixits. */
2708 /* Verify that print_parseable_fixits emits the empty string if there
2709 are no fixits. */
2711 static void
2712 test_print_parseable_fixits_none ()
2714 pretty_printer pp;
2715 file_cache fc;
2716 rich_location richloc (line_table, UNKNOWN_LOCATION);
2718 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2719 ASSERT_STREQ ("", pp_formatted_text (&pp));
2722 /* Verify that print_parseable_fixits does the right thing if there
2723 is an insertion fixit hint. */
2725 static void
2726 test_print_parseable_fixits_insert ()
2728 pretty_printer pp;
2729 file_cache fc;
2730 rich_location richloc (line_table, UNKNOWN_LOCATION);
2732 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2733 linemap_line_start (line_table, 5, 100);
2734 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2735 location_t where = linemap_position_for_column (line_table, 10);
2736 richloc.add_fixit_insert_before (where, "added content");
2738 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2739 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2740 pp_formatted_text (&pp));
2743 /* Verify that print_parseable_fixits does the right thing if there
2744 is an removal fixit hint. */
2746 static void
2747 test_print_parseable_fixits_remove ()
2749 pretty_printer pp;
2750 file_cache fc;
2751 rich_location richloc (line_table, UNKNOWN_LOCATION);
2753 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2754 linemap_line_start (line_table, 5, 100);
2755 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2756 source_range where;
2757 where.m_start = linemap_position_for_column (line_table, 10);
2758 where.m_finish = linemap_position_for_column (line_table, 20);
2759 richloc.add_fixit_remove (where);
2761 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2762 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2763 pp_formatted_text (&pp));
2766 /* Verify that print_parseable_fixits does the right thing if there
2767 is an replacement fixit hint. */
2769 static void
2770 test_print_parseable_fixits_replace ()
2772 pretty_printer pp;
2773 file_cache fc;
2774 rich_location richloc (line_table, UNKNOWN_LOCATION);
2776 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2777 linemap_line_start (line_table, 5, 100);
2778 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2779 source_range where;
2780 where.m_start = linemap_position_for_column (line_table, 10);
2781 where.m_finish = linemap_position_for_column (line_table, 20);
2782 richloc.add_fixit_replace (where, "replacement");
2784 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2785 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2786 pp_formatted_text (&pp));
2789 /* Verify that print_parseable_fixits correctly handles
2790 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2792 static void
2793 test_print_parseable_fixits_bytes_vs_display_columns ()
2795 line_table_test ltt;
2796 rich_location richloc (line_table, UNKNOWN_LOCATION);
2798 /* 1-based byte offsets: 12345677778888999900001234567. */
2799 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2800 /* 1-based display cols: 123456[......7-8.....]9012345. */
2801 const int tabstop = 8;
2803 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2804 file_cache fc;
2805 const char *const fname = tmp.get_filename ();
2807 linemap_add (line_table, LC_ENTER, false, fname, 0);
2808 linemap_line_start (line_table, 1, 100);
2809 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2810 source_range where;
2811 where.m_start = linemap_position_for_column (line_table, 12);
2812 where.m_finish = linemap_position_for_column (line_table, 17);
2813 richloc.add_fixit_replace (where, "color");
2815 /* Escape fname. */
2816 pretty_printer tmp_pp;
2817 print_escaped_string (&tmp_pp, fname);
2818 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2820 const int buf_len = strlen (escaped_fname) + 100;
2821 char *const expected = XNEWVEC (char, buf_len);
2824 pretty_printer pp;
2825 print_parseable_fixits (fc, &pp, &richloc,
2826 DIAGNOSTICS_COLUMN_UNIT_BYTE,
2827 tabstop);
2828 snprintf (expected, buf_len,
2829 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2830 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2833 pretty_printer pp;
2834 print_parseable_fixits (fc, &pp, &richloc,
2835 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2836 tabstop);
2837 snprintf (expected, buf_len,
2838 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2839 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2842 XDELETEVEC (expected);
2843 free (escaped_fname);
2846 /* Verify that
2847 diagnostic_get_location_text (..., SHOW_COLUMN)
2848 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2849 colorization disabled. */
2851 static void
2852 assert_location_text (const char *expected_loc_text,
2853 const char *filename, int line, int column,
2854 bool show_column,
2855 int origin = 1,
2856 enum diagnostics_column_unit column_unit
2857 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2859 test_diagnostic_context dc;
2860 dc.m_show_column = show_column;
2861 dc.m_column_unit = column_unit;
2862 dc.m_column_origin = origin;
2864 expanded_location xloc;
2865 xloc.file = filename;
2866 xloc.line = line;
2867 xloc.column = column;
2868 xloc.data = NULL;
2869 xloc.sysp = false;
2871 label_text actual_loc_text = dc.get_location_text (xloc);
2872 ASSERT_STREQ (expected_loc_text, actual_loc_text.get ());
2875 /* Verify that diagnostic_get_location_text works as expected. */
2877 static void
2878 test_diagnostic_get_location_text ()
2880 const char *old_progname = progname;
2881 progname = "PROGNAME";
2882 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2883 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2884 assert_location_text (built_in_colon, special_fname_builtin (),
2885 42, 10, true);
2886 free (built_in_colon);
2887 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2888 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2889 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2890 for (int origin = 0; origin != 2; ++origin)
2891 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2892 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2893 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2894 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2896 maybe_line_and_column (INT_MAX, INT_MAX);
2897 maybe_line_and_column (INT_MIN, INT_MIN);
2900 /* In order to test display columns vs byte columns, we need to create a
2901 file for location_get_source_line() to read. */
2903 const char *const content = "smile \xf0\x9f\x98\x82\n";
2904 const int line_bytes = strlen (content) - 1;
2905 const int def_tabstop = 8;
2906 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2907 const int display_width = cpp_display_width (content, line_bytes, policy);
2908 ASSERT_EQ (line_bytes - 2, display_width);
2909 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2910 const char *const fname = tmp.get_filename ();
2911 const int buf_len = strlen (fname) + 16;
2912 char *const expected = XNEWVEC (char, buf_len);
2914 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2915 assert_location_text (expected, fname, 1, line_bytes, true,
2916 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2918 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2919 assert_location_text (expected, fname, 1, line_bytes, true,
2920 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2922 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2923 assert_location_text (expected, fname, 1, line_bytes, true,
2924 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2926 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2927 assert_location_text (expected, fname, 1, line_bytes, true,
2928 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2930 XDELETEVEC (expected);
2934 progname = old_progname;
2937 /* Selftest for num_digits. */
2939 static void
2940 test_num_digits ()
2942 ASSERT_EQ (1, num_digits (0));
2943 ASSERT_EQ (1, num_digits (9));
2944 ASSERT_EQ (2, num_digits (10));
2945 ASSERT_EQ (2, num_digits (99));
2946 ASSERT_EQ (3, num_digits (100));
2947 ASSERT_EQ (3, num_digits (999));
2948 ASSERT_EQ (4, num_digits (1000));
2949 ASSERT_EQ (4, num_digits (9999));
2950 ASSERT_EQ (5, num_digits (10000));
2951 ASSERT_EQ (5, num_digits (99999));
2952 ASSERT_EQ (6, num_digits (100000));
2953 ASSERT_EQ (6, num_digits (999999));
2954 ASSERT_EQ (7, num_digits (1000000));
2955 ASSERT_EQ (7, num_digits (9999999));
2956 ASSERT_EQ (8, num_digits (10000000));
2957 ASSERT_EQ (8, num_digits (99999999));
2960 /* Run all of the selftests within this file. */
2962 void
2963 c_diagnostic_cc_tests ()
2965 test_print_escaped_string ();
2966 test_print_parseable_fixits_none ();
2967 test_print_parseable_fixits_insert ();
2968 test_print_parseable_fixits_remove ();
2969 test_print_parseable_fixits_replace ();
2970 test_print_parseable_fixits_bytes_vs_display_columns ();
2971 test_diagnostic_get_location_text ();
2972 test_num_digits ();
2976 } // namespace selftest
2978 #endif /* #if CHECKING_P */
2980 #if __GNUC__ >= 10
2981 # pragma GCC diagnostic pop
2982 #endif