tree-optimization/114485 - neg induction with partial vectors
[official-gcc.git] / gcc / diagnostic.cc
blob6ffd62361462e6a506c565c69145850c08efa6d5
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 fnotice (stderr, "compilation terminated.\n");
806 finish ();
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 : DK_ANY;
1140 m_classify_diagnostic[option_index] = old_kind;
1143 for (i = m_n_classification_history - 1; i >= 0; i --)
1144 if (m_classification_history[i].option == option_index)
1146 old_kind = m_classification_history[i].kind;
1147 break;
1150 i = m_n_classification_history;
1151 m_classification_history =
1152 (diagnostic_classification_change_t *) xrealloc (m_classification_history, (i + 1)
1153 * sizeof (diagnostic_classification_change_t));
1154 m_classification_history[i].location = where;
1155 m_classification_history[i].option = option_index;
1156 m_classification_history[i].kind = new_kind;
1157 m_n_classification_history ++;
1159 else
1160 m_classify_diagnostic[option_index] = new_kind;
1162 return old_kind;
1165 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1166 escaping rules for -fdiagnostics-parseable-fixits. */
1168 static void
1169 print_escaped_string (pretty_printer *pp, const char *text)
1171 gcc_assert (pp);
1172 gcc_assert (text);
1174 pp_character (pp, '"');
1175 for (const char *ch = text; *ch; ch++)
1177 switch (*ch)
1179 case '\\':
1180 /* Escape backslash as two backslashes. */
1181 pp_string (pp, "\\\\");
1182 break;
1183 case '\t':
1184 /* Escape tab as "\t". */
1185 pp_string (pp, "\\t");
1186 break;
1187 case '\n':
1188 /* Escape newline as "\n". */
1189 pp_string (pp, "\\n");
1190 break;
1191 case '"':
1192 /* Escape doublequotes as \". */
1193 pp_string (pp, "\\\"");
1194 break;
1195 default:
1196 if (ISPRINT (*ch))
1197 pp_character (pp, *ch);
1198 else
1199 /* Use octal for non-printable chars. */
1201 unsigned char c = (*ch & 0xff);
1202 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1204 break;
1207 pp_character (pp, '"');
1210 /* Implementation of -fdiagnostics-parseable-fixits and
1211 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1212 Print a machine-parseable version of all fixits in RICHLOC to PP,
1213 using COLUMN_UNIT to express columns.
1214 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1216 static void
1217 print_parseable_fixits (file_cache &fc,
1218 pretty_printer *pp, rich_location *richloc,
1219 enum diagnostics_column_unit column_unit,
1220 int tabstop)
1222 gcc_assert (pp);
1223 gcc_assert (richloc);
1225 char *saved_prefix = pp_take_prefix (pp);
1226 pp_set_prefix (pp, NULL);
1228 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1230 const fixit_hint *hint = richloc->get_fixit_hint (i);
1231 location_t start_loc = hint->get_start_loc ();
1232 expanded_location start_exploc = expand_location (start_loc);
1233 pp_string (pp, "fix-it:");
1234 print_escaped_string (pp, start_exploc.file);
1235 /* For compatibility with clang, print as a half-open range. */
1236 location_t next_loc = hint->get_next_loc ();
1237 expanded_location next_exploc = expand_location (next_loc);
1238 int start_col
1239 = convert_column_unit (fc, column_unit, tabstop, start_exploc);
1240 int next_col
1241 = convert_column_unit (fc, column_unit, tabstop, next_exploc);
1242 pp_printf (pp, ":{%i:%i-%i:%i}:",
1243 start_exploc.line, start_col,
1244 next_exploc.line, next_col);
1245 print_escaped_string (pp, hint->get_string ());
1246 pp_newline (pp);
1249 pp_set_prefix (pp, saved_prefix);
1252 /* Update the inlining info in this context for a DIAGNOSTIC. */
1254 void
1255 diagnostic_context::get_any_inlining_info (diagnostic_info *diagnostic)
1257 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1259 if (m_set_locations_cb)
1260 /* Retrieve the locations into which the expression about to be
1261 diagnosed has been inlined, including those of all the callers
1262 all the way down the inlining stack. */
1263 m_set_locations_cb (this, diagnostic);
1264 else
1266 /* When there's no callback use just the one location provided
1267 by the caller of the diagnostic function. */
1268 location_t loc = diagnostic_location (diagnostic);
1269 ilocs.safe_push (loc);
1270 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1274 /* Update the kind of DIAGNOSTIC based on its location(s), including
1275 any of those in its inlining stack, relative to any
1276 #pragma GCC diagnostic
1277 directives recorded within this object.
1279 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1280 otherwise. */
1282 diagnostic_t
1283 diagnostic_option_classifier::
1284 update_effective_level_from_pragmas (diagnostic_info *diagnostic) const
1286 if (m_n_classification_history <= 0)
1287 return DK_UNSPECIFIED;
1289 /* Iterate over the locations, checking the diagnostic disposition
1290 for the diagnostic at each. If it's explicitly set as opposed
1291 to unspecified, update the disposition for this instance of
1292 the diagnostic and return it. */
1293 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1295 /* FIXME: Stupid search. Optimize later. */
1296 for (int i = m_n_classification_history - 1; i >= 0; i --)
1298 const diagnostic_classification_change_t &hist
1299 = m_classification_history[i];
1301 location_t pragloc = hist.location;
1302 if (!linemap_location_before_p (line_table, pragloc, loc))
1303 continue;
1305 if (hist.kind == (int) DK_POP)
1307 /* Move on to the next region. */
1308 i = hist.option;
1309 continue;
1312 int option = hist.option;
1313 /* The option 0 is for all the diagnostics. */
1314 if (option == 0 || option == diagnostic->option_index)
1316 diagnostic_t kind = hist.kind;
1317 if (kind != DK_UNSPECIFIED)
1318 diagnostic->kind = kind;
1319 return kind;
1324 return DK_UNSPECIFIED;
1327 /* Generate a URL string describing CWE. The caller is responsible for
1328 freeing the string. */
1330 char *
1331 get_cwe_url (int cwe)
1333 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1336 /* If DIAGNOSTIC has a CWE identifier, print it.
1338 For example, if the diagnostic metadata associates it with CWE-119,
1339 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1340 description of the security issue. */
1342 void
1343 diagnostic_context::print_any_cwe (const diagnostic_info &diagnostic)
1345 if (diagnostic.metadata == NULL)
1346 return;
1348 int cwe = diagnostic.metadata->get_cwe ();
1349 if (cwe)
1351 pretty_printer * const pp = this->printer;
1352 char *saved_prefix = pp_take_prefix (pp);
1353 pp_string (pp, " [");
1354 pp_string (pp, colorize_start (pp_show_color (pp),
1355 diagnostic_kind_color[diagnostic.kind]));
1356 if (pp->url_format != URL_FORMAT_NONE)
1358 char *cwe_url = get_cwe_url (cwe);
1359 pp_begin_url (pp, cwe_url);
1360 free (cwe_url);
1362 pp_printf (pp, "CWE-%i", cwe);
1363 pp_set_prefix (pp, saved_prefix);
1364 if (pp->url_format != URL_FORMAT_NONE)
1365 pp_end_url (pp);
1366 pp_string (pp, colorize_stop (pp_show_color (pp)));
1367 pp_character (pp, ']');
1371 /* If DIAGNOSTIC has any rules associated with it, print them.
1373 For example, if the diagnostic metadata associates it with a rule
1374 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1375 with any URL provided by the rule. */
1377 void
1378 diagnostic_context::print_any_rules (const diagnostic_info &diagnostic)
1380 if (diagnostic.metadata == NULL)
1381 return;
1383 for (unsigned idx = 0; idx < diagnostic.metadata->get_num_rules (); idx++)
1385 const diagnostic_metadata::rule &rule
1386 = diagnostic.metadata->get_rule (idx);
1387 if (char *desc = rule.make_description ())
1389 pretty_printer * const pp = this->printer;
1390 char *saved_prefix = pp_take_prefix (pp);
1391 pp_string (pp, " [");
1392 pp_string (pp,
1393 colorize_start (pp_show_color (pp),
1394 diagnostic_kind_color[diagnostic.kind]));
1395 char *url = NULL;
1396 if (pp->url_format != URL_FORMAT_NONE)
1398 url = rule.make_url ();
1399 if (url)
1400 pp_begin_url (pp, url);
1402 pp_string (pp, desc);
1403 pp_set_prefix (pp, saved_prefix);
1404 if (pp->url_format != URL_FORMAT_NONE)
1405 if (url)
1406 pp_end_url (pp);
1407 free (url);
1408 pp_string (pp, colorize_stop (pp_show_color (pp)));
1409 pp_character (pp, ']');
1410 free (desc);
1415 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1416 printer, e.g. " [-Werror=uninitialized]".
1417 Subroutine of diagnostic_context::report_diagnostic. */
1419 void
1420 diagnostic_context::print_option_information (const diagnostic_info &diagnostic,
1421 diagnostic_t orig_diag_kind)
1423 if (char *option_text = make_option_name (diagnostic.option_index,
1424 orig_diag_kind, diagnostic.kind))
1426 char *option_url = nullptr;
1427 if (this->printer->url_format != URL_FORMAT_NONE)
1428 option_url = make_option_url (diagnostic.option_index);
1429 pretty_printer * const pp = this->printer;
1430 pp_string (pp, " [");
1431 pp_string (pp, colorize_start (pp_show_color (pp),
1432 diagnostic_kind_color[diagnostic.kind]));
1433 if (option_url)
1434 pp_begin_url (pp, option_url);
1435 pp_string (pp, option_text);
1436 if (option_url)
1438 pp_end_url (pp);
1439 free (option_url);
1441 pp_string (pp, colorize_stop (pp_show_color (pp)));
1442 pp_character (pp, ']');
1443 free (option_text);
1447 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1448 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1450 bool
1451 diagnostic_context::diagnostic_enabled (diagnostic_info *diagnostic)
1453 /* Update the inlining stack for this diagnostic. */
1454 get_any_inlining_info (diagnostic);
1456 /* Diagnostics with no option or -fpermissive are always enabled. */
1457 if (!diagnostic->option_index
1458 || diagnostic->option_index == permissive_error_option (this))
1459 return true;
1461 /* This tests if the user provided the appropriate -Wfoo or
1462 -Wno-foo option. */
1463 if (!option_enabled_p (diagnostic->option_index))
1464 return false;
1466 /* This tests for #pragma diagnostic changes. */
1467 diagnostic_t diag_class
1468 = m_option_classifier.update_effective_level_from_pragmas (diagnostic);
1470 /* This tests if the user provided the appropriate -Werror=foo
1471 option. */
1472 if (diag_class == DK_UNSPECIFIED
1473 && !option_unspecified_p (diagnostic->option_index))
1475 const diagnostic_t new_kind
1476 = m_option_classifier.get_current_override (diagnostic->option_index);
1477 if (new_kind != DK_ANY)
1478 /* DK_ANY means the diagnostic is not to be ignored, but we don't want
1479 to change it specifically to DK_ERROR or DK_WARNING; we want to
1480 preserve whatever the caller has specified. */
1481 diagnostic->kind = new_kind;
1484 /* This allows for future extensions, like temporarily disabling
1485 warnings for ranges of source code. */
1486 if (diagnostic->kind == DK_IGNORED)
1487 return false;
1489 return true;
1492 /* Returns whether warning OPT is enabled at LOC. */
1494 bool
1495 diagnostic_context::warning_enabled_at (location_t loc, int opt)
1497 if (!diagnostic_report_warnings_p (this, loc))
1498 return false;
1500 rich_location richloc (line_table, loc);
1501 diagnostic_info diagnostic = {};
1502 diagnostic.option_index = opt;
1503 diagnostic.richloc = &richloc;
1504 diagnostic.message.m_richloc = &richloc;
1505 diagnostic.kind = DK_WARNING;
1506 return diagnostic_enabled (&diagnostic);
1509 /* Report a diagnostic message (an error or a warning) as specified by
1510 this diagnostic_context.
1511 front-end independent format specifiers are exactly those described
1512 in the documentation of output_format.
1513 Return true if a diagnostic was printed, false otherwise. */
1515 bool
1516 diagnostic_context::report_diagnostic (diagnostic_info *diagnostic)
1518 diagnostic_t orig_diag_kind = diagnostic->kind;
1520 gcc_assert (m_output_format);
1522 /* Give preference to being able to inhibit warnings, before they
1523 get reclassified to something else. */
1524 bool was_warning = (diagnostic->kind == DK_WARNING
1525 || diagnostic->kind == DK_PEDWARN);
1526 if (was_warning && m_inhibit_warnings)
1527 return false;
1529 if (diagnostic->kind == DK_PEDWARN)
1531 diagnostic->kind = pedantic_warning_kind (this);
1532 /* We do this to avoid giving the message for -pedantic-errors. */
1533 orig_diag_kind = diagnostic->kind;
1536 if (diagnostic->kind == DK_NOTE && m_inhibit_notes_p)
1537 return false;
1539 if (m_lock > 0)
1541 /* If we're reporting an ICE in the middle of some other error,
1542 try to flush out the previous error, then let this one
1543 through. Don't do this more than once. */
1544 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1545 && m_lock == 1)
1546 pp_newline_and_flush (this->printer);
1547 else
1548 error_recursion ();
1551 /* If the user requested that warnings be treated as errors, so be
1552 it. Note that we do this before the next block so that
1553 individual warnings can be overridden back to warnings with
1554 -Wno-error=*. */
1555 if (m_warning_as_error_requested
1556 && diagnostic->kind == DK_WARNING)
1557 diagnostic->kind = DK_ERROR;
1559 diagnostic->message.m_data = &diagnostic->x_data;
1561 /* Check to see if the diagnostic is enabled at the location and
1562 not disabled by #pragma GCC diagnostic anywhere along the inlining
1563 stack. . */
1564 if (!diagnostic_enabled (diagnostic))
1565 return false;
1567 if ((was_warning || diagnostic->kind == DK_WARNING)
1568 && ((!m_warn_system_headers
1569 && diagnostic->m_iinfo.m_allsyslocs)
1570 || m_inhibit_warnings))
1571 /* Bail if the warning is not to be reported because all locations in the
1572 inlining stack (if there is one) are in system headers. */
1573 return false;
1575 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1576 diagnostic_check_max_errors (this);
1578 m_lock++;
1580 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1582 /* When not checking, ICEs are converted to fatal errors when an
1583 error has already occurred. This is counteracted by
1584 abort_on_error. */
1585 if (!CHECKING_P
1586 && (m_diagnostic_count[DK_ERROR] > 0
1587 || m_diagnostic_count[DK_SORRY] > 0)
1588 && !m_abort_on_error)
1590 expanded_location s
1591 = expand_location (diagnostic_location (diagnostic));
1592 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1593 s.file, s.line);
1594 exit (ICE_EXIT_CODE);
1596 if (m_internal_error)
1597 (*m_internal_error) (this,
1598 diagnostic->message.m_format_spec,
1599 diagnostic->message.m_args_ptr);
1601 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1602 ++m_diagnostic_count[DK_WERROR];
1603 else
1604 ++m_diagnostic_count[diagnostic->kind];
1606 /* Is this the initial diagnostic within the stack of groups? */
1607 if (m_diagnostic_groups.m_emission_count == 0)
1608 m_output_format->on_begin_group ();
1609 m_diagnostic_groups.m_emission_count++;
1611 pp_format (this->printer, &diagnostic->message, m_urlifier);
1612 m_output_format->on_begin_diagnostic (*diagnostic);
1613 pp_output_formatted_text (this->printer, m_urlifier);
1614 if (m_show_cwe)
1615 print_any_cwe (*diagnostic);
1616 if (m_show_rules)
1617 print_any_rules (*diagnostic);
1618 if (m_show_option_requested)
1619 print_option_information (*diagnostic, orig_diag_kind);
1620 m_output_format->on_end_diagnostic (*diagnostic, orig_diag_kind);
1621 switch (m_extra_output_kind)
1623 default:
1624 break;
1625 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1626 print_parseable_fixits (get_file_cache (),
1627 this->printer, diagnostic->richloc,
1628 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1629 m_tabstop);
1630 pp_flush (this->printer);
1631 break;
1632 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1633 print_parseable_fixits (get_file_cache (),
1634 this->printer, diagnostic->richloc,
1635 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1636 m_tabstop);
1637 pp_flush (this->printer);
1638 break;
1640 diagnostic_action_after_output (this, diagnostic->kind);
1641 diagnostic->x_data = NULL;
1643 if (m_edit_context_ptr)
1644 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1645 m_edit_context_ptr->add_fixits (diagnostic->richloc);
1647 m_lock--;
1649 show_any_path (*diagnostic);
1651 return true;
1654 /* Get the number of digits in the decimal representation of VALUE. */
1657 num_digits (int value)
1659 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1660 using floating point. */
1661 gcc_assert (value >= 0);
1663 if (value == 0)
1664 return 1;
1666 int digits = 0;
1667 while (value > 0)
1669 digits++;
1670 value /= 10;
1672 return digits;
1675 /* Given a partial pathname as input, return another pathname that
1676 shares no directory elements with the pathname of __FILE__. This
1677 is used by fancy_abort() to print `internal compiler error in expr.cc'
1678 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1680 const char *
1681 trim_filename (const char *name)
1683 static const char this_file[] = __FILE__;
1684 const char *p = name, *q = this_file;
1686 /* First skip any "../" in each filename. This allows us to give a proper
1687 reference to a file in a subdirectory. */
1688 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1689 p += 3;
1691 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1692 q += 3;
1694 /* Now skip any parts the two filenames have in common. */
1695 while (*p == *q && *p != 0 && *q != 0)
1696 p++, q++;
1698 /* Now go backwards until the previous directory separator. */
1699 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1700 p--;
1702 return p;
1705 /* Standard error reporting routines in increasing order of severity.
1706 All of these take arguments like printf. */
1708 /* Text to be emitted verbatim to the error message stream; this
1709 produces no prefix and disables line-wrapping. Use rarely. */
1710 void
1711 verbatim (const char *gmsgid, ...)
1713 va_list ap;
1715 va_start (ap, gmsgid);
1716 text_info text (_(gmsgid), &ap, errno);
1717 pp_format_verbatim (global_dc->printer, &text);
1718 pp_newline_and_flush (global_dc->printer);
1719 va_end (ap);
1722 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1723 void
1724 diagnostic_append_note (diagnostic_context *context,
1725 location_t location,
1726 const char * gmsgid, ...)
1728 diagnostic_info diagnostic;
1729 va_list ap;
1730 rich_location richloc (line_table, location);
1732 va_start (ap, gmsgid);
1733 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1734 if (context->m_inhibit_notes_p)
1736 va_end (ap);
1737 return;
1739 char *saved_prefix = pp_take_prefix (context->printer);
1740 pp_set_prefix (context->printer,
1741 diagnostic_build_prefix (context, &diagnostic));
1742 pp_format (context->printer, &diagnostic.message);
1743 pp_output_formatted_text (context->printer);
1744 pp_destroy_prefix (context->printer);
1745 pp_set_prefix (context->printer, saved_prefix);
1746 pp_newline (context->printer);
1747 diagnostic_show_locus (context, &richloc, DK_NOTE);
1748 va_end (ap);
1751 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1752 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1753 and internal_error_no_backtrace, as documented and defined below. */
1754 static bool
1755 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1756 int opt, const char *gmsgid,
1757 va_list *ap, diagnostic_t kind)
1759 diagnostic_info diagnostic;
1760 if (kind == DK_PERMERROR)
1762 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1763 permissive_error_kind (global_dc));
1764 diagnostic.option_index = (opt != -1 ? opt
1765 : permissive_error_option (global_dc));
1767 else
1769 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1770 if (kind == DK_WARNING || kind == DK_PEDWARN)
1771 diagnostic.option_index = opt;
1773 diagnostic.metadata = metadata;
1774 return global_dc->report_diagnostic (&diagnostic);
1777 /* Implement inform_n, warning_n, and error_n, as documented and
1778 defined below. */
1779 static bool
1780 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1781 int opt, unsigned HOST_WIDE_INT n,
1782 const char *singular_gmsgid,
1783 const char *plural_gmsgid,
1784 va_list *ap, diagnostic_t kind)
1786 diagnostic_info diagnostic;
1787 unsigned long gtn;
1789 if (sizeof n <= sizeof gtn)
1790 gtn = n;
1791 else
1792 /* Use the largest number ngettext can handle, otherwise
1793 preserve the six least significant decimal digits for
1794 languages where the plural form depends on them. */
1795 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1797 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1798 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1799 if (kind == DK_WARNING)
1800 diagnostic.option_index = opt;
1801 diagnostic.metadata = metadata;
1802 return global_dc->report_diagnostic (&diagnostic);
1805 /* Wrapper around diagnostic_impl taking a variable argument list. */
1807 bool
1808 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1809 const char *gmsgid, ...)
1811 auto_diagnostic_group d;
1812 va_list ap;
1813 va_start (ap, gmsgid);
1814 rich_location richloc (line_table, location);
1815 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1816 va_end (ap);
1817 return ret;
1820 /* As above, but for rich_location *. */
1822 bool
1823 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1824 const char *gmsgid, ...)
1826 auto_diagnostic_group d;
1827 va_list ap;
1828 va_start (ap, gmsgid);
1829 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1830 va_end (ap);
1831 return ret;
1834 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1836 bool
1837 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1838 const char *gmsgid, va_list *ap)
1840 rich_location richloc (line_table, location);
1841 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1844 /* As above, but with rich_location and metadata. */
1846 bool
1847 emit_diagnostic_valist_meta (diagnostic_t kind,
1848 rich_location *richloc,
1849 const diagnostic_metadata *metadata,
1850 int opt,
1851 const char *gmsgid, va_list *ap)
1853 return diagnostic_impl (richloc, metadata, opt, gmsgid, ap, kind);
1856 /* An informative note at LOCATION. Use this for additional details on an error
1857 message. */
1858 void
1859 inform (location_t location, const char *gmsgid, ...)
1861 auto_diagnostic_group d;
1862 va_list ap;
1863 va_start (ap, gmsgid);
1864 rich_location richloc (line_table, location);
1865 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1866 va_end (ap);
1869 /* Same as "inform" above, but at RICHLOC. */
1870 void
1871 inform (rich_location *richloc, const char *gmsgid, ...)
1873 gcc_assert (richloc);
1875 auto_diagnostic_group d;
1876 va_list ap;
1877 va_start (ap, gmsgid);
1878 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1879 va_end (ap);
1882 /* An informative note at LOCATION. Use this for additional details on an
1883 error message. */
1884 void
1885 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1886 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1888 va_list ap;
1889 va_start (ap, plural_gmsgid);
1890 auto_diagnostic_group d;
1891 rich_location richloc (line_table, location);
1892 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1893 &ap, DK_NOTE);
1894 va_end (ap);
1897 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1898 to the relevant language specification but is likely to be buggy anyway.
1899 Returns true if the warning was printed, false if it was inhibited. */
1900 bool
1901 warning (int opt, const char *gmsgid, ...)
1903 auto_diagnostic_group d;
1904 va_list ap;
1905 va_start (ap, gmsgid);
1906 rich_location richloc (line_table, input_location);
1907 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1908 va_end (ap);
1909 return ret;
1912 /* A warning at LOCATION. Use this for code which is correct according to the
1913 relevant language specification but is likely to be buggy anyway.
1914 Returns true if the warning was printed, false if it was inhibited. */
1916 bool
1917 warning_at (location_t location, int opt, const char *gmsgid, ...)
1919 auto_diagnostic_group d;
1920 va_list ap;
1921 va_start (ap, gmsgid);
1922 rich_location richloc (line_table, location);
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 RICHLOC. */
1930 bool
1931 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1933 gcc_assert (richloc);
1935 auto_diagnostic_group d;
1936 va_list ap;
1937 va_start (ap, gmsgid);
1938 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1939 va_end (ap);
1940 return ret;
1943 /* Same as "warning at" above, but using METADATA. */
1945 bool
1946 warning_meta (rich_location *richloc,
1947 const diagnostic_metadata &metadata,
1948 int opt, const char *gmsgid, ...)
1950 gcc_assert (richloc);
1952 auto_diagnostic_group d;
1953 va_list ap;
1954 va_start (ap, gmsgid);
1955 bool ret
1956 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1957 DK_WARNING);
1958 va_end (ap);
1959 return ret;
1962 /* Same as warning_n plural variant below, but using RICHLOC. */
1964 bool
1965 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1966 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1968 gcc_assert (richloc);
1970 auto_diagnostic_group d;
1971 va_list ap;
1972 va_start (ap, plural_gmsgid);
1973 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1974 singular_gmsgid, plural_gmsgid,
1975 &ap, DK_WARNING);
1976 va_end (ap);
1977 return ret;
1980 /* A warning at LOCATION. Use this for code which is correct according to the
1981 relevant language specification but is likely to be buggy anyway.
1982 Returns true if the warning was printed, false if it was inhibited. */
1984 bool
1985 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1986 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1988 auto_diagnostic_group d;
1989 va_list ap;
1990 va_start (ap, plural_gmsgid);
1991 rich_location richloc (line_table, location);
1992 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1993 singular_gmsgid, plural_gmsgid,
1994 &ap, DK_WARNING);
1995 va_end (ap);
1996 return ret;
1999 /* A "pedantic" warning at LOCATION: issues a warning unless
2000 -pedantic-errors was given on the command line, in which case it
2001 issues an error. Use this for diagnostics required by the relevant
2002 language standard, if you have chosen not to make them errors.
2004 Note that these diagnostics are issued independent of the setting
2005 of the -Wpedantic command-line switch. To get a warning enabled
2006 only with that switch, use either "if (pedantic) pedwarn
2007 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
2008 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
2010 Returns true if the warning was printed, false if it was inhibited. */
2012 bool
2013 pedwarn (location_t location, int opt, const char *gmsgid, ...)
2015 auto_diagnostic_group d;
2016 va_list ap;
2017 va_start (ap, gmsgid);
2018 rich_location richloc (line_table, location);
2019 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2020 va_end (ap);
2021 return ret;
2024 /* Same as pedwarn above, but using RICHLOC. */
2026 bool
2027 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
2029 gcc_assert (richloc);
2031 auto_diagnostic_group d;
2032 va_list ap;
2033 va_start (ap, gmsgid);
2034 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
2035 va_end (ap);
2036 return ret;
2039 /* A "permissive" error at LOCATION: issues an error unless
2040 -fpermissive was given on the command line, in which case it issues
2041 a warning. Use this for things that really should be errors but we
2042 want to support legacy code.
2044 Returns true if the warning was printed, false if it was inhibited. */
2046 bool
2047 permerror (location_t location, const char *gmsgid, ...)
2049 auto_diagnostic_group d;
2050 va_list ap;
2051 va_start (ap, gmsgid);
2052 rich_location richloc (line_table, location);
2053 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2054 va_end (ap);
2055 return ret;
2058 /* Same as "permerror" above, but at RICHLOC. */
2060 bool
2061 permerror (rich_location *richloc, const char *gmsgid, ...)
2063 gcc_assert (richloc);
2065 auto_diagnostic_group d;
2066 va_list ap;
2067 va_start (ap, gmsgid);
2068 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2069 va_end (ap);
2070 return ret;
2073 /* Similar to the above, but controlled by a flag other than -fpermissive.
2074 As above, an error by default or a warning with -fpermissive, but this
2075 diagnostic can also be downgraded by -Wno-error=opt. */
2077 bool
2078 permerror_opt (location_t location, int opt, const char *gmsgid, ...)
2080 auto_diagnostic_group d;
2081 va_list ap;
2082 va_start (ap, gmsgid);
2083 rich_location richloc (line_table, location);
2084 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2085 va_end (ap);
2086 return ret;
2089 /* Same as "permerror" above, but at RICHLOC. */
2091 bool
2092 permerror_opt (rich_location *richloc, int opt, const char *gmsgid, ...)
2094 gcc_assert (richloc);
2096 auto_diagnostic_group d;
2097 va_list ap;
2098 va_start (ap, gmsgid);
2099 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2100 va_end (ap);
2101 return ret;
2104 /* A hard error: the code is definitely ill-formed, and an object file
2105 will not be produced. */
2106 void
2107 error (const char *gmsgid, ...)
2109 auto_diagnostic_group d;
2110 va_list ap;
2111 va_start (ap, gmsgid);
2112 rich_location richloc (line_table, input_location);
2113 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2114 va_end (ap);
2117 /* A hard error: the code is definitely ill-formed, and an object file
2118 will not be produced. */
2119 void
2120 error_n (location_t location, unsigned HOST_WIDE_INT n,
2121 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2123 auto_diagnostic_group d;
2124 va_list ap;
2125 va_start (ap, plural_gmsgid);
2126 rich_location richloc (line_table, location);
2127 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2128 &ap, DK_ERROR);
2129 va_end (ap);
2132 /* Same as above, but use location LOC instead of input_location. */
2133 void
2134 error_at (location_t loc, const char *gmsgid, ...)
2136 auto_diagnostic_group d;
2137 va_list ap;
2138 va_start (ap, gmsgid);
2139 rich_location richloc (line_table, loc);
2140 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2141 va_end (ap);
2144 /* Same as above, but use RICH_LOC. */
2146 void
2147 error_at (rich_location *richloc, 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, NULL, -1, gmsgid, &ap, DK_ERROR);
2155 va_end (ap);
2158 /* Same as above, but with metadata. */
2160 void
2161 error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
2162 const char *gmsgid, ...)
2164 gcc_assert (richloc);
2166 auto_diagnostic_group d;
2167 va_list ap;
2168 va_start (ap, gmsgid);
2169 diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
2170 va_end (ap);
2173 /* "Sorry, not implemented." Use for a language feature which is
2174 required by the relevant specification but not implemented by GCC.
2175 An object file will not be produced. */
2176 void
2177 sorry (const char *gmsgid, ...)
2179 auto_diagnostic_group d;
2180 va_list ap;
2181 va_start (ap, gmsgid);
2182 rich_location richloc (line_table, input_location);
2183 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2184 va_end (ap);
2187 /* Same as above, but use location LOC instead of input_location. */
2188 void
2189 sorry_at (location_t loc, const char *gmsgid, ...)
2191 auto_diagnostic_group d;
2192 va_list ap;
2193 va_start (ap, gmsgid);
2194 rich_location richloc (line_table, loc);
2195 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2196 va_end (ap);
2199 /* Return true if an error or a "sorry" has been seen. Various
2200 processing is disabled after errors. */
2201 bool
2202 seen_error (void)
2204 return errorcount || sorrycount;
2207 /* An error which is severe enough that we make no attempt to
2208 continue. Do not use this for internal consistency checks; that's
2209 internal_error. Use of this function should be rare. */
2210 void
2211 fatal_error (location_t loc, const char *gmsgid, ...)
2213 auto_diagnostic_group d;
2214 va_list ap;
2215 va_start (ap, gmsgid);
2216 rich_location richloc (line_table, loc);
2217 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2218 va_end (ap);
2220 gcc_unreachable ();
2223 /* An internal consistency check has failed. We make no attempt to
2224 continue. */
2225 void
2226 internal_error (const char *gmsgid, ...)
2228 auto_diagnostic_group d;
2229 va_list ap;
2230 va_start (ap, gmsgid);
2231 rich_location richloc (line_table, input_location);
2232 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2233 va_end (ap);
2235 gcc_unreachable ();
2238 /* Like internal_error, but no backtrace will be printed. Used when
2239 the internal error does not happen at the current location, but happened
2240 somewhere else. */
2241 void
2242 internal_error_no_backtrace (const char *gmsgid, ...)
2244 auto_diagnostic_group d;
2245 va_list ap;
2246 va_start (ap, gmsgid);
2247 rich_location richloc (line_table, input_location);
2248 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2249 va_end (ap);
2251 gcc_unreachable ();
2254 /* Emit DIAGRAM to this context, respecting the output format. */
2256 void
2257 diagnostic_context::emit_diagram (const diagnostic_diagram &diagram)
2259 if (m_diagrams.m_theme == nullptr)
2260 return;
2262 gcc_assert (m_output_format);
2263 m_output_format->on_diagram (diagram);
2266 /* Special case error functions. Most are implemented in terms of the
2267 above, or should be. */
2269 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2270 runs its second argument through gettext. */
2271 void
2272 fnotice (FILE *file, const char *cmsgid, ...)
2274 /* If the user requested one of the machine-readable diagnostic output
2275 formats on stderr (e.g. -fdiagnostics-format=sarif-stderr), then
2276 emitting free-form text on stderr will lead to corrupt output.
2277 Skip the message for such cases. */
2278 if (file == stderr && global_dc)
2279 if (const diagnostic_output_format *output_format
2280 = global_dc->get_output_format ())
2281 if (output_format->machine_readable_stderr_p ())
2282 return;
2284 va_list ap;
2286 va_start (ap, cmsgid);
2287 vfprintf (file, _(cmsgid), ap);
2288 va_end (ap);
2291 /* Inform the user that an error occurred while trying to report some
2292 other error. This indicates catastrophic internal inconsistencies,
2293 so give up now. But do try to flush out the previous error.
2294 This mustn't use internal_error, that will cause infinite recursion. */
2296 void
2297 diagnostic_context::error_recursion ()
2299 if (m_lock < 3)
2300 pp_newline_and_flush (this->printer);
2302 fnotice (stderr,
2303 "internal compiler error: error reporting routines re-entered.\n");
2305 /* Call diagnostic_action_after_output to get the "please submit a bug
2306 report" message. */
2307 diagnostic_action_after_output (this, DK_ICE);
2309 /* Do not use gcc_unreachable here; that goes through internal_error
2310 and therefore would cause infinite recursion. */
2311 real_abort ();
2314 /* Report an internal compiler error in a friendly manner. This is
2315 the function that gets called upon use of abort() in the source
2316 code generally, thanks to a special macro. */
2318 void
2319 fancy_abort (const char *file, int line, const char *function)
2321 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2322 internal_error will crash internally in a way that prevents a
2323 useful message reaching the user.
2324 This can happen with libgccjit in the case of gcc_assert failures
2325 that occur outside of the libgccjit mutex that guards the rest of
2326 gcc's state, including global_dc (when global_dc may not be
2327 initialized yet, or might be in use by another thread).
2328 Handle such cases as gracefully as possible by falling back to a
2329 minimal abort handler that only relies on i18n. */
2330 if (global_dc->printer == NULL)
2332 /* Print the error message. */
2333 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2334 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2335 fputc ('\n', stderr);
2337 /* Attempt to print a backtrace. */
2338 struct backtrace_state *state
2339 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2340 int count = 0;
2341 if (state != NULL)
2342 backtrace_full (state, 2, bt_callback, bt_err_callback,
2343 (void *) &count);
2345 /* We can't call warn_if_plugins or emergency_dump_function as these
2346 rely on GCC state that might not be initialized, or might be in
2347 use by another thread. */
2349 /* Abort the process. */
2350 real_abort ();
2353 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2356 /* class diagnostic_context. */
2358 void
2359 diagnostic_context::begin_group ()
2361 m_diagnostic_groups.m_nesting_depth++;
2364 void
2365 diagnostic_context::end_group ()
2367 if (--m_diagnostic_groups.m_nesting_depth == 0)
2369 /* Handle the case where we've popped the final diagnostic group.
2370 If any diagnostics were emitted, give the context a chance
2371 to do something. */
2372 if (m_diagnostic_groups.m_emission_count > 0)
2373 m_output_format->on_end_group ();
2374 m_diagnostic_groups.m_emission_count = 0;
2378 /* class auto_diagnostic_group. */
2380 /* Constructor: "push" this group into global_dc. */
2382 auto_diagnostic_group::auto_diagnostic_group ()
2384 global_dc->begin_group ();
2387 /* Destructor: "pop" this group from global_dc. */
2389 auto_diagnostic_group::~auto_diagnostic_group ()
2391 global_dc->end_group ();
2394 /* class diagnostic_text_output_format : public diagnostic_output_format. */
2396 diagnostic_text_output_format::~diagnostic_text_output_format ()
2398 /* Some of the errors may actually have been warnings. */
2399 if (m_context.diagnostic_count (DK_WERROR))
2401 /* -Werror was given. */
2402 if (m_context.warning_as_error_requested_p ())
2403 pp_verbatim (m_context.printer,
2404 _("%s: all warnings being treated as errors"),
2405 progname);
2406 /* At least one -Werror= was given. */
2407 else
2408 pp_verbatim (m_context.printer,
2409 _("%s: some warnings being treated as errors"),
2410 progname);
2411 pp_newline_and_flush (m_context.printer);
2415 void
2416 diagnostic_text_output_format::on_begin_diagnostic (const diagnostic_info &diagnostic)
2418 (*diagnostic_starter (&m_context)) (&m_context, &diagnostic);
2421 void
2422 diagnostic_text_output_format::on_end_diagnostic (const diagnostic_info &diagnostic,
2423 diagnostic_t orig_diag_kind)
2425 (*diagnostic_finalizer (&m_context)) (&m_context, &diagnostic,
2426 orig_diag_kind);
2429 void
2430 diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
2432 char *saved_prefix = pp_take_prefix (m_context.printer);
2433 pp_set_prefix (m_context.printer, NULL);
2434 /* Use a newline before and after and a two-space indent
2435 to make the diagram stand out a little from the wall of text. */
2436 pp_newline (m_context.printer);
2437 diagram.get_canvas ().print_to_pp (m_context.printer, " ");
2438 pp_newline (m_context.printer);
2439 pp_set_prefix (m_context.printer, saved_prefix);
2440 pp_flush (m_context.printer);
2443 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2444 file-based output formats. */
2446 void
2447 diagnostic_output_format_init (diagnostic_context *context,
2448 const char *base_file_name,
2449 enum diagnostics_output_format format,
2450 bool json_formatting)
2452 switch (format)
2454 default:
2455 gcc_unreachable ();
2456 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2457 /* The default; do nothing. */
2458 break;
2460 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2461 diagnostic_output_format_init_json_stderr (context,
2462 json_formatting);
2463 break;
2465 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2466 diagnostic_output_format_init_json_file (context,
2467 json_formatting,
2468 base_file_name);
2469 break;
2471 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2472 diagnostic_output_format_init_sarif_stderr (context,
2473 json_formatting);
2474 break;
2476 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2477 diagnostic_output_format_init_sarif_file (context,
2478 json_formatting,
2479 base_file_name);
2480 break;
2484 /* Initialize this context's m_diagrams based on CHARSET.
2485 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2486 (or NULL for "no diagrams"). */
2488 void
2489 diagnostic_context::
2490 set_text_art_charset (enum diagnostic_text_art_charset charset)
2492 delete m_diagrams.m_theme;
2493 switch (charset)
2495 default:
2496 gcc_unreachable ();
2498 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
2499 m_diagrams.m_theme = nullptr;
2500 break;
2502 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
2503 m_diagrams.m_theme = new text_art::ascii_theme ();
2504 break;
2506 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
2507 m_diagrams.m_theme = new text_art::unicode_theme ();
2508 break;
2510 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
2511 m_diagrams.m_theme = new text_art::emoji_theme ();
2512 break;
2516 /* class simple_diagnostic_path : public diagnostic_path. */
2518 simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
2519 : m_event_pp (event_pp)
2521 add_thread ("main");
2524 /* Implementation of diagnostic_path::num_events vfunc for
2525 simple_diagnostic_path: simply get the number of events in the vec. */
2527 unsigned
2528 simple_diagnostic_path::num_events () const
2530 return m_events.length ();
2533 /* Implementation of diagnostic_path::get_event vfunc for
2534 simple_diagnostic_path: simply return the event in the vec. */
2536 const diagnostic_event &
2537 simple_diagnostic_path::get_event (int idx) const
2539 return *m_events[idx];
2542 unsigned
2543 simple_diagnostic_path::num_threads () const
2545 return m_threads.length ();
2548 const diagnostic_thread &
2549 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
2551 return *m_threads[idx];
2554 diagnostic_thread_id_t
2555 simple_diagnostic_path::add_thread (const char *name)
2557 m_threads.safe_push (new simple_diagnostic_thread (name));
2558 return m_threads.length () - 1;
2561 /* Add an event to this path at LOC within function FNDECL at
2562 stack depth DEPTH.
2564 Use m_context's printer to format FMT, as the text of the new
2565 event.
2567 Return the id of the new event. */
2569 diagnostic_event_id_t
2570 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2571 const char *fmt, ...)
2573 pretty_printer *pp = m_event_pp;
2574 pp_clear_output_area (pp);
2576 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2578 va_list ap;
2580 va_start (ap, fmt);
2582 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2583 pp_format (pp, &ti);
2584 pp_output_formatted_text (pp);
2586 va_end (ap);
2588 simple_diagnostic_event *new_event
2589 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2590 m_events.safe_push (new_event);
2592 pp_clear_output_area (pp);
2594 return diagnostic_event_id_t (m_events.length () - 1);
2597 diagnostic_event_id_t
2598 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
2599 location_t loc,
2600 tree fndecl,
2601 int depth,
2602 const char *fmt, ...)
2604 pretty_printer *pp = m_event_pp;
2605 pp_clear_output_area (pp);
2607 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2609 va_list ap;
2611 va_start (ap, fmt);
2613 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2615 pp_format (pp, &ti);
2616 pp_output_formatted_text (pp);
2618 va_end (ap);
2620 simple_diagnostic_event *new_event
2621 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
2622 thread_id);
2623 m_events.safe_push (new_event);
2625 pp_clear_output_area (pp);
2627 return diagnostic_event_id_t (m_events.length () - 1);
2630 /* struct simple_diagnostic_event. */
2632 /* simple_diagnostic_event's ctor. */
2634 simple_diagnostic_event::
2635 simple_diagnostic_event (location_t loc,
2636 tree fndecl,
2637 int depth,
2638 const char *desc,
2639 diagnostic_thread_id_t thread_id)
2640 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
2641 m_thread_id (thread_id)
2645 /* simple_diagnostic_event's dtor. */
2647 simple_diagnostic_event::~simple_diagnostic_event ()
2649 free (m_desc);
2652 /* Print PATH by emitting a dummy "note" associated with it. */
2654 DEBUG_FUNCTION
2655 void debug (diagnostic_path *path)
2657 rich_location richloc (line_table, UNKNOWN_LOCATION);
2658 richloc.set_path (path);
2659 inform (&richloc, "debug path");
2662 /* Really call the system 'abort'. This has to go right at the end of
2663 this file, so that there are no functions after it that call abort
2664 and get the system abort instead of our macro. */
2665 #undef abort
2666 static void
2667 real_abort (void)
2669 abort ();
2672 #if CHECKING_P
2674 namespace selftest {
2676 /* Helper function for test_print_escaped_string. */
2678 static void
2679 assert_print_escaped_string (const location &loc, const char *expected_output,
2680 const char *input)
2682 pretty_printer pp;
2683 print_escaped_string (&pp, input);
2684 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2687 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2688 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2690 /* Tests of print_escaped_string. */
2692 static void
2693 test_print_escaped_string ()
2695 /* Empty string. */
2696 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2698 /* Non-empty string. */
2699 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2701 /* Various things that need to be escaped: */
2702 /* Backslash. */
2703 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2704 "before\\after");
2705 /* Tab. */
2706 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2707 "before\tafter");
2708 /* Newline. */
2709 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2710 "before\nafter");
2711 /* Double quote. */
2712 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2713 "before\"after");
2715 /* Non-printable characters: BEL: '\a': 0x07 */
2716 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2717 "before\aafter");
2718 /* Non-printable characters: vertical tab: '\v': 0x0b */
2719 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2720 "before\vafter");
2723 /* Tests of print_parseable_fixits. */
2725 /* Verify that print_parseable_fixits emits the empty string if there
2726 are no fixits. */
2728 static void
2729 test_print_parseable_fixits_none ()
2731 pretty_printer pp;
2732 file_cache fc;
2733 rich_location richloc (line_table, UNKNOWN_LOCATION);
2735 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2736 ASSERT_STREQ ("", pp_formatted_text (&pp));
2739 /* Verify that print_parseable_fixits does the right thing if there
2740 is an insertion fixit hint. */
2742 static void
2743 test_print_parseable_fixits_insert ()
2745 pretty_printer pp;
2746 file_cache fc;
2747 rich_location richloc (line_table, UNKNOWN_LOCATION);
2749 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2750 linemap_line_start (line_table, 5, 100);
2751 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2752 location_t where = linemap_position_for_column (line_table, 10);
2753 richloc.add_fixit_insert_before (where, "added content");
2755 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2756 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2757 pp_formatted_text (&pp));
2760 /* Verify that print_parseable_fixits does the right thing if there
2761 is an removal fixit hint. */
2763 static void
2764 test_print_parseable_fixits_remove ()
2766 pretty_printer pp;
2767 file_cache fc;
2768 rich_location richloc (line_table, UNKNOWN_LOCATION);
2770 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2771 linemap_line_start (line_table, 5, 100);
2772 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2773 source_range where;
2774 where.m_start = linemap_position_for_column (line_table, 10);
2775 where.m_finish = linemap_position_for_column (line_table, 20);
2776 richloc.add_fixit_remove (where);
2778 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2779 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2780 pp_formatted_text (&pp));
2783 /* Verify that print_parseable_fixits does the right thing if there
2784 is an replacement fixit hint. */
2786 static void
2787 test_print_parseable_fixits_replace ()
2789 pretty_printer pp;
2790 file_cache fc;
2791 rich_location richloc (line_table, UNKNOWN_LOCATION);
2793 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2794 linemap_line_start (line_table, 5, 100);
2795 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2796 source_range where;
2797 where.m_start = linemap_position_for_column (line_table, 10);
2798 where.m_finish = linemap_position_for_column (line_table, 20);
2799 richloc.add_fixit_replace (where, "replacement");
2801 print_parseable_fixits (fc, &pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2802 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2803 pp_formatted_text (&pp));
2806 /* Verify that print_parseable_fixits correctly handles
2807 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2809 static void
2810 test_print_parseable_fixits_bytes_vs_display_columns ()
2812 line_table_test ltt;
2813 rich_location richloc (line_table, UNKNOWN_LOCATION);
2815 /* 1-based byte offsets: 12345677778888999900001234567. */
2816 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2817 /* 1-based display cols: 123456[......7-8.....]9012345. */
2818 const int tabstop = 8;
2820 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2821 file_cache fc;
2822 const char *const fname = tmp.get_filename ();
2824 linemap_add (line_table, LC_ENTER, false, fname, 0);
2825 linemap_line_start (line_table, 1, 100);
2826 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2827 source_range where;
2828 where.m_start = linemap_position_for_column (line_table, 12);
2829 where.m_finish = linemap_position_for_column (line_table, 17);
2830 richloc.add_fixit_replace (where, "color");
2832 /* Escape fname. */
2833 pretty_printer tmp_pp;
2834 print_escaped_string (&tmp_pp, fname);
2835 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2837 const int buf_len = strlen (escaped_fname) + 100;
2838 char *const expected = XNEWVEC (char, buf_len);
2841 pretty_printer pp;
2842 print_parseable_fixits (fc, &pp, &richloc,
2843 DIAGNOSTICS_COLUMN_UNIT_BYTE,
2844 tabstop);
2845 snprintf (expected, buf_len,
2846 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2847 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2850 pretty_printer pp;
2851 print_parseable_fixits (fc, &pp, &richloc,
2852 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2853 tabstop);
2854 snprintf (expected, buf_len,
2855 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2856 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2859 XDELETEVEC (expected);
2860 free (escaped_fname);
2863 /* Verify that
2864 diagnostic_get_location_text (..., SHOW_COLUMN)
2865 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2866 colorization disabled. */
2868 static void
2869 assert_location_text (const char *expected_loc_text,
2870 const char *filename, int line, int column,
2871 bool show_column,
2872 int origin = 1,
2873 enum diagnostics_column_unit column_unit
2874 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2876 test_diagnostic_context dc;
2877 dc.m_show_column = show_column;
2878 dc.m_column_unit = column_unit;
2879 dc.m_column_origin = origin;
2881 expanded_location xloc;
2882 xloc.file = filename;
2883 xloc.line = line;
2884 xloc.column = column;
2885 xloc.data = NULL;
2886 xloc.sysp = false;
2888 label_text actual_loc_text = dc.get_location_text (xloc);
2889 ASSERT_STREQ (expected_loc_text, actual_loc_text.get ());
2892 /* Verify that diagnostic_get_location_text works as expected. */
2894 static void
2895 test_diagnostic_get_location_text ()
2897 const char *old_progname = progname;
2898 progname = "PROGNAME";
2899 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2900 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2901 assert_location_text (built_in_colon, special_fname_builtin (),
2902 42, 10, true);
2903 free (built_in_colon);
2904 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2905 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2906 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2907 for (int origin = 0; origin != 2; ++origin)
2908 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2909 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2910 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2911 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2913 maybe_line_and_column (INT_MAX, INT_MAX);
2914 maybe_line_and_column (INT_MIN, INT_MIN);
2917 /* In order to test display columns vs byte columns, we need to create a
2918 file for location_get_source_line() to read. */
2920 const char *const content = "smile \xf0\x9f\x98\x82\n";
2921 const int line_bytes = strlen (content) - 1;
2922 const int def_tabstop = 8;
2923 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2924 const int display_width = cpp_display_width (content, line_bytes, policy);
2925 ASSERT_EQ (line_bytes - 2, display_width);
2926 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2927 const char *const fname = tmp.get_filename ();
2928 const int buf_len = strlen (fname) + 16;
2929 char *const expected = XNEWVEC (char, buf_len);
2931 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2932 assert_location_text (expected, fname, 1, line_bytes, true,
2933 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2935 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2936 assert_location_text (expected, fname, 1, line_bytes, true,
2937 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2939 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2940 assert_location_text (expected, fname, 1, line_bytes, true,
2941 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2943 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2944 assert_location_text (expected, fname, 1, line_bytes, true,
2945 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2947 XDELETEVEC (expected);
2951 progname = old_progname;
2954 /* Selftest for num_digits. */
2956 static void
2957 test_num_digits ()
2959 ASSERT_EQ (1, num_digits (0));
2960 ASSERT_EQ (1, num_digits (9));
2961 ASSERT_EQ (2, num_digits (10));
2962 ASSERT_EQ (2, num_digits (99));
2963 ASSERT_EQ (3, num_digits (100));
2964 ASSERT_EQ (3, num_digits (999));
2965 ASSERT_EQ (4, num_digits (1000));
2966 ASSERT_EQ (4, num_digits (9999));
2967 ASSERT_EQ (5, num_digits (10000));
2968 ASSERT_EQ (5, num_digits (99999));
2969 ASSERT_EQ (6, num_digits (100000));
2970 ASSERT_EQ (6, num_digits (999999));
2971 ASSERT_EQ (7, num_digits (1000000));
2972 ASSERT_EQ (7, num_digits (9999999));
2973 ASSERT_EQ (8, num_digits (10000000));
2974 ASSERT_EQ (8, num_digits (99999999));
2977 /* Run all of the selftests within this file. */
2979 void
2980 c_diagnostic_cc_tests ()
2982 test_print_escaped_string ();
2983 test_print_parseable_fixits_none ();
2984 test_print_parseable_fixits_insert ();
2985 test_print_parseable_fixits_remove ();
2986 test_print_parseable_fixits_replace ();
2987 test_print_parseable_fixits_bytes_vs_display_columns ();
2988 test_diagnostic_get_location_text ();
2989 test_num_digits ();
2993 } // namespace selftest
2995 #endif /* #if CHECKING_P */
2997 #if __GNUC__ >= 10
2998 # pragma GCC diagnostic pop
2999 #endif