hppa: Export main in pr104869.C on hpux
[official-gcc.git] / gcc / diagnostic.cc
blobb4ebcd29457c67aef075c747792947827df20f68
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>
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 malloc'd string describing a location e.g. "foo.c:42:10".
562 The caller is responsible for freeing the memory. */
564 static char *
565 diagnostic_get_location_text (diagnostic_context *context,
566 expanded_location s)
568 pretty_printer *pp = context->printer;
569 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
570 const char *locus_ce = colorize_stop (pp_show_color (pp));
571 const char *file = s.file ? s.file : progname;
572 int line = 0;
573 int col = -1;
574 if (strcmp (file, special_fname_builtin ()))
576 line = s.line;
577 if (context->m_show_column)
578 col = context->converted_column (s);
581 const char *line_col = maybe_line_and_column (line, col);
582 return build_message_string ("%s%s%s:%s", locus_cs, file,
583 line_col, locus_ce);
586 static const char *const diagnostic_kind_text[] = {
587 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
588 #include "diagnostic.def"
589 #undef DEFINE_DIAGNOSTIC_KIND
590 "must-not-happen"
593 /* Return a malloc'd string describing a location and the severity of the
594 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
595 freeing the memory. */
596 char *
597 diagnostic_build_prefix (diagnostic_context *context,
598 const diagnostic_info *diagnostic)
600 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
602 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
603 const char *text_cs = "", *text_ce = "";
604 pretty_printer *pp = context->printer;
606 if (diagnostic_kind_color[diagnostic->kind])
608 text_cs = colorize_start (pp_show_color (pp),
609 diagnostic_kind_color[diagnostic->kind]);
610 text_ce = colorize_stop (pp_show_color (pp));
613 expanded_location s = diagnostic_expand_location (diagnostic);
614 char *location_text = diagnostic_get_location_text (context, s);
616 char *result = build_message_string ("%s %s%s%s", location_text,
617 text_cs, text, text_ce);
618 free (location_text);
619 return result;
622 /* Functions at which to stop the backtrace print. It's not
623 particularly helpful to print the callers of these functions. */
625 static const char * const bt_stop[] =
627 "main",
628 "toplev::main",
629 "execute_one_pass",
630 "compile_file",
633 /* A callback function passed to the backtrace_full function. */
635 static int
636 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
637 const char *function)
639 int *pcount = (int *) data;
641 /* If we don't have any useful information, don't print
642 anything. */
643 if (filename == NULL && function == NULL)
644 return 0;
646 /* Skip functions in diagnostic.cc. */
647 if (*pcount == 0
648 && filename != NULL
649 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
650 return 0;
652 /* Print up to 20 functions. We could make this a --param, but
653 since this is only for debugging just use a constant for now. */
654 if (*pcount >= 20)
656 /* Returning a non-zero value stops the backtrace. */
657 return 1;
659 ++*pcount;
661 char *alc = NULL;
662 if (function != NULL)
664 char *str = cplus_demangle_v3 (function,
665 (DMGL_VERBOSE | DMGL_ANSI
666 | DMGL_GNU_V3 | DMGL_PARAMS));
667 if (str != NULL)
669 alc = str;
670 function = str;
673 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
675 size_t len = strlen (bt_stop[i]);
676 if (strncmp (function, bt_stop[i], len) == 0
677 && (function[len] == '\0' || function[len] == '('))
679 if (alc != NULL)
680 free (alc);
681 /* Returning a non-zero value stops the backtrace. */
682 return 1;
687 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
688 (unsigned long) pc,
689 function == NULL ? "???" : function,
690 filename == NULL ? "???" : filename,
691 lineno);
693 if (alc != NULL)
694 free (alc);
696 return 0;
699 /* A callback function passed to the backtrace_full function. This is
700 called if backtrace_full has an error. */
702 static void
703 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
705 if (errnum < 0)
707 /* This means that no debug info was available. Just quietly
708 skip printing backtrace info. */
709 return;
711 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
712 errnum == 0 ? "" : xstrerror (errnum));
715 /* Check if we've met the maximum error limit, and if so fatally exit
716 with a message.
717 FLUSH indicates whether a diagnostic_context::finish call is needed. */
719 void
720 diagnostic_context::check_max_errors (bool flush)
722 if (!m_max_errors)
723 return;
725 int count = (m_diagnostic_count[DK_ERROR]
726 + m_diagnostic_count[DK_SORRY]
727 + m_diagnostic_count[DK_WERROR]);
729 if (count >= m_max_errors)
731 fnotice (stderr,
732 "compilation terminated due to -fmax-errors=%u.\n",
733 m_max_errors);
734 if (flush)
735 finish ();
736 exit (FATAL_EXIT_CODE);
740 /* Take any action which is expected to happen after the diagnostic
741 is written out. This function does not always return. */
742 void
743 diagnostic_context::action_after_output (diagnostic_t diag_kind)
745 switch (diag_kind)
747 case DK_DEBUG:
748 case DK_NOTE:
749 case DK_ANACHRONISM:
750 case DK_WARNING:
751 break;
753 case DK_ERROR:
754 case DK_SORRY:
755 if (m_abort_on_error)
756 real_abort ();
757 if (m_fatal_errors)
759 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
760 finish ();
761 exit (FATAL_EXIT_CODE);
763 break;
765 case DK_ICE:
766 case DK_ICE_NOBT:
768 /* Optional callback for attempting to handle ICEs gracefully. */
769 if (void (*ice_handler_cb) (diagnostic_context *) = m_ice_handler_cb)
771 /* Clear the callback, to avoid potentially re-entering
772 the routine if there's a crash within the handler. */
773 m_ice_handler_cb = NULL;
774 ice_handler_cb (this);
776 /* The context might have had diagnostic_finish called on
777 it at this point. */
779 struct backtrace_state *state = NULL;
780 if (diag_kind == DK_ICE)
781 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
782 int count = 0;
783 if (state != NULL)
784 backtrace_full (state, 2, bt_callback, bt_err_callback,
785 (void *) &count);
787 if (m_abort_on_error)
788 real_abort ();
790 if (m_report_bug)
791 fnotice (stderr, "Please submit a full bug report, "
792 "with preprocessed source.\n");
793 else
794 fnotice (stderr, "Please submit a full bug report, "
795 "with preprocessed source (by using -freport-bug).\n");
797 if (count > 0)
798 fnotice (stderr, "Please include the complete backtrace "
799 "with any bug report.\n");
800 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
802 exit (ICE_EXIT_CODE);
805 case DK_FATAL:
806 if (m_abort_on_error)
807 real_abort ();
808 finish ();
809 fnotice (stderr, "compilation terminated.\n");
810 exit (FATAL_EXIT_CODE);
812 default:
813 gcc_unreachable ();
817 /* Only dump the "In file included from..." stack once for each file. */
819 bool
820 diagnostic_context::includes_seen_p (const line_map_ordinary *map)
822 /* No include path for main. */
823 if (MAIN_FILE_P (map))
824 return true;
826 /* Always identify C++ modules, at least for now. */
827 auto probe = map;
828 if (linemap_check_ordinary (map)->reason == LC_RENAME)
829 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
830 probe = linemap_included_from_linemap (line_table, map);
831 if (MAP_MODULE_P (probe))
832 return false;
834 if (!m_includes_seen)
835 m_includes_seen = new hash_set<location_t, false, location_hash>;
837 /* Hash the location of the #include directive to better handle files
838 that are included multiple times with different macros defined. */
839 return m_includes_seen->add (linemap_included_from (map));
842 void
843 diagnostic_context::report_current_module (location_t where)
845 const line_map_ordinary *map = NULL;
847 if (pp_needs_newline (this->printer))
849 pp_newline (this->printer);
850 pp_needs_newline (this->printer) = false;
853 if (where <= BUILTINS_LOCATION)
854 return;
856 linemap_resolve_location (line_table, where,
857 LRK_MACRO_DEFINITION_LOCATION,
858 &map);
860 if (map && m_last_module != map)
862 m_last_module = map;
863 if (!includes_seen_p (map))
865 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
866 expanded_location s = {};
869 where = linemap_included_from (map);
870 map = linemap_included_from_linemap (line_table, map);
871 bool is_module = MAP_MODULE_P (map);
872 s.file = LINEMAP_FILE (map);
873 s.line = SOURCE_LINE (map, where);
874 int col = -1;
875 if (first && m_show_column)
877 s.column = SOURCE_COLUMN (map, where);
878 col = converted_column (s);
880 const char *line_col = maybe_line_and_column (s.line, col);
881 static const char *const msgs[] =
883 NULL,
884 N_(" from"),
885 N_("In file included from"), /* 2 */
886 N_(" included from"),
887 N_("In module"), /* 4 */
888 N_("of module"),
889 N_("In module imported at"), /* 6 */
890 N_("imported at"),
893 unsigned index = (was_module ? 6 : is_module ? 4
894 : need_inc ? 2 : 0) + !first;
896 pp_verbatim (this->printer, "%s%s %r%s%s%R",
897 first ? "" : was_module ? ", " : ",\n",
898 _(msgs[index]),
899 "locus", s.file, line_col);
900 first = false, need_inc = was_module, was_module = is_module;
902 while (!includes_seen_p (map));
903 pp_verbatim (this->printer, ":");
904 pp_newline (this->printer);
909 /* If DIAGNOSTIC has a diagnostic_path and this context supports
910 printing paths, print the path. */
912 void
913 diagnostic_context::show_any_path (const diagnostic_info &diagnostic)
915 const diagnostic_path *path = diagnostic.richloc->get_path ();
916 if (!path)
917 return;
919 if (m_print_path)
920 m_print_path (this, path);
923 /* class diagnostic_event. */
925 /* struct diagnostic_event::meaning. */
927 void
928 diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
930 bool need_comma = false;
931 pp_character (pp, '{');
932 if (const char *verb_str = maybe_get_verb_str (m_verb))
934 pp_printf (pp, "verb: %qs", verb_str);
935 need_comma = true;
937 if (const char *noun_str = maybe_get_noun_str (m_noun))
939 if (need_comma)
940 pp_string (pp, ", ");
941 pp_printf (pp, "noun: %qs", noun_str);
942 need_comma = true;
944 if (const char *property_str = maybe_get_property_str (m_property))
946 if (need_comma)
947 pp_string (pp, ", ");
948 pp_printf (pp, "property: %qs", property_str);
949 need_comma = true;
951 pp_character (pp, '}');
954 /* Get a string (or NULL) for V suitable for use within a SARIF
955 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
957 const char *
958 diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
960 switch (v)
962 default:
963 gcc_unreachable ();
964 case VERB_unknown:
965 return NULL;
966 case VERB_acquire:
967 return "acquire";
968 case VERB_release:
969 return "release";
970 case VERB_enter:
971 return "enter";
972 case VERB_exit:
973 return "exit";
974 case VERB_call:
975 return "call";
976 case VERB_return:
977 return "return";
978 case VERB_branch:
979 return "branch";
980 case VERB_danger:
981 return "danger";
985 /* Get a string (or NULL) for N suitable for use within a SARIF
986 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
988 const char *
989 diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
991 switch (n)
993 default:
994 gcc_unreachable ();
995 case NOUN_unknown:
996 return NULL;
997 case NOUN_taint:
998 return "taint";
999 case NOUN_sensitive:
1000 return "sensitive";
1001 case NOUN_function:
1002 return "function";
1003 case NOUN_lock:
1004 return "lock";
1005 case NOUN_memory:
1006 return "memory";
1007 case NOUN_resource:
1008 return "resource";
1012 /* Get a string (or NULL) for P suitable for use within a SARIF
1013 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
1015 const char *
1016 diagnostic_event::meaning::maybe_get_property_str (enum property p)
1018 switch (p)
1020 default:
1021 gcc_unreachable ();
1022 case PROPERTY_unknown:
1023 return NULL;
1024 case PROPERTY_true:
1025 return "true";
1026 case PROPERTY_false:
1027 return "false";
1031 /* class diagnostic_path. */
1033 /* Subroutint of diagnostic_path::interprocedural_p.
1034 Look for the first event in this path that is within a function
1035 i.e. has a non-NULL fndecl, and a non-zero stack depth.
1036 If found, write its index to *OUT_IDX and return true.
1037 Otherwise return false. */
1039 bool
1040 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
1042 const unsigned num = num_events ();
1043 for (unsigned i = 0; i < num; i++)
1045 if (!(get_event (i).get_fndecl () == NULL
1046 && get_event (i).get_stack_depth () == 0))
1048 *out_idx = i;
1049 return true;
1052 return false;
1055 /* Return true if the events in this path involve more than one
1056 function, or false if it is purely intraprocedural. */
1058 bool
1059 diagnostic_path::interprocedural_p () const
1061 /* Ignore leading events that are outside of any function. */
1062 unsigned first_fn_event_idx;
1063 if (!get_first_event_in_a_function (&first_fn_event_idx))
1064 return false;
1066 const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
1067 tree first_fndecl = first_fn_event.get_fndecl ();
1068 int first_fn_stack_depth = first_fn_event.get_stack_depth ();
1070 const unsigned num = num_events ();
1071 for (unsigned i = first_fn_event_idx + 1; i < num; i++)
1073 if (get_event (i).get_fndecl () != first_fndecl)
1074 return true;
1075 if (get_event (i).get_stack_depth () != first_fn_stack_depth)
1076 return true;
1078 return false;
1081 void
1082 default_diagnostic_starter (diagnostic_context *context,
1083 diagnostic_info *diagnostic)
1085 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
1086 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
1087 diagnostic));
1090 void
1091 default_diagnostic_start_span_fn (diagnostic_context *context,
1092 expanded_location exploc)
1094 char *text = diagnostic_get_location_text (context, exploc);
1095 pp_string (context->printer, text);
1096 free (text);
1097 pp_newline (context->printer);
1100 void
1101 default_diagnostic_finalizer (diagnostic_context *context,
1102 diagnostic_info *diagnostic,
1103 diagnostic_t)
1105 char *saved_prefix = pp_take_prefix (context->printer);
1106 pp_set_prefix (context->printer, NULL);
1107 pp_newline (context->printer);
1108 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
1109 pp_set_prefix (context->printer, saved_prefix);
1110 pp_flush (context->printer);
1113 /* Interface to specify diagnostic kind overrides. Returns the
1114 previous setting, or DK_UNSPECIFIED if the parameters are out of
1115 range. If OPTION_INDEX is zero, the new setting is for all the
1116 diagnostics. */
1117 diagnostic_t
1118 diagnostic_option_classifier::
1119 classify_diagnostic (const diagnostic_context *context,
1120 int option_index,
1121 diagnostic_t new_kind,
1122 location_t where)
1124 diagnostic_t old_kind;
1126 if (option_index < 0
1127 || option_index >= m_n_opts
1128 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1129 return DK_UNSPECIFIED;
1131 old_kind = m_classify_diagnostic[option_index];
1133 /* Handle pragmas separately, since we need to keep track of *where*
1134 the pragmas were. */
1135 if (where != UNKNOWN_LOCATION)
1137 int i;
1139 /* Record the command-line status, so we can reset it back on DK_POP. */
1140 if (old_kind == DK_UNSPECIFIED)
1142 old_kind = !context->option_enabled_p (option_index)
1143 ? DK_IGNORED : (context->warning_as_error_requested_p ()
1144 ? DK_ERROR : DK_WARNING);
1145 m_classify_diagnostic[option_index] = old_kind;
1148 for (i = m_n_classification_history - 1; i >= 0; i --)
1149 if (m_classification_history[i].option == option_index)
1151 old_kind = m_classification_history[i].kind;
1152 break;
1155 i = m_n_classification_history;
1156 m_classification_history =
1157 (diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
1158 * sizeof (diagnostic_classification_change_t));
1159 m_classification_history[i].location = where;
1160 m_classification_history[i].option = option_index;
1161 m_classification_history[i].kind = new_kind;
1162 m_n_classification_history ++;
1164 else
1165 m_classify_diagnostic[option_index] = new_kind;
1167 return old_kind;
1170 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1171 escaping rules for -fdiagnostics-parseable-fixits. */
1173 static void
1174 print_escaped_string (pretty_printer *pp, const char *text)
1176 gcc_assert (pp);
1177 gcc_assert (text);
1179 pp_character (pp, '"');
1180 for (const char *ch = text; *ch; ch++)
1182 switch (*ch)
1184 case '\\':
1185 /* Escape backslash as two backslashes. */
1186 pp_string (pp, "\\\\");
1187 break;
1188 case '\t':
1189 /* Escape tab as "\t". */
1190 pp_string (pp, "\\t");
1191 break;
1192 case '\n':
1193 /* Escape newline as "\n". */
1194 pp_string (pp, "\\n");
1195 break;
1196 case '"':
1197 /* Escape doublequotes as \". */
1198 pp_string (pp, "\\\"");
1199 break;
1200 default:
1201 if (ISPRINT (*ch))
1202 pp_character (pp, *ch);
1203 else
1204 /* Use octal for non-printable chars. */
1206 unsigned char c = (*ch & 0xff);
1207 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1209 break;
1212 pp_character (pp, '"');
1215 /* Implementation of -fdiagnostics-parseable-fixits and
1216 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1217 Print a machine-parseable version of all fixits in RICHLOC to PP,
1218 using COLUMN_UNIT to express columns.
1219 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1221 static void
1222 print_parseable_fixits (file_cache &fc,
1223 pretty_printer *pp, rich_location *richloc,
1224 enum diagnostics_column_unit column_unit,
1225 int tabstop)
1227 gcc_assert (pp);
1228 gcc_assert (richloc);
1230 char *saved_prefix = pp_take_prefix (pp);
1231 pp_set_prefix (pp, NULL);
1233 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1235 const fixit_hint *hint = richloc->get_fixit_hint (i);
1236 location_t start_loc = hint->get_start_loc ();
1237 expanded_location start_exploc = expand_location (start_loc);
1238 pp_string (pp, "fix-it:");
1239 print_escaped_string (pp, start_exploc.file);
1240 /* For compatibility with clang, print as a half-open range. */
1241 location_t next_loc = hint->get_next_loc ();
1242 expanded_location next_exploc = expand_location (next_loc);
1243 int start_col
1244 = convert_column_unit (fc, column_unit, tabstop, start_exploc);
1245 int next_col
1246 = convert_column_unit (fc, column_unit, tabstop, next_exploc);
1247 pp_printf (pp, ":{%i:%i-%i:%i}:",
1248 start_exploc.line, start_col,
1249 next_exploc.line, next_col);
1250 print_escaped_string (pp, hint->get_string ());
1251 pp_newline (pp);
1254 pp_set_prefix (pp, saved_prefix);
1257 /* Update the inlining info in this context for a DIAGNOSTIC. */
1259 void
1260 diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
1262 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1264 if (m_set_locations_cb)
1265 /* Retrieve the locations into which the expression about to be
1266 diagnosed has been inlined, including those of all the callers
1267 all the way down the inlining stack. */
1268 m_set_locations_cb (this, diagnostic);
1269 else
1271 /* When there's no callback use just the one location provided
1272 by the caller of the diagnostic function. */
1273 location_t loc = diagnostic_location (diagnostic);
1274 ilocs.safe_push (loc);
1275 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1279 /* Update the kind of DIAGNOSTIC based on its location(s), including
1280 any of those in its inlining stack, relative to any
1281 #pragma GCC diagnostic
1282 directives recorded within this object.
1284 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1285 otherwise. */
1287 diagnostic_t
1288 diagnostic_option_classifier::
1289 update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
1291 if (m_n_classification_history <= 0)
1292 return DK_UNSPECIFIED;
1294 /* Iterate over the locations, checking the diagnostic disposition
1295 for the diagnostic at each. If it's explicitly set as opposed
1296 to unspecified, update the disposition for this instance of
1297 the diagnostic and return it. */
1298 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1300 /* FIXME: Stupid search. Optimize later. */
1301 for (int i = m_n_classification_history - 1; i >= 0; i --)
1303 const diagnostic_classification_change_t &hist
1304 = m_classification_history[i];
1306 location_t pragloc = hist.location;
1307 if (!linemap_location_before_p (line_table, pragloc, loc))
1308 continue;
1310 if (hist.kind == (int) DK_POP)
1312 /* Move on to the next region. */
1313 i = hist.option;
1314 continue;
1317 int option = hist.option;
1318 /* The option 0 is for all the diagnostics. */
1319 if (option == 0 || option == diagnostic->option_index)
1321 diagnostic_t kind = hist.kind;
1322 if (kind != DK_UNSPECIFIED)
1323 diagnostic->kind = kind;
1324 return kind;
1329 return DK_UNSPECIFIED;
1332 /* Generate a URL string describing CWE. The caller is responsible for
1333 freeing the string. */
1335 char *
1336 get_cwe_url (int cwe)
1338 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1341 /* If DIAGNOSTIC has a CWE identifier, print it.
1343 For example, if the diagnostic metadata associates it with CWE-119,
1344 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1345 description of the security issue. */
1347 void
1348 diagnostic_context::print_any_cwe (const diagnostic_info &diagnostic)
1350 if (diagnostic.metadata == NULL)
1351 return;
1353 int cwe = diagnostic.metadata->get_cwe ();
1354 if (cwe)
1356 pretty_printer * const pp = this->printer;
1357 char *saved_prefix = pp_take_prefix (pp);
1358 pp_string (pp, " [");
1359 pp_string (pp, colorize_start (pp_show_color (pp),
1360 diagnostic_kind_color[diagnostic.kind]));
1361 if (pp->url_format != URL_FORMAT_NONE)
1363 char *cwe_url = get_cwe_url (cwe);
1364 pp_begin_url (pp, cwe_url);
1365 free (cwe_url);
1367 pp_printf (pp, "CWE-%i", cwe);
1368 pp_set_prefix (pp, saved_prefix);
1369 if (pp->url_format != URL_FORMAT_NONE)
1370 pp_end_url (pp);
1371 pp_string (pp, colorize_stop (pp_show_color (pp)));
1372 pp_character (pp, ']');
1376 /* If DIAGNOSTIC has any rules associated with it, print them.
1378 For example, if the diagnostic metadata associates it with a rule
1379 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1380 with any URL provided by the rule. */
1382 void
1383 diagnostic_context::print_any_rules (const diagnostic_info &diagnostic)
1385 if (diagnostic.metadata == NULL)
1386 return;
1388 for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
1390 const diagnostic_metadata::rule &rule
1391 = diagnostic.metadata->get_rule (idx);
1392 if (char *desc = rule.make_description ())
1394 pretty_printer * const pp = this->printer;
1395 char *saved_prefix = pp_take_prefix (pp);
1396 pp_string (pp, " [");
1397 pp_string (pp,
1398 colorize_start (pp_show_color (pp),
1399 diagnostic_kind_color[diagnostic.kind]));
1400 char *url = NULL;
1401 if (pp->url_format != URL_FORMAT_NONE)
1403 url = rule.make_url ();
1404 if (url)
1405 pp_begin_url (pp, url);
1407 pp_string (pp, desc);
1408 pp_set_prefix (pp, saved_prefix);
1409 if (pp->url_format != URL_FORMAT_NONE)
1410 if (url)
1411 pp_end_url (pp);
1412 free (url);
1413 pp_string (pp, colorize_stop (pp_show_color (pp)));
1414 pp_character (pp, ']');
1415 free (desc);
1420 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1421 printer, e.g. " [-Werror=uninitialized]".
1422 Subroutine of diagnostic_context::report_diagnostic. */
1424 void
1425 diagnostic_context::print_option_information (const diagnostic_info &diagnostic,
1426 diagnostic_t orig_diag_kind)
1428 if (char *option_text = make_option_name (diagnostic.option_index,
1429 orig_diag_kind, diagnostic.kind))
1431 char *option_url = nullptr;
1432 if (this->printer->url_format != URL_FORMAT_NONE)
1433 option_url = make_option_url (diagnostic.option_index);
1434 pretty_printer * const pp = this->printer;
1435 pp_string (pp, " [");
1436 pp_string (pp, colorize_start (pp_show_color (pp),
1437 diagnostic_kind_color[diagnostic.kind]));
1438 if (option_url)
1439 pp_begin_url (pp, option_url);
1440 pp_string (pp, option_text);
1441 if (option_url)
1443 pp_end_url (pp);
1444 free (option_url);
1446 pp_string (pp, colorize_stop (pp_show_color (pp)));
1447 pp_character (pp, ']');
1448 free (option_text);
1452 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1453 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1455 bool
1456 diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
1458 /* Update the inlining stack for this diagnostic. */
1459 get_any_inlining_info (diagnostic);
1461 /* Diagnostics with no option or -fpermissive are always enabled. */
1462 if (!diagnostic->option_index
1463 || diagnostic->option_index == permissive_error_option (this))
1464 return true;
1466 /* This tests if the user provided the appropriate -Wfoo or
1467 -Wno-foo option. */
1468 if (!option_enabled_p (diagnostic->option_index))
1469 return false;
1471 /* This tests for #pragma diagnostic changes. */
1472 diagnostic_t diag_class
1473 = m_option_classifier.update_effective_level_from_pragmas (diagnostic);
1475 /* This tests if the user provided the appropriate -Werror=foo
1476 option. */
1477 if (diag_class == DK_UNSPECIFIED
1478 && !option_unspecified_p (diagnostic->option_index))
1479 diagnostic->kind = m_option_classifier.get_current_override (diagnostic->option_index);
1481 /* This allows for future extensions, like temporarily disabling
1482 warnings for ranges of source code. */
1483 if (diagnostic->kind == DK_IGNORED)
1484 return false;
1486 return true;
1489 /* Returns whether warning OPT is enabled at LOC. */
1491 bool
1492 diagnostic_context::warning_enabled_at (location_t loc, int opt)
1494 if (!diagnostic_report_warnings_p (this, loc))
1495 return false;
1497 rich_location richloc (line_table, loc);
1498 diagnostic_info diagnostic = {};
1499 diagnostic.option_index = opt;
1500 diagnostic.richloc = &richloc;
1501 diagnostic.message.m_richloc = &richloc;
1502 diagnostic.kind = DK_WARNING;
1503 return diagnostic_enabled (&diagnostic);
1506 /* Report a diagnostic message (an error or a warning) as specified by
1507 this diagnostic_context.
1508 front-end independent format specifiers are exactly those described
1509 in the documentation of output_format.
1510 Return true if a diagnostic was printed, false otherwise. */
1512 bool
1513 diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
1515 diagnostic_t orig_diag_kind = diagnostic->kind;
1517 gcc_assert (m_output_format);
1519 /* Give preference to being able to inhibit warnings, before they
1520 get reclassified to something else. */
1521 bool was_warning = (diagnostic->kind == DK_WARNING
1522 || diagnostic->kind == DK_PEDWARN);
1523 if (was_warning && m_inhibit_warnings)
1524 return false;
1526 if (diagnostic->kind == DK_PEDWARN)
1528 diagnostic->kind = pedantic_warning_kind (this);
1529 /* We do this to avoid giving the message for -pedantic-errors. */
1530 orig_diag_kind = diagnostic->kind;
1533 if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p)
1534 return false;
1536 if (m_lock > 0)
1538 /* If we're reporting an ICE in the middle of some other error,
1539 try to flush out the previous error, then let this one
1540 through. Don't do this more than once. */
1541 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1542 && m_lock == 1)
1543 pp_newline_and_flush (this->printer);
1544 else
1545 error_recursion ();
1548 /* If the user requested that warnings be treated as errors, so be
1549 it. Note that we do this before the next block so that
1550 individual warnings can be overridden back to warnings with
1551 -Wno-error=*. */
1552 if (m_warning_as_error_requested
1553 && diagnostic->kind == DK_WARNING)
1554 diagnostic->kind = DK_ERROR;
1556 diagnostic->message.m_data = &diagnostic->x_data;
1558 /* Check to see if the diagnostic is enabled at the location and
1559 not disabled by #pragma GCC diagnostic anywhere along the inlining
1560 stack. . */
1561 if (!diagnostic_enabled (diagnostic))
1562 return false;
1564 if ((was_warning || diagnostic->kind == DK_WARNING)
1565 && ((!m_warn_system_headers
1566 && diagnostic->m_iinfo.m_allsyslocs)
1567 || m_inhibit_warnings))
1568 /* Bail if the warning is not to be reported because all locations in the
1569 inlining stack (if there is one) are in system headers. */
1570 return false;
1572 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1573 diagnostic_check_max_errors (this);
1575 m_lock++;
1577 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1579 /* When not checking, ICEs are converted to fatal errors when an
1580 error has already occurred. This is counteracted by
1581 abort_on_error. */
1582 if (!CHECKING_P
1583 && (m_diagnostic_count[DK_ERROR] > 0
1584 || m_diagnostic_count[DK_SORRY] > 0)
1585 && !m_abort_on_error)
1587 expanded_location s
1588 = expand_location (diagnostic_location (diagnostic));
1589 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1590 s.file, s.line);
1591 exit (ICE_EXIT_CODE);
1593 if (m_internal_error)
1594 (*m_internal_error) (this,
1595 diagnostic->message.m_format_spec,
1596 diagnostic->message.m_args_ptr);
1598 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1599 ++m_diagnostic_count[DK_WERROR];
1600 else
1601 ++m_diagnostic_count[diagnostic->kind];
1603 /* Is this the initial diagnostic within the stack of groups? */
1604 if (m_diagnostic_groups.m_emission_count == 0)
1605 m_output_format->on_begin_group ();
1606 m_diagnostic_groups.m_emission_count++;
1608 pp_format (this->printer, &diagnostic->message, m_urlifier);
1609 m_output_format->on_begin_diagnostic (diagnostic);
1610 pp_output_formatted_text (this->printer);
1611 if (m_show_cwe)
1612 print_any_cwe (*diagnostic);
1613 if (m_show_rules)
1614 print_any_rules (*diagnostic);
1615 if (m_show_option_requested)
1616 print_option_information (*diagnostic, orig_diag_kind);
1617 m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind);
1618 switch (m_extra_output_kind)
1620 default:
1621 break;
1622 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1623 print_parseable_fixits (get_file_cache (),
1624 this->printer, diagnostic->richloc,
1625 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1626 m_tabstop);
1627 pp_flush (this->printer);
1628 break;
1629 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1630 print_parseable_fixits (get_file_cache (),
1631 this->printer, diagnostic->richloc,
1632 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1633 m_tabstop);
1634 pp_flush (this->printer);
1635 break;
1637 diagnostic_action_after_output (this, diagnostic->kind);
1638 diagnostic->x_data = NULL;
1640 if (m_edit_context_ptr)
1641 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1642 m_edit_context_ptr->add_fixits (diagnostic->richloc);
1644 m_lock--;
1646 show_any_path (*diagnostic);
1648 return true;
1651 /* Get the number of digits in the decimal representation of VALUE. */
1654 num_digits (int value)
1656 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1657 using floating point. */
1658 gcc_assert (value >= 0);
1660 if (value == 0)
1661 return 1;
1663 int digits = 0;
1664 while (value > 0)
1666 digits++;
1667 value /= 10;
1669 return digits;
1672 /* Given a partial pathname as input, return another pathname that
1673 shares no directory elements with the pathname of __FILE__. This
1674 is used by fancy_abort() to print `internal compiler error in expr.cc'
1675 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1677 const char *
1678 trim_filename (const char *name)
1680 static const char this_file[] = __FILE__;
1681 const char *p = name, *q = this_file;
1683 /* First skip any "../" in each filename. This allows us to give a proper
1684 reference to a file in a subdirectory. */
1685 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1686 p += 3;
1688 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1689 q += 3;
1691 /* Now skip any parts the two filenames have in common. */
1692 while (*p == *q && *p != 0 && *q != 0)
1693 p++, q++;
1695 /* Now go backwards until the previous directory separator. */
1696 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1697 p--;
1699 return p;
1702 /* Standard error reporting routines in increasing order of severity.
1703 All of these take arguments like printf. */
1705 /* Text to be emitted verbatim to the error message stream; this
1706 produces no prefix and disables line-wrapping. Use rarely. */
1707 void
1708 verbatim (const char *gmsgid, ...)
1710 va_list ap;
1712 va_start (ap, gmsgid);
1713 text_info text (_(gmsgid), &ap, errno);
1714 pp_format_verbatim (global_dc->printer, &text);
1715 pp_newline_and_flush (global_dc->printer);
1716 va_end (ap);
1719 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1720 void
1721 diagnostic_append_note (diagnostic_context *context,
1722 location_t location,
1723 const char * gmsgid, ...)
1725 diagnostic_info diagnostic;
1726 va_list ap;
1727 rich_location richloc (line_table, location);
1729 va_start (ap, gmsgid);
1730 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1731 if (context->m_inhibit_notes_p)
1733 va_end (ap);
1734 return;
1736 char *saved_prefix = pp_take_prefix (context->printer);
1737 pp_set_prefix (context->printer,
1738 diagnostic_build_prefix (context, &diagnostic));
1739 pp_format (context->printer, &diagnostic.message);
1740 pp_output_formatted_text (context->printer);
1741 pp_destroy_prefix (context->printer);
1742 pp_set_prefix (context->printer, saved_prefix);
1743 pp_newline (context->printer);
1744 diagnostic_show_locus (context, &richloc, DK_NOTE);
1745 va_end (ap);
1748 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1749 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1750 and internal_error_no_backtrace, as documented and defined below. */
1751 static bool
1752 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1753 int opt, const char *gmsgid,
1754 va_list *ap, diagnostic_t kind)
1756 diagnostic_info diagnostic;
1757 if (kind == DK_PERMERROR)
1759 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1760 permissive_error_kind (global_dc));
1761 diagnostic.option_index = (opt != -1 ? opt
1762 : permissive_error_option (global_dc));
1764 else
1766 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1767 if (kind == DK_WARNING || kind == DK_PEDWARN)
1768 diagnostic.option_index = opt;
1770 diagnostic.metadata = metadata;
1771 return global_dc->report_diagnostic (&diagnostic);
1774 /* Implement inform_n, warning_n, and error_n, as documented and
1775 defined below. */
1776 static bool
1777 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1778 int opt, unsigned HOST_WIDE_INT n,
1779 const char *singular_gmsgid,
1780 const char *plural_gmsgid,
1781 va_list *ap, diagnostic_t kind)
1783 diagnostic_info diagnostic;
1784 unsigned long gtn;
1786 if (sizeof n <= sizeof gtn)
1787 gtn = n;
1788 else
1789 /* Use the largest number ngettext can handle, otherwise
1790 preserve the six least significant decimal digits for
1791 languages where the plural form depends on them. */
1792 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1794 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1795 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1796 if (kind == DK_WARNING)
1797 diagnostic.option_index = opt;
1798 diagnostic.metadata = metadata;
1799 return global_dc->report_diagnostic (&diagnostic);
1802 /* Wrapper around diagnostic_impl taking a variable argument list. */
1804 bool
1805 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1806 const char *gmsgid, ...)
1808 auto_diagnostic_group d;
1809 va_list ap;
1810 va_start (ap, gmsgid);
1811 rich_location richloc (line_table, location);
1812 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1813 va_end (ap);
1814 return ret;
1817 /* As above, but for rich_location *. */
1819 bool
1820 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1821 const char *gmsgid, ...)
1823 auto_diagnostic_group d;
1824 va_list ap;
1825 va_start (ap, gmsgid);
1826 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1827 va_end (ap);
1828 return ret;
1831 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1833 bool
1834 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1835 const char *gmsgid, va_list *ap)
1837 rich_location richloc (line_table, location);
1838 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1841 /* An informative note at LOCATION. Use this for additional details on an error
1842 message. */
1843 void
1844 inform (location_t location, const char *gmsgid, ...)
1846 auto_diagnostic_group d;
1847 va_list ap;
1848 va_start (ap, gmsgid);
1849 rich_location richloc (line_table, location);
1850 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1851 va_end (ap);
1854 /* Same as "inform" above, but at RICHLOC. */
1855 void
1856 inform (rich_location *richloc, const char *gmsgid, ...)
1858 gcc_assert (richloc);
1860 auto_diagnostic_group d;
1861 va_list ap;
1862 va_start (ap, gmsgid);
1863 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1864 va_end (ap);
1867 /* An informative note at LOCATION. Use this for additional details on an
1868 error message. */
1869 void
1870 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1871 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1873 va_list ap;
1874 va_start (ap, plural_gmsgid);
1875 auto_diagnostic_group d;
1876 rich_location richloc (line_table, location);
1877 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1878 &ap, DK_NOTE);
1879 va_end (ap);
1882 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1883 to the relevant language specification but is likely to be buggy anyway.
1884 Returns true if the warning was printed, false if it was inhibited. */
1885 bool
1886 warning (int opt, const char *gmsgid, ...)
1888 auto_diagnostic_group d;
1889 va_list ap;
1890 va_start (ap, gmsgid);
1891 rich_location richloc (line_table, input_location);
1892 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1893 va_end (ap);
1894 return ret;
1897 /* A warning at LOCATION. Use this for code which is correct according to the
1898 relevant language specification but is likely to be buggy anyway.
1899 Returns true if the warning was printed, false if it was inhibited. */
1901 bool
1902 warning_at (location_t location, int opt, const char *gmsgid, ...)
1904 auto_diagnostic_group d;
1905 va_list ap;
1906 va_start (ap, gmsgid);
1907 rich_location richloc (line_table, location);
1908 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1909 va_end (ap);
1910 return ret;
1913 /* Same as "warning at" above, but using RICHLOC. */
1915 bool
1916 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1918 gcc_assert (richloc);
1920 auto_diagnostic_group d;
1921 va_list ap;
1922 va_start (ap, gmsgid);
1923 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1924 va_end (ap);
1925 return ret;
1928 /* Same as "warning at" above, but using METADATA. */
1930 bool
1931 warning_meta (rich_location *richloc,
1932 const diagnostic_metadata &metadata,
1933 int opt, const char *gmsgid, ...)
1935 gcc_assert (richloc);
1937 auto_diagnostic_group d;
1938 va_list ap;
1939 va_start (ap, gmsgid);
1940 bool ret
1941 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1942 DK_WARNING);
1943 va_end (ap);
1944 return ret;
1947 /* Same as warning_n plural variant below, but using RICHLOC. */
1949 bool
1950 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1951 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1953 gcc_assert (richloc);
1955 auto_diagnostic_group d;
1956 va_list ap;
1957 va_start (ap, plural_gmsgid);
1958 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1959 singular_gmsgid, plural_gmsgid,
1960 &ap, DK_WARNING);
1961 va_end (ap);
1962 return ret;
1965 /* A warning at LOCATION. Use this for code which is correct according to the
1966 relevant language specification but is likely to be buggy anyway.
1967 Returns true if the warning was printed, false if it was inhibited. */
1969 bool
1970 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1971 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1973 auto_diagnostic_group d;
1974 va_list ap;
1975 va_start (ap, plural_gmsgid);
1976 rich_location richloc (line_table, location);
1977 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1978 singular_gmsgid, plural_gmsgid,
1979 &ap, DK_WARNING);
1980 va_end (ap);
1981 return ret;
1984 /* A "pedantic" warning at LOCATION: issues a warning unless
1985 -pedantic-errors was given on the command line, in which case it
1986 issues an error. Use this for diagnostics required by the relevant
1987 language standard, if you have chosen not to make them errors.
1989 Note that these diagnostics are issued independent of the setting
1990 of the -Wpedantic command-line switch. To get a warning enabled
1991 only with that switch, use either "if (pedantic) pedwarn
1992 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1993 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1995 Returns true if the warning was printed, false if it was inhibited. */
1997 bool
1998 pedwarn (location_t location, int opt, const char *gmsgid, ...)
2000 auto_diagnostic_group d;
2001 va_list ap;
2002 va_start (ap, gmsgid);
2003 rich_location richloc (line_table, location);
2004 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2005 va_end (ap);
2006 return ret;
2009 /* Same as pedwarn above, but using RICHLOC. */
2011 bool
2012 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
2014 gcc_assert (richloc);
2016 auto_diagnostic_group d;
2017 va_list ap;
2018 va_start (ap, gmsgid);
2019 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2020 va_end (ap);
2021 return ret;
2024 /* A "permissive" error at LOCATION: issues an error unless
2025 -fpermissive was given on the command line, in which case it issues
2026 a warning. Use this for things that really should be errors but we
2027 want to support legacy code.
2029 Returns true if the warning was printed, false if it was inhibited. */
2031 bool
2032 permerror (location_t location, const char *gmsgid, ...)
2034 auto_diagnostic_group d;
2035 va_list ap;
2036 va_start (ap, gmsgid);
2037 rich_location richloc (line_table, location);
2038 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2039 va_end (ap);
2040 return ret;
2043 /* Same as "permerror" above, but at RICHLOC. */
2045 bool
2046 permerror (rich_location *richloc, const char *gmsgid, ...)
2048 gcc_assert (richloc);
2050 auto_diagnostic_group d;
2051 va_list ap;
2052 va_start (ap, gmsgid);
2053 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2054 va_end (ap);
2055 return ret;
2058 /* Similar to the above, but controlled by a flag other than -fpermissive.
2059 As above, an error by default or a warning with -fpermissive, but this
2060 diagnostic can also be downgraded by -Wno-error=opt. */
2062 bool
2063 permerror_opt (location_t location, int opt, const char *gmsgid, ...)
2065 auto_diagnostic_group d;
2066 va_list ap;
2067 va_start (ap, gmsgid);
2068 rich_location richloc (line_table, location);
2069 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2070 va_end (ap);
2071 return ret;
2074 /* Same as "permerror" above, but at RICHLOC. */
2076 bool
2077 permerror_opt (rich_location *richloc, int opt, const char *gmsgid, ...)
2079 gcc_assert (richloc);
2081 auto_diagnostic_group d;
2082 va_list ap;
2083 va_start (ap, gmsgid);
2084 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2085 va_end (ap);
2086 return ret;
2089 /* A hard error: the code is definitely ill-formed, and an object file
2090 will not be produced. */
2091 void
2092 error (const char *gmsgid, ...)
2094 auto_diagnostic_group d;
2095 va_list ap;
2096 va_start (ap, gmsgid);
2097 rich_location richloc (line_table, input_location);
2098 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2099 va_end (ap);
2102 /* A hard error: the code is definitely ill-formed, and an object file
2103 will not be produced. */
2104 void
2105 error_n (location_t location, unsigned HOST_WIDE_INT n,
2106 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2108 auto_diagnostic_group d;
2109 va_list ap;
2110 va_start (ap, plural_gmsgid);
2111 rich_location richloc (line_table, location);
2112 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2113 &ap, DK_ERROR);
2114 va_end (ap);
2117 /* Same as above, but use location LOC instead of input_location. */
2118 void
2119 error_at (location_t loc, const char *gmsgid, ...)
2121 auto_diagnostic_group d;
2122 va_list ap;
2123 va_start (ap, gmsgid);
2124 rich_location richloc (line_table, loc);
2125 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2126 va_end (ap);
2129 /* Same as above, but use RICH_LOC. */
2131 void
2132 error_at (rich_location *richloc, const char *gmsgid, ...)
2134 gcc_assert (richloc);
2136 auto_diagnostic_group d;
2137 va_list ap;
2138 va_start (ap, gmsgid);
2139 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2140 va_end (ap);
2143 /* Same as above, but with metadata. */
2145 void
2146 error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
2147 const char *gmsgid, ...)
2149 gcc_assert (richloc);
2151 auto_diagnostic_group d;
2152 va_list ap;
2153 va_start (ap, gmsgid);
2154 diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
2155 va_end (ap);
2158 /* "Sorry, not implemented." Use for a language feature which is
2159 required by the relevant specification but not implemented by GCC.
2160 An object file will not be produced. */
2161 void
2162 sorry (const char *gmsgid, ...)
2164 auto_diagnostic_group d;
2165 va_list ap;
2166 va_start (ap, gmsgid);
2167 rich_location richloc (line_table, input_location);
2168 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2169 va_end (ap);
2172 /* Same as above, but use location LOC instead of input_location. */
2173 void
2174 sorry_at (location_t loc, const char *gmsgid, ...)
2176 auto_diagnostic_group d;
2177 va_list ap;
2178 va_start (ap, gmsgid);
2179 rich_location richloc (line_table, loc);
2180 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2181 va_end (ap);
2184 /* Return true if an error or a "sorry" has been seen. Various
2185 processing is disabled after errors. */
2186 bool
2187 seen_error (void)
2189 return errorcount || sorrycount;
2192 /* An error which is severe enough that we make no attempt to
2193 continue. Do not use this for internal consistency checks; that's
2194 internal_error. Use of this function should be rare. */
2195 void
2196 fatal_error (location_t loc, const char *gmsgid, ...)
2198 auto_diagnostic_group d;
2199 va_list ap;
2200 va_start (ap, gmsgid);
2201 rich_location richloc (line_table, loc);
2202 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2203 va_end (ap);
2205 gcc_unreachable ();
2208 /* An internal consistency check has failed. We make no attempt to
2209 continue. */
2210 void
2211 internal_error (const char *gmsgid, ...)
2213 auto_diagnostic_group d;
2214 va_list ap;
2215 va_start (ap, gmsgid);
2216 rich_location richloc (line_table, input_location);
2217 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2218 va_end (ap);
2220 gcc_unreachable ();
2223 /* Like internal_error, but no backtrace will be printed. Used when
2224 the internal error does not happen at the current location, but happened
2225 somewhere else. */
2226 void
2227 internal_error_no_backtrace (const char *gmsgid, ...)
2229 auto_diagnostic_group d;
2230 va_list ap;
2231 va_start (ap, gmsgid);
2232 rich_location richloc (line_table, input_location);
2233 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2234 va_end (ap);
2236 gcc_unreachable ();
2239 /* Emit DIAGRAM to this context, respecting the output format. */
2241 void
2242 diagnostic_context::emit_diagram (const diagnostic_diagram &diagram)
2244 if (m_diagrams.m_theme == nullptr)
2245 return;
2247 gcc_assert (m_output_format);
2248 m_output_format->on_diagram (diagram);
2251 /* Special case error functions. Most are implemented in terms of the
2252 above, or should be. */
2254 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2255 runs its second argument through gettext. */
2256 void
2257 fnotice (FILE *file, const char *cmsgid, ...)
2259 va_list ap;
2261 va_start (ap, cmsgid);
2262 vfprintf (file, _(cmsgid), ap);
2263 va_end (ap);
2266 /* Inform the user that an error occurred while trying to report some
2267 other error. This indicates catastrophic internal inconsistencies,
2268 so give up now. But do try to flush out the previous error.
2269 This mustn't use internal_error, that will cause infinite recursion. */
2271 void
2272 diagnostic_context::error_recursion ()
2274 if (m_lock < 3)
2275 pp_newline_and_flush (this->printer);
2277 fnotice (stderr,
2278 "internal compiler error: error reporting routines re-entered.\n");
2280 /* Call diagnostic_action_after_output to get the "please submit a bug
2281 report" message. */
2282 diagnostic_action_after_output (this, DK_ICE);
2284 /* Do not use gcc_unreachable here; that goes through internal_error
2285 and therefore would cause infinite recursion. */
2286 real_abort ();
2289 /* Report an internal compiler error in a friendly manner. This is
2290 the function that gets called upon use of abort() in the source
2291 code generally, thanks to a special macro. */
2293 void
2294 fancy_abort (const char *file, int line, const char *function)
2296 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2297 internal_error will crash internally in a way that prevents a
2298 useful message reaching the user.
2299 This can happen with libgccjit in the case of gcc_assert failures
2300 that occur outside of the libgccjit mutex that guards the rest of
2301 gcc's state, including global_dc (when global_dc may not be
2302 initialized yet, or might be in use by another thread).
2303 Handle such cases as gracefully as possible by falling back to a
2304 minimal abort handler that only relies on i18n. */
2305 if (global_dc->printer == NULL)
2307 /* Print the error message. */
2308 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2309 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2310 fputc ('\n', stderr);
2312 /* Attempt to print a backtrace. */
2313 struct backtrace_state *state
2314 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2315 int count = 0;
2316 if (state != NULL)
2317 backtrace_full (state, 2, bt_callback, bt_err_callback,
2318 (void *) &count);
2320 /* We can't call warn_if_plugins or emergency_dump_function as these
2321 rely on GCC state that might not be initialized, or might be in
2322 use by another thread. */
2324 /* Abort the process. */
2325 real_abort ();
2328 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2331 /* class diagnostic_context. */
2333 void
2334 diagnostic_context::begin_group ()
2336 m_diagnostic_groups.m_nesting_depth++;
2339 void
2340 diagnostic_context::end_group ()
2342 if (--m_diagnostic_groups.m_nesting_depth == 0)
2344 /* Handle the case where we've popped the final diagnostic group.
2345 If any diagnostics were emitted, give the context a chance
2346 to do something. */
2347 if (m_diagnostic_groups.m_emission_count > 0)
2348 m_output_format->on_end_group ();
2349 m_diagnostic_groups.m_emission_count = 0;
2353 /* class auto_diagnostic_group. */
2355 /* Constructor: "push" this group into global_dc. */
2357 auto_diagnostic_group::auto_diagnostic_group ()
2359 global_dc->begin_group ();
2362 /* Destructor: "pop" this group from global_dc. */
2364 auto_diagnostic_group::~auto_diagnostic_group ()
2366 global_dc->end_group ();
2369 /* class diagnostic_text_output_format : public diagnostic_output_format. */
2371 diagnostic_text_output_format::~diagnostic_text_output_format ()
2373 /* Some of the errors may actually have been warnings. */
2374 if (m_context.diagnostic_count (DK_WERROR))
2376 /* -Werror was given. */
2377 if (m_context.warning_as_error_requested_p ())
2378 pp_verbatim (m_context.printer,
2379 _("%s: all warnings being treated as errors"),
2380 progname);
2381 /* At least one -Werror= was given. */
2382 else
2383 pp_verbatim (m_context.printer,
2384 _("%s: some warnings being treated as errors"),
2385 progname);
2386 pp_newline_and_flush (m_context.printer);
2390 void
2391 diagnostic_text_output_format::on_begin_diagnostic (diagnostic_info *diagnostic)
2393 (*diagnostic_starter (&m_context)) (&m_context, diagnostic);
2396 void
2397 diagnostic_text_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
2398 diagnostic_t orig_diag_kind)
2400 (*diagnostic_finalizer (&m_context)) (&m_context, diagnostic, orig_diag_kind);
2403 void
2404 diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
2406 char *saved_prefix = pp_take_prefix (m_context.printer);
2407 pp_set_prefix (m_context.printer, NULL);
2408 /* Use a newline before and after and a two-space indent
2409 to make the diagram stand out a little from the wall of text. */
2410 pp_newline (m_context.printer);
2411 diagram.get_canvas ().print_to_pp (m_context.printer, " ");
2412 pp_newline (m_context.printer);
2413 pp_set_prefix (m_context.printer, saved_prefix);
2414 pp_flush (m_context.printer);
2417 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2418 file-based output formats. */
2420 void
2421 diagnostic_output_format_init (diagnostic_context *context,
2422 const char *base_file_name,
2423 enum diagnostics_output_format format)
2425 switch (format)
2427 default:
2428 gcc_unreachable ();
2429 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2430 /* The default; do nothing. */
2431 break;
2433 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2434 diagnostic_output_format_init_json_stderr (context);
2435 break;
2437 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2438 diagnostic_output_format_init_json_file (context, base_file_name);
2439 break;
2441 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2442 diagnostic_output_format_init_sarif_stderr (context);
2443 break;
2445 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2446 diagnostic_output_format_init_sarif_file (context, base_file_name);
2447 break;
2451 /* Initialize this context's m_diagrams based on CHARSET.
2452 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2453 (or NULL for "no diagrams"). */
2455 void
2456 diagnostic_context::
2457 set_text_art_charset (enum diagnostic_text_art_charset charset)
2459 delete m_diagrams.m_theme;
2460 switch (charset)
2462 default:
2463 gcc_unreachable ();
2465 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
2466 m_diagrams.m_theme = nullptr;
2467 break;
2469 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
2470 m_diagrams.m_theme = new text_art::ascii_theme ();
2471 break;
2473 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
2474 m_diagrams.m_theme = new text_art::unicode_theme ();
2475 break;
2477 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
2478 m_diagrams.m_theme = new text_art::emoji_theme ();
2479 break;
2483 /* class simple_diagnostic_path : public diagnostic_path. */
2485 simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
2486 : m_event_pp (event_pp)
2488 add_thread ("main");
2491 /* Implementation of diagnostic_path::num_events vfunc for
2492 simple_diagnostic_path: simply get the number of events in the vec. */
2494 unsigned
2495 simple_diagnostic_path::num_events () const
2497 return m_events.length ();
2500 /* Implementation of diagnostic_path::get_event vfunc for
2501 simple_diagnostic_path: simply return the event in the vec. */
2503 const diagnostic_event &
2504 simple_diagnostic_path::get_event (int idx) const
2506 return *m_events[idx];
2509 unsigned
2510 simple_diagnostic_path::num_threads () const
2512 return m_threads.length ();
2515 const diagnostic_thread &
2516 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
2518 return *m_threads[idx];
2521 diagnostic_thread_id_t
2522 simple_diagnostic_path::add_thread (const char *name)
2524 m_threads.safe_push (new simple_diagnostic_thread (name));
2525 return m_threads.length () - 1;
2528 /* Add an event to this path at LOC within function FNDECL at
2529 stack depth DEPTH.
2531 Use m_context's printer to format FMT, as the text of the new
2532 event.
2534 Return the id of the new event. */
2536 diagnostic_event_id_t
2537 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2538 const char *fmt, ...)
2540 pretty_printer *pp = m_event_pp;
2541 pp_clear_output_area (pp);
2543 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2545 va_list ap;
2547 va_start (ap, fmt);
2549 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2550 pp_format (pp, &ti);
2551 pp_output_formatted_text (pp);
2553 va_end (ap);
2555 simple_diagnostic_event *new_event
2556 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2557 m_events.safe_push (new_event);
2559 pp_clear_output_area (pp);
2561 return diagnostic_event_id_t (m_events.length () - 1);
2564 diagnostic_event_id_t
2565 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
2566 location_t loc,
2567 tree fndecl,
2568 int depth,
2569 const char *fmt, ...)
2571 pretty_printer *pp = m_event_pp;
2572 pp_clear_output_area (pp);
2574 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2576 va_list ap;
2578 va_start (ap, fmt);
2580 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2582 pp_format (pp, &ti);
2583 pp_output_formatted_text (pp);
2585 va_end (ap);
2587 simple_diagnostic_event *new_event
2588 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
2589 thread_id);
2590 m_events.safe_push (new_event);
2592 pp_clear_output_area (pp);
2594 return diagnostic_event_id_t (m_events.length () - 1);
2597 /* struct simple_diagnostic_event. */
2599 /* simple_diagnostic_event's ctor. */
2601 simple_diagnostic_event::
2602 simple_diagnostic_event (location_t loc,
2603 tree fndecl,
2604 int depth,
2605 const char *desc,
2606 diagnostic_thread_id_t thread_id)
2607 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
2608 m_thread_id (thread_id)
2612 /* simple_diagnostic_event's dtor. */
2614 simple_diagnostic_event::~simple_diagnostic_event ()
2616 free (m_desc);
2619 /* Print PATH by emitting a dummy "note" associated with it. */
2621 DEBUG_FUNCTION
2622 void debug (diagnostic_path *path)
2624 rich_location richloc (line_table, UNKNOWN_LOCATION);
2625 richloc.set_path (path);
2626 inform (&richloc, "debug path");
2629 /* Really call the system 'abort'. This has to go right at the end of
2630 this file, so that there are no functions after it that call abort
2631 and get the system abort instead of our macro. */
2632 #undef abort
2633 static void
2634 real_abort (void)
2636 abort ();
2639 #if CHECKING_P
2641 namespace selftest {
2643 /* Helper function for test_print_escaped_string. */
2645 static void
2646 assert_print_escaped_string (const location &loc, const char *expected_output,
2647 const char *input)
2649 pretty_printer pp;
2650 print_escaped_string (&pp, input);
2651 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2654 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2655 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2657 /* Tests of print_escaped_string. */
2659 static void
2660 test_print_escaped_string ()
2662 /* Empty string. */
2663 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2665 /* Non-empty string. */
2666 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2668 /* Various things that need to be escaped: */
2669 /* Backslash. */
2670 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2671 "before\\after");
2672 /* Tab. */
2673 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2674 "before\tafter");
2675 /* Newline. */
2676 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2677 "before\nafter");
2678 /* Double quote. */
2679 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2680 "before\"after");
2682 /* Non-printable characters: BEL: '\a': 0x07 */
2683 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2684 "before\aafter");
2685 /* Non-printable characters: vertical tab: '\v': 0x0b */
2686 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2687 "before\vafter");
2690 /* Tests of print_parseable_fixits. */
2692 /* Verify that print_parseable_fixits emits the empty string if there
2693 are no fixits. */
2695 static void
2696 test_print_parseable_fixits_none ()
2698 pretty_printer pp;
2699 file_cache fc;
2700 rich_location richloc (line_table, UNKNOWN_LOCATION);
2702 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2703 ASSERT_STREQ ("", pp_formatted_text (&pp));
2706 /* Verify that print_parseable_fixits does the right thing if there
2707 is an insertion fixit hint. */
2709 static void
2710 test_print_parseable_fixits_insert ()
2712 pretty_printer pp;
2713 file_cache fc;
2714 rich_location richloc (line_table, UNKNOWN_LOCATION);
2716 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2717 linemap_line_start (line_table, 5, 100);
2718 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2719 location_t where = linemap_position_for_column (line_table, 10);
2720 richloc.add_fixit_insert_before (where, "added content");
2722 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2723 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2724 pp_formatted_text (&pp));
2727 /* Verify that print_parseable_fixits does the right thing if there
2728 is an removal fixit hint. */
2730 static void
2731 test_print_parseable_fixits_remove ()
2733 pretty_printer pp;
2734 file_cache fc;
2735 rich_location richloc (line_table, UNKNOWN_LOCATION);
2737 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2738 linemap_line_start (line_table, 5, 100);
2739 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2740 source_range where;
2741 where.m_start = linemap_position_for_column (line_table, 10);
2742 where.m_finish = linemap_position_for_column (line_table, 20);
2743 richloc.add_fixit_remove (where);
2745 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2746 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2747 pp_formatted_text (&pp));
2750 /* Verify that print_parseable_fixits does the right thing if there
2751 is an replacement fixit hint. */
2753 static void
2754 test_print_parseable_fixits_replace ()
2756 pretty_printer pp;
2757 file_cache fc;
2758 rich_location richloc (line_table, UNKNOWN_LOCATION);
2760 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2761 linemap_line_start (line_table, 5, 100);
2762 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2763 source_range where;
2764 where.m_start = linemap_position_for_column (line_table, 10);
2765 where.m_finish = linemap_position_for_column (line_table, 20);
2766 richloc.add_fixit_replace (where, "replacement");
2768 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2769 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2770 pp_formatted_text (&pp));
2773 /* Verify that print_parseable_fixits correctly handles
2774 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2776 static void
2777 test_print_parseable_fixits_bytes_vs_display_columns ()
2779 line_table_test ltt;
2780 rich_location richloc (line_table, UNKNOWN_LOCATION);
2782 /* 1-based byte offsets: 12345677778888999900001234567. */
2783 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2784 /* 1-based display cols: 123456[......7-8.....]9012345. */
2785 const int tabstop = 8;
2787 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2788 file_cache fc;
2789 const char *const fname = tmp.get_filename ();
2791 linemap_add (line_table, LC_ENTER, false, fname, 0);
2792 linemap_line_start (line_table, 1, 100);
2793 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2794 source_range where;
2795 where.m_start = linemap_position_for_column (line_table, 12);
2796 where.m_finish = linemap_position_for_column (line_table, 17);
2797 richloc.add_fixit_replace (where, "color");
2799 /* Escape fname. */
2800 pretty_printer tmp_pp;
2801 print_escaped_string (&tmp_pp, fname);
2802 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2804 const int buf_len = strlen (escaped_fname) + 100;
2805 char *const expected = XNEWVEC (char, buf_len);
2808 pretty_printer pp;
2809 print_parseable_fixits (fc, &pp, &richloc,
2810 DIAGNOSTICS_COLUMN_UNIT_BYTE,
2811 tabstop);
2812 snprintf (expected, buf_len,
2813 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2814 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2817 pretty_printer pp;
2818 print_parseable_fixits (fc, &pp, &richloc,
2819 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2820 tabstop);
2821 snprintf (expected, buf_len,
2822 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2823 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2826 XDELETEVEC (expected);
2827 free (escaped_fname);
2830 /* Verify that
2831 diagnostic_get_location_text (..., SHOW_COLUMN)
2832 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2833 colorization disabled. */
2835 static void
2836 assert_location_text (const char *expected_loc_text,
2837 const char *filename, int line, int column,
2838 bool show_column,
2839 int origin = 1,
2840 enum diagnostics_column_unit column_unit
2841 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2843 test_diagnostic_context dc;
2844 dc.m_show_column = show_column;
2845 dc.m_column_unit = column_unit;
2846 dc.m_column_origin = origin;
2848 expanded_location xloc;
2849 xloc.file = filename;
2850 xloc.line = line;
2851 xloc.column = column;
2852 xloc.data = NULL;
2853 xloc.sysp = false;
2855 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2856 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2857 free (actual_loc_text);
2860 /* Verify that diagnostic_get_location_text works as expected. */
2862 static void
2863 test_diagnostic_get_location_text ()
2865 const char *old_progname = progname;
2866 progname = "PROGNAME";
2867 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2868 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2869 assert_location_text (built_in_colon, special_fname_builtin (),
2870 42, 10, true);
2871 free (built_in_colon);
2872 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2873 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2874 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2875 for (int origin = 0; origin != 2; ++origin)
2876 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2877 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2878 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2879 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2881 maybe_line_and_column (INT_MAX, INT_MAX);
2882 maybe_line_and_column (INT_MIN, INT_MIN);
2885 /* In order to test display columns vs byte columns, we need to create a
2886 file for location_get_source_line() to read. */
2888 const char *const content = "smile \xf0\x9f\x98\x82\n";
2889 const int line_bytes = strlen (content) - 1;
2890 const int def_tabstop = 8;
2891 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2892 const int display_width = cpp_display_width (content, line_bytes, policy);
2893 ASSERT_EQ (line_bytes - 2, display_width);
2894 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2895 const char *const fname = tmp.get_filename ();
2896 const int buf_len = strlen (fname) + 16;
2897 char *const expected = XNEWVEC (char, buf_len);
2899 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2900 assert_location_text (expected, fname, 1, line_bytes, true,
2901 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2903 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2904 assert_location_text (expected, fname, 1, line_bytes, true,
2905 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2907 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2908 assert_location_text (expected, fname, 1, line_bytes, true,
2909 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2911 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2912 assert_location_text (expected, fname, 1, line_bytes, true,
2913 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2915 XDELETEVEC (expected);
2919 progname = old_progname;
2922 /* Selftest for num_digits. */
2924 static void
2925 test_num_digits ()
2927 ASSERT_EQ (1, num_digits (0));
2928 ASSERT_EQ (1, num_digits (9));
2929 ASSERT_EQ (2, num_digits (10));
2930 ASSERT_EQ (2, num_digits (99));
2931 ASSERT_EQ (3, num_digits (100));
2932 ASSERT_EQ (3, num_digits (999));
2933 ASSERT_EQ (4, num_digits (1000));
2934 ASSERT_EQ (4, num_digits (9999));
2935 ASSERT_EQ (5, num_digits (10000));
2936 ASSERT_EQ (5, num_digits (99999));
2937 ASSERT_EQ (6, num_digits (100000));
2938 ASSERT_EQ (6, num_digits (999999));
2939 ASSERT_EQ (7, num_digits (1000000));
2940 ASSERT_EQ (7, num_digits (9999999));
2941 ASSERT_EQ (8, num_digits (10000000));
2942 ASSERT_EQ (8, num_digits (99999999));
2945 /* Run all of the selftests within this file. */
2947 void
2948 c_diagnostic_cc_tests ()
2950 test_print_escaped_string ();
2951 test_print_parseable_fixits_none ();
2952 test_print_parseable_fixits_insert ();
2953 test_print_parseable_fixits_remove ();
2954 test_print_parseable_fixits_replace ();
2955 test_print_parseable_fixits_bytes_vs_display_columns ();
2956 test_diagnostic_get_location_text ();
2957 test_num_digits ();
2961 } // namespace selftest
2963 #endif /* #if CHECKING_P */
2965 #if __GNUC__ >= 10
2966 # pragma GCC diagnostic pop
2967 #endif