rust: build failure after NON_DEPENDENT_EXPR removal [PR111899]
[official-gcc.git] / gcc / diagnostic.cc
blob0f392358aef618f67195a5b6fdf0eaf3e4b0aba5
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-text-art.h"
40 #include "diagnostic-diagram.h"
41 #include "edit-context.h"
42 #include "selftest.h"
43 #include "selftest-diagnostic.h"
44 #include "opts.h"
45 #include "cpplib.h"
46 #include "text-art/theme.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)->pedantic_errors ? DK_ERROR : DK_WARNING)
65 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
66 #define permissive_error_option(DC) ((DC)->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 error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
78 static void real_abort (void) ATTRIBUTE_NORETURN;
80 /* Name of program invoked, sans directories. */
82 const char *progname;
84 /* A diagnostic_context surrogate for stderr. */
85 static diagnostic_context global_diagnostic_context;
86 diagnostic_context *global_dc = &global_diagnostic_context;
88 /* Return a malloc'd string containing MSG formatted a la printf. The
89 caller is responsible for freeing the memory. */
90 char *
91 build_message_string (const char *msg, ...)
93 char *str;
94 va_list ap;
96 va_start (ap, msg);
97 str = xvasprintf (msg, ap);
98 va_end (ap);
100 return str;
103 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
104 char *
105 file_name_as_prefix (diagnostic_context *context, const char *f)
107 const char *locus_cs
108 = colorize_start (pp_show_color (context->printer), "locus");
109 const char *locus_ce = colorize_stop (pp_show_color (context->printer));
110 return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
115 /* Return the value of the getenv("COLUMNS") as an integer. If the
116 value is not set to a positive integer, use ioctl to get the
117 terminal width. If it fails, return INT_MAX. */
119 get_terminal_width (void)
121 const char * s = getenv ("COLUMNS");
122 if (s != NULL) {
123 int n = atoi (s);
124 if (n > 0)
125 return n;
128 #ifdef TIOCGWINSZ
129 struct winsize w;
130 w.ws_col = 0;
131 if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
132 return w.ws_col;
133 #endif
135 return INT_MAX;
138 /* Set caret_max_width to value. */
139 void
140 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
142 /* One minus to account for the leading empty space. */
143 value = value ? value - 1
144 : (isatty (fileno (pp_buffer (context->printer)->stream))
145 ? get_terminal_width () - 1: INT_MAX);
147 if (value <= 0)
148 value = INT_MAX;
150 context->m_source_printing.max_width = value;
153 /* Initialize the diagnostic message outputting machinery. */
154 void
155 diagnostic_initialize (diagnostic_context *context, int n_opts)
157 int i;
159 /* Allocate a basic pretty-printer. Clients will replace this a
160 much more elaborated pretty-printer if they wish. */
161 context->printer = XNEW (pretty_printer);
162 new (context->printer) pretty_printer ();
164 memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
165 context->warning_as_error_requested = false;
166 context->n_opts = n_opts;
167 context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
168 for (i = 0; i < n_opts; i++)
169 context->classify_diagnostic[i] = DK_UNSPECIFIED;
170 context->m_source_printing.enabled = false;
171 diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
172 for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
173 context->m_source_printing.caret_chars[i] = '^';
174 context->show_cwe = false;
175 context->show_rules = false;
176 context->path_format = DPF_NONE;
177 context->show_path_depths = false;
178 context->show_option_requested = false;
179 context->abort_on_error = false;
180 context->show_column = false;
181 context->pedantic_errors = false;
182 context->permissive = false;
183 context->opt_permissive = 0;
184 context->fatal_errors = false;
185 context->dc_inhibit_warnings = false;
186 context->dc_warn_system_headers = false;
187 context->max_errors = 0;
188 context->internal_error = NULL;
189 diagnostic_starter (context) = default_diagnostic_starter;
190 context->m_text_callbacks.start_span = default_diagnostic_start_span_fn;
191 diagnostic_finalizer (context) = default_diagnostic_finalizer;
192 context->option_enabled = NULL;
193 context->option_state = NULL;
194 context->option_name = NULL;
195 context->get_option_url = NULL;
196 context->last_location = UNKNOWN_LOCATION;
197 context->last_module = 0;
198 context->x_data = NULL;
199 context->lock = 0;
200 context->inhibit_notes_p = false;
201 context->m_source_printing.colorize_source_p = false;
202 context->m_source_printing.show_labels_p = false;
203 context->m_source_printing.show_line_numbers_p = false;
204 context->m_source_printing.min_margin_width = 0;
205 context->m_source_printing.show_ruler_p = false;
206 context->report_bug = false;
207 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_none;
208 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
210 if (!strcmp (var, "fixits-v1"))
211 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
212 else if (!strcmp (var, "fixits-v2"))
213 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
214 /* Silently ignore unrecognized values. */
216 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
217 context->column_origin = 1;
218 context->tabstop = 8;
219 context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
220 context->edit_context_ptr = NULL;
221 context->diagnostic_group_nesting_depth = 0;
222 context->diagnostic_group_emission_count = 0;
223 context->m_output_format = new diagnostic_text_output_format (*context);
224 context->set_locations_cb = nullptr;
225 context->ice_handler_cb = NULL;
226 context->includes_seen = NULL;
227 context->m_client_data_hooks = NULL;
228 context->m_diagrams.m_theme = NULL;
230 enum diagnostic_text_art_charset text_art_charset
231 = DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT;
232 if (const char *lang = getenv ("LANG"))
234 /* For LANG=C, don't assume the terminal supports anything
235 other than ASCII. */
236 if (!strcmp (lang, "C"))
237 text_art_charset = DIAGNOSTICS_TEXT_ART_CHARSET_ASCII;
239 diagnostics_text_art_charset_init (context, text_art_charset);
242 /* Maybe initialize the color support. We require clients to do this
243 explicitly, since most clients don't want color. When called
244 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
246 void
247 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
249 /* value == -1 is the default value. */
250 if (value < 0)
252 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
253 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
254 otherwise default to -fdiagnostics-color=never, for other
255 values default to that
256 -fdiagnostics-color={never,auto,always}. */
257 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
259 if (!getenv ("GCC_COLORS"))
260 return;
261 value = DIAGNOSTICS_COLOR_AUTO;
263 else
264 value = DIAGNOSTICS_COLOR_DEFAULT;
266 pp_show_color (context->printer)
267 = colorize_init ((diagnostic_color_rule_t) value);
270 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
272 void
273 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
275 /* value == -1 is the default value. */
276 if (value < 0)
278 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
279 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
280 environment, otherwise default to -fdiagnostics-urls=never,
281 for other values default to that
282 -fdiagnostics-urls={never,auto,always}. */
283 if (DIAGNOSTICS_URLS_DEFAULT == -1)
285 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
286 return;
287 value = DIAGNOSTICS_URL_AUTO;
289 else
290 value = DIAGNOSTICS_URLS_DEFAULT;
293 context->printer->url_format
294 = determine_url_format ((diagnostic_url_rule_t) value);
297 /* Create the file_cache, if not already created, and tell it how to
298 translate files on input. */
299 void diagnostic_initialize_input_context (diagnostic_context *context,
300 diagnostic_input_charset_callback ccb,
301 bool should_skip_bom)
303 if (!context->m_file_cache)
304 context->m_file_cache = new file_cache;
305 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
308 /* Do any cleaning up required after the last diagnostic is emitted. */
310 void
311 diagnostic_finish (diagnostic_context *context)
313 delete context->m_output_format;
314 context->m_output_format= nullptr;
316 if (context->m_diagrams.m_theme)
318 delete context->m_diagrams.m_theme;
319 context->m_diagrams.m_theme = NULL;
322 diagnostic_file_cache_fini ();
324 XDELETEVEC (context->classify_diagnostic);
325 context->classify_diagnostic = NULL;
327 /* diagnostic_initialize allocates context->printer using XNEW
328 and placement-new. */
329 context->printer->~pretty_printer ();
330 XDELETE (context->printer);
331 context->printer = NULL;
333 if (context->edit_context_ptr)
335 delete context->edit_context_ptr;
336 context->edit_context_ptr = NULL;
339 if (context->includes_seen)
341 delete context->includes_seen;
342 context->includes_seen = nullptr;
345 if (context->m_client_data_hooks)
347 delete context->m_client_data_hooks;
348 context->m_client_data_hooks = NULL;
352 /* Initialize DIAGNOSTIC, where the message MSG has already been
353 translated. */
354 void
355 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
356 va_list *args, rich_location *richloc,
357 diagnostic_t kind)
359 gcc_assert (richloc);
360 diagnostic->message.m_err_no = errno;
361 diagnostic->message.m_args_ptr = args;
362 diagnostic->message.m_format_spec = msg;
363 diagnostic->message.m_richloc = richloc;
364 diagnostic->richloc = richloc;
365 diagnostic->metadata = NULL;
366 diagnostic->kind = kind;
367 diagnostic->option_index = 0;
370 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
371 translated. */
372 void
373 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
374 va_list *args, rich_location *richloc,
375 diagnostic_t kind)
377 gcc_assert (richloc);
378 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
381 static const char *const diagnostic_kind_color[] = {
382 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
383 #include "diagnostic.def"
384 #undef DEFINE_DIAGNOSTIC_KIND
385 NULL
388 /* Get a color name for diagnostics of type KIND
389 Result could be NULL. */
391 const char *
392 diagnostic_get_color_for_kind (diagnostic_t kind)
394 return diagnostic_kind_color[kind];
397 /* Given an expanded_location, convert the column (which is in 1-based bytes)
398 to the requested units, without converting the origin.
399 Return -1 if the column is invalid (<= 0). */
401 static int
402 convert_column_unit (enum diagnostics_column_unit column_unit,
403 int tabstop,
404 expanded_location s)
406 if (s.column <= 0)
407 return -1;
409 switch (column_unit)
411 default:
412 gcc_unreachable ();
414 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
416 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
417 return location_compute_display_column (s, policy);
420 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
421 return s.column;
425 /* Given an expanded_location, convert the column (which is in 1-based bytes)
426 to the requested units and origin. Return -1 if the column is
427 invalid (<= 0). */
429 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
431 int one_based_col
432 = convert_column_unit (context->column_unit, context->tabstop, s);
433 if (one_based_col <= 0)
434 return -1;
435 return one_based_col + (context->column_origin - 1);
438 /* Return a formatted line and column ':%line:%column'. Elided if
439 line == 0 or col < 0. (A column of 0 may be valid due to the
440 -fdiagnostics-column-origin option.)
441 The result is a statically allocated buffer. */
443 static const char *
444 maybe_line_and_column (int line, int col)
446 static char result[32];
448 if (line)
450 size_t l
451 = snprintf (result, sizeof (result),
452 col >= 0 ? ":%d:%d" : ":%d", line, col);
453 gcc_checking_assert (l < sizeof (result));
455 else
456 result[0] = 0;
457 return result;
460 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
461 The caller is responsible for freeing the memory. */
463 static char *
464 diagnostic_get_location_text (diagnostic_context *context,
465 expanded_location s)
467 pretty_printer *pp = context->printer;
468 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
469 const char *locus_ce = colorize_stop (pp_show_color (pp));
470 const char *file = s.file ? s.file : progname;
471 int line = 0;
472 int col = -1;
473 if (strcmp (file, special_fname_builtin ()))
475 line = s.line;
476 if (context->show_column)
477 col = diagnostic_converted_column (context, s);
480 const char *line_col = maybe_line_and_column (line, col);
481 return build_message_string ("%s%s%s:%s", locus_cs, file,
482 line_col, locus_ce);
485 static const char *const diagnostic_kind_text[] = {
486 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
487 #include "diagnostic.def"
488 #undef DEFINE_DIAGNOSTIC_KIND
489 "must-not-happen"
492 /* Return a malloc'd string describing a location and the severity of the
493 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
494 freeing the memory. */
495 char *
496 diagnostic_build_prefix (diagnostic_context *context,
497 const diagnostic_info *diagnostic)
499 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
501 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
502 const char *text_cs = "", *text_ce = "";
503 pretty_printer *pp = context->printer;
505 if (diagnostic_kind_color[diagnostic->kind])
507 text_cs = colorize_start (pp_show_color (pp),
508 diagnostic_kind_color[diagnostic->kind]);
509 text_ce = colorize_stop (pp_show_color (pp));
512 expanded_location s = diagnostic_expand_location (diagnostic);
513 char *location_text = diagnostic_get_location_text (context, s);
515 char *result = build_message_string ("%s %s%s%s", location_text,
516 text_cs, text, text_ce);
517 free (location_text);
518 return result;
521 /* Functions at which to stop the backtrace print. It's not
522 particularly helpful to print the callers of these functions. */
524 static const char * const bt_stop[] =
526 "main",
527 "toplev::main",
528 "execute_one_pass",
529 "compile_file",
532 /* A callback function passed to the backtrace_full function. */
534 static int
535 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
536 const char *function)
538 int *pcount = (int *) data;
540 /* If we don't have any useful information, don't print
541 anything. */
542 if (filename == NULL && function == NULL)
543 return 0;
545 /* Skip functions in diagnostic.cc. */
546 if (*pcount == 0
547 && filename != NULL
548 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
549 return 0;
551 /* Print up to 20 functions. We could make this a --param, but
552 since this is only for debugging just use a constant for now. */
553 if (*pcount >= 20)
555 /* Returning a non-zero value stops the backtrace. */
556 return 1;
558 ++*pcount;
560 char *alc = NULL;
561 if (function != NULL)
563 char *str = cplus_demangle_v3 (function,
564 (DMGL_VERBOSE | DMGL_ANSI
565 | DMGL_GNU_V3 | DMGL_PARAMS));
566 if (str != NULL)
568 alc = str;
569 function = str;
572 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
574 size_t len = strlen (bt_stop[i]);
575 if (strncmp (function, bt_stop[i], len) == 0
576 && (function[len] == '\0' || function[len] == '('))
578 if (alc != NULL)
579 free (alc);
580 /* Returning a non-zero value stops the backtrace. */
581 return 1;
586 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
587 (unsigned long) pc,
588 function == NULL ? "???" : function,
589 filename == NULL ? "???" : filename,
590 lineno);
592 if (alc != NULL)
593 free (alc);
595 return 0;
598 /* A callback function passed to the backtrace_full function. This is
599 called if backtrace_full has an error. */
601 static void
602 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
604 if (errnum < 0)
606 /* This means that no debug info was available. Just quietly
607 skip printing backtrace info. */
608 return;
610 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
611 errnum == 0 ? "" : xstrerror (errnum));
614 /* Check if we've met the maximum error limit, and if so fatally exit
615 with a message. CONTEXT is the context to check, and FLUSH
616 indicates whether a diagnostic_finish call is needed. */
618 void
619 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
621 if (!context->max_errors)
622 return;
624 int count = (diagnostic_kind_count (context, DK_ERROR)
625 + diagnostic_kind_count (context, DK_SORRY)
626 + diagnostic_kind_count (context, DK_WERROR));
628 if (count >= context->max_errors)
630 fnotice (stderr,
631 "compilation terminated due to -fmax-errors=%u.\n",
632 context->max_errors);
633 if (flush)
634 diagnostic_finish (context);
635 exit (FATAL_EXIT_CODE);
639 /* Take any action which is expected to happen after the diagnostic
640 is written out. This function does not always return. */
641 void
642 diagnostic_action_after_output (diagnostic_context *context,
643 diagnostic_t diag_kind)
645 switch (diag_kind)
647 case DK_DEBUG:
648 case DK_NOTE:
649 case DK_ANACHRONISM:
650 case DK_WARNING:
651 break;
653 case DK_ERROR:
654 case DK_SORRY:
655 if (context->abort_on_error)
656 real_abort ();
657 if (context->fatal_errors)
659 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
660 diagnostic_finish (context);
661 exit (FATAL_EXIT_CODE);
663 break;
665 case DK_ICE:
666 case DK_ICE_NOBT:
668 /* Optional callback for attempting to handle ICEs gracefully. */
669 if (void (*ice_handler_cb) (diagnostic_context *)
670 = context->ice_handler_cb)
672 /* Clear the callback, to avoid potentially re-entering
673 the routine if there's a crash within the handler. */
674 context->ice_handler_cb = NULL;
675 ice_handler_cb (context);
677 /* The context might have had diagnostic_finish called on
678 it at this point. */
680 struct backtrace_state *state = NULL;
681 if (diag_kind == DK_ICE)
682 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
683 int count = 0;
684 if (state != NULL)
685 backtrace_full (state, 2, bt_callback, bt_err_callback,
686 (void *) &count);
688 if (context->abort_on_error)
689 real_abort ();
691 if (context->report_bug)
692 fnotice (stderr, "Please submit a full bug report, "
693 "with preprocessed source.\n");
694 else
695 fnotice (stderr, "Please submit a full bug report, "
696 "with preprocessed source (by using -freport-bug).\n");
698 if (count > 0)
699 fnotice (stderr, "Please include the complete backtrace "
700 "with any bug report.\n");
701 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
703 exit (ICE_EXIT_CODE);
706 case DK_FATAL:
707 if (context->abort_on_error)
708 real_abort ();
709 diagnostic_finish (context);
710 fnotice (stderr, "compilation terminated.\n");
711 exit (FATAL_EXIT_CODE);
713 default:
714 gcc_unreachable ();
718 /* True if the last module or file in which a diagnostic was reported is
719 different from the current one. */
721 static bool
722 last_module_changed_p (diagnostic_context *context,
723 const line_map_ordinary *map)
725 return context->last_module != map;
728 /* Remember the current module or file as being the last one in which we
729 report a diagnostic. */
731 static void
732 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
734 context->last_module = map;
737 /* Only dump the "In file included from..." stack once for each file. */
739 static bool
740 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
742 /* No include path for main. */
743 if (MAIN_FILE_P (map))
744 return true;
746 /* Always identify C++ modules, at least for now. */
747 auto probe = map;
748 if (linemap_check_ordinary (map)->reason == LC_RENAME)
749 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
750 probe = linemap_included_from_linemap (line_table, map);
751 if (MAP_MODULE_P (probe))
752 return false;
754 if (!context->includes_seen)
755 context->includes_seen = new hash_set<location_t, false, location_hash>;
757 /* Hash the location of the #include directive to better handle files
758 that are included multiple times with different macros defined. */
759 return context->includes_seen->add (linemap_included_from (map));
762 void
763 diagnostic_report_current_module (diagnostic_context *context, location_t where)
765 const line_map_ordinary *map = NULL;
767 if (pp_needs_newline (context->printer))
769 pp_newline (context->printer);
770 pp_needs_newline (context->printer) = false;
773 if (where <= BUILTINS_LOCATION)
774 return;
776 linemap_resolve_location (line_table, where,
777 LRK_MACRO_DEFINITION_LOCATION,
778 &map);
780 if (map && last_module_changed_p (context, map))
782 set_last_module (context, map);
783 if (!includes_seen (context, map))
785 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
786 expanded_location s = {};
789 where = linemap_included_from (map);
790 map = linemap_included_from_linemap (line_table, map);
791 bool is_module = MAP_MODULE_P (map);
792 s.file = LINEMAP_FILE (map);
793 s.line = SOURCE_LINE (map, where);
794 int col = -1;
795 if (first && context->show_column)
797 s.column = SOURCE_COLUMN (map, where);
798 col = diagnostic_converted_column (context, s);
800 const char *line_col = maybe_line_and_column (s.line, col);
801 static const char *const msgs[] =
803 NULL,
804 N_(" from"),
805 N_("In file included from"), /* 2 */
806 N_(" included from"),
807 N_("In module"), /* 4 */
808 N_("of module"),
809 N_("In module imported at"), /* 6 */
810 N_("imported at"),
813 unsigned index = (was_module ? 6 : is_module ? 4
814 : need_inc ? 2 : 0) + !first;
816 pp_verbatim (context->printer, "%s%s %r%s%s%R",
817 first ? "" : was_module ? ", " : ",\n",
818 _(msgs[index]),
819 "locus", s.file, line_col);
820 first = false, need_inc = was_module, was_module = is_module;
822 while (!includes_seen (context, map));
823 pp_verbatim (context->printer, ":");
824 pp_newline (context->printer);
829 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
830 print the path. */
832 void
833 diagnostic_show_any_path (diagnostic_context *context,
834 diagnostic_info *diagnostic)
836 const diagnostic_path *path = diagnostic->richloc->get_path ();
837 if (!path)
838 return;
840 if (context->print_path)
841 context->print_path (context, path);
844 /* class diagnostic_event. */
846 /* struct diagnostic_event::meaning. */
848 void
849 diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
851 bool need_comma = false;
852 pp_character (pp, '{');
853 if (const char *verb_str = maybe_get_verb_str (m_verb))
855 pp_printf (pp, "verb: %qs", verb_str);
856 need_comma = true;
858 if (const char *noun_str = maybe_get_noun_str (m_noun))
860 if (need_comma)
861 pp_string (pp, ", ");
862 pp_printf (pp, "noun: %qs", noun_str);
863 need_comma = true;
865 if (const char *property_str = maybe_get_property_str (m_property))
867 if (need_comma)
868 pp_string (pp, ", ");
869 pp_printf (pp, "property: %qs", property_str);
870 need_comma = true;
872 pp_character (pp, '}');
875 /* Get a string (or NULL) for V suitable for use within a SARIF
876 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
878 const char *
879 diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
881 switch (v)
883 default:
884 gcc_unreachable ();
885 case VERB_unknown:
886 return NULL;
887 case VERB_acquire:
888 return "acquire";
889 case VERB_release:
890 return "release";
891 case VERB_enter:
892 return "enter";
893 case VERB_exit:
894 return "exit";
895 case VERB_call:
896 return "call";
897 case VERB_return:
898 return "return";
899 case VERB_branch:
900 return "branch";
901 case VERB_danger:
902 return "danger";
906 /* Get a string (or NULL) for N suitable for use within a SARIF
907 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
909 const char *
910 diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
912 switch (n)
914 default:
915 gcc_unreachable ();
916 case NOUN_unknown:
917 return NULL;
918 case NOUN_taint:
919 return "taint";
920 case NOUN_sensitive:
921 return "sensitive";
922 case NOUN_function:
923 return "function";
924 case NOUN_lock:
925 return "lock";
926 case NOUN_memory:
927 return "memory";
928 case NOUN_resource:
929 return "resource";
933 /* Get a string (or NULL) for P suitable for use within a SARIF
934 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
936 const char *
937 diagnostic_event::meaning::maybe_get_property_str (enum property p)
939 switch (p)
941 default:
942 gcc_unreachable ();
943 case PROPERTY_unknown:
944 return NULL;
945 case PROPERTY_true:
946 return "true";
947 case PROPERTY_false:
948 return "false";
952 /* class diagnostic_path. */
954 /* Subroutint of diagnostic_path::interprocedural_p.
955 Look for the first event in this path that is within a function
956 i.e. has a non-NULL fndecl, and a non-zero stack depth.
957 If found, write its index to *OUT_IDX and return true.
958 Otherwise return false. */
960 bool
961 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
963 const unsigned num = num_events ();
964 for (unsigned i = 0; i < num; i++)
966 if (!(get_event (i).get_fndecl () == NULL
967 && get_event (i).get_stack_depth () == 0))
969 *out_idx = i;
970 return true;
973 return false;
976 /* Return true if the events in this path involve more than one
977 function, or false if it is purely intraprocedural. */
979 bool
980 diagnostic_path::interprocedural_p () const
982 /* Ignore leading events that are outside of any function. */
983 unsigned first_fn_event_idx;
984 if (!get_first_event_in_a_function (&first_fn_event_idx))
985 return false;
987 const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
988 tree first_fndecl = first_fn_event.get_fndecl ();
989 int first_fn_stack_depth = first_fn_event.get_stack_depth ();
991 const unsigned num = num_events ();
992 for (unsigned i = first_fn_event_idx + 1; i < num; i++)
994 if (get_event (i).get_fndecl () != first_fndecl)
995 return true;
996 if (get_event (i).get_stack_depth () != first_fn_stack_depth)
997 return true;
999 return false;
1002 void
1003 default_diagnostic_starter (diagnostic_context *context,
1004 diagnostic_info *diagnostic)
1006 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
1007 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
1008 diagnostic));
1011 void
1012 default_diagnostic_start_span_fn (diagnostic_context *context,
1013 expanded_location exploc)
1015 char *text = diagnostic_get_location_text (context, exploc);
1016 pp_string (context->printer, text);
1017 free (text);
1018 pp_newline (context->printer);
1021 void
1022 default_diagnostic_finalizer (diagnostic_context *context,
1023 diagnostic_info *diagnostic,
1024 diagnostic_t)
1026 char *saved_prefix = pp_take_prefix (context->printer);
1027 pp_set_prefix (context->printer, NULL);
1028 pp_newline (context->printer);
1029 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
1030 pp_set_prefix (context->printer, saved_prefix);
1031 pp_flush (context->printer);
1034 /* Interface to specify diagnostic kind overrides. Returns the
1035 previous setting, or DK_UNSPECIFIED if the parameters are out of
1036 range. If OPTION_INDEX is zero, the new setting is for all the
1037 diagnostics. */
1038 diagnostic_t
1039 diagnostic_classify_diagnostic (diagnostic_context *context,
1040 int option_index,
1041 diagnostic_t new_kind,
1042 location_t where)
1044 diagnostic_t old_kind;
1046 if (option_index < 0
1047 || option_index >= context->n_opts
1048 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1049 return DK_UNSPECIFIED;
1051 old_kind = context->classify_diagnostic[option_index];
1053 /* Handle pragmas separately, since we need to keep track of *where*
1054 the pragmas were. */
1055 if (where != UNKNOWN_LOCATION)
1057 int i;
1059 /* Record the command-line status, so we can reset it back on DK_POP. */
1060 if (old_kind == DK_UNSPECIFIED)
1062 old_kind = !context->option_enabled (option_index,
1063 context->lang_mask,
1064 context->option_state)
1065 ? DK_IGNORED : (context->warning_as_error_requested
1066 ? DK_ERROR : DK_WARNING);
1067 context->classify_diagnostic[option_index] = old_kind;
1070 for (i = context->n_classification_history - 1; i >= 0; i --)
1071 if (context->classification_history[i].option == option_index)
1073 old_kind = context->classification_history[i].kind;
1074 break;
1077 i = context->n_classification_history;
1078 context->classification_history =
1079 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1080 * sizeof (diagnostic_classification_change_t));
1081 context->classification_history[i].location = where;
1082 context->classification_history[i].option = option_index;
1083 context->classification_history[i].kind = new_kind;
1084 context->n_classification_history ++;
1086 else
1087 context->classify_diagnostic[option_index] = new_kind;
1089 return old_kind;
1092 /* Save all diagnostic classifications in a stack. */
1093 void
1094 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
1096 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
1097 context->push_list[context->n_push ++] = context->n_classification_history;
1100 /* Restore the topmost classification set off the stack. If the stack
1101 is empty, revert to the state based on command line parameters. */
1102 void
1103 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
1105 int jump_to;
1106 int i;
1108 if (context->n_push)
1109 jump_to = context->push_list [-- context->n_push];
1110 else
1111 jump_to = 0;
1113 i = context->n_classification_history;
1114 context->classification_history =
1115 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1116 * sizeof (diagnostic_classification_change_t));
1117 context->classification_history[i].location = where;
1118 context->classification_history[i].option = jump_to;
1119 context->classification_history[i].kind = DK_POP;
1120 context->n_classification_history ++;
1123 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1124 escaping rules for -fdiagnostics-parseable-fixits. */
1126 static void
1127 print_escaped_string (pretty_printer *pp, const char *text)
1129 gcc_assert (pp);
1130 gcc_assert (text);
1132 pp_character (pp, '"');
1133 for (const char *ch = text; *ch; ch++)
1135 switch (*ch)
1137 case '\\':
1138 /* Escape backslash as two backslashes. */
1139 pp_string (pp, "\\\\");
1140 break;
1141 case '\t':
1142 /* Escape tab as "\t". */
1143 pp_string (pp, "\\t");
1144 break;
1145 case '\n':
1146 /* Escape newline as "\n". */
1147 pp_string (pp, "\\n");
1148 break;
1149 case '"':
1150 /* Escape doublequotes as \". */
1151 pp_string (pp, "\\\"");
1152 break;
1153 default:
1154 if (ISPRINT (*ch))
1155 pp_character (pp, *ch);
1156 else
1157 /* Use octal for non-printable chars. */
1159 unsigned char c = (*ch & 0xff);
1160 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1162 break;
1165 pp_character (pp, '"');
1168 /* Implementation of -fdiagnostics-parseable-fixits and
1169 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1170 Print a machine-parseable version of all fixits in RICHLOC to PP,
1171 using COLUMN_UNIT to express columns.
1172 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1174 static void
1175 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1176 enum diagnostics_column_unit column_unit,
1177 int tabstop)
1179 gcc_assert (pp);
1180 gcc_assert (richloc);
1182 char *saved_prefix = pp_take_prefix (pp);
1183 pp_set_prefix (pp, NULL);
1185 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1187 const fixit_hint *hint = richloc->get_fixit_hint (i);
1188 location_t start_loc = hint->get_start_loc ();
1189 expanded_location start_exploc = expand_location (start_loc);
1190 pp_string (pp, "fix-it:");
1191 print_escaped_string (pp, start_exploc.file);
1192 /* For compatibility with clang, print as a half-open range. */
1193 location_t next_loc = hint->get_next_loc ();
1194 expanded_location next_exploc = expand_location (next_loc);
1195 int start_col
1196 = convert_column_unit (column_unit, tabstop, start_exploc);
1197 int next_col
1198 = convert_column_unit (column_unit, tabstop, next_exploc);
1199 pp_printf (pp, ":{%i:%i-%i:%i}:",
1200 start_exploc.line, start_col,
1201 next_exploc.line, next_col);
1202 print_escaped_string (pp, hint->get_string ());
1203 pp_newline (pp);
1206 pp_set_prefix (pp, saved_prefix);
1209 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1211 static void
1212 get_any_inlining_info (diagnostic_context *context,
1213 diagnostic_info *diagnostic)
1215 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1217 if (context->set_locations_cb)
1218 /* Retrieve the locations into which the expression about to be
1219 diagnosed has been inlined, including those of all the callers
1220 all the way down the inlining stack. */
1221 context->set_locations_cb (context, diagnostic);
1222 else
1224 /* When there's no callback use just the one location provided
1225 by the caller of the diagnostic function. */
1226 location_t loc = diagnostic_location (diagnostic);
1227 ilocs.safe_push (loc);
1228 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1232 /* Update the kind of DIAGNOSTIC based on its location(s), including
1233 any of those in its inlining stack, relative to any
1234 #pragma GCC diagnostic
1235 directives recorded within CONTEXT.
1237 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1238 otherwise. */
1240 static diagnostic_t
1241 update_effective_level_from_pragmas (diagnostic_context *context,
1242 diagnostic_info *diagnostic)
1244 if (context->n_classification_history <= 0)
1245 return DK_UNSPECIFIED;
1247 /* Iterate over the locations, checking the diagnostic disposition
1248 for the diagnostic at each. If it's explicitly set as opposed
1249 to unspecified, update the disposition for this instance of
1250 the diagnostic and return it. */
1251 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1253 /* FIXME: Stupid search. Optimize later. */
1254 for (int i = context->n_classification_history - 1; i >= 0; i --)
1256 const diagnostic_classification_change_t &hist
1257 = context->classification_history[i];
1259 location_t pragloc = hist.location;
1260 if (!linemap_location_before_p (line_table, pragloc, loc))
1261 continue;
1263 if (hist.kind == (int) DK_POP)
1265 /* Move on to the next region. */
1266 i = hist.option;
1267 continue;
1270 int option = hist.option;
1271 /* The option 0 is for all the diagnostics. */
1272 if (option == 0 || option == diagnostic->option_index)
1274 diagnostic_t kind = hist.kind;
1275 if (kind != DK_UNSPECIFIED)
1276 diagnostic->kind = kind;
1277 return kind;
1282 return DK_UNSPECIFIED;
1285 /* Generate a URL string describing CWE. The caller is responsible for
1286 freeing the string. */
1288 char *
1289 get_cwe_url (int cwe)
1291 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1294 /* If DIAGNOSTIC has a CWE identifier, print it.
1296 For example, if the diagnostic metadata associates it with CWE-119,
1297 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1298 description of the security issue. */
1300 static void
1301 print_any_cwe (diagnostic_context *context,
1302 const diagnostic_info *diagnostic)
1304 if (diagnostic->metadata == NULL)
1305 return;
1307 int cwe = diagnostic->metadata->get_cwe ();
1308 if (cwe)
1310 pretty_printer *pp = context->printer;
1311 char *saved_prefix = pp_take_prefix (context->printer);
1312 pp_string (pp, " [");
1313 pp_string (pp, colorize_start (pp_show_color (pp),
1314 diagnostic_kind_color[diagnostic->kind]));
1315 if (pp->url_format != URL_FORMAT_NONE)
1317 char *cwe_url = get_cwe_url (cwe);
1318 pp_begin_url (pp, cwe_url);
1319 free (cwe_url);
1321 pp_printf (pp, "CWE-%i", cwe);
1322 pp_set_prefix (context->printer, saved_prefix);
1323 if (pp->url_format != URL_FORMAT_NONE)
1324 pp_end_url (pp);
1325 pp_string (pp, colorize_stop (pp_show_color (pp)));
1326 pp_character (pp, ']');
1330 /* If DIAGNOSTIC has any rules associated with it, print them.
1332 For example, if the diagnostic metadata associates it with a rule
1333 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1334 with any URL provided by the rule. */
1336 static void
1337 print_any_rules (diagnostic_context *context,
1338 const diagnostic_info *diagnostic)
1340 if (diagnostic->metadata == NULL)
1341 return;
1343 for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
1345 const diagnostic_metadata::rule &rule
1346 = diagnostic->metadata->get_rule (idx);
1347 if (char *desc = rule.make_description ())
1349 pretty_printer *pp = context->printer;
1350 char *saved_prefix = pp_take_prefix (context->printer);
1351 pp_string (pp, " [");
1352 pp_string (pp,
1353 colorize_start (pp_show_color (pp),
1354 diagnostic_kind_color[diagnostic->kind]));
1355 char *url = NULL;
1356 if (pp->url_format != URL_FORMAT_NONE)
1358 url = rule.make_url ();
1359 if (url)
1360 pp_begin_url (pp, url);
1362 pp_string (pp, desc);
1363 pp_set_prefix (context->printer, saved_prefix);
1364 if (pp->url_format != URL_FORMAT_NONE)
1365 if (url)
1366 pp_end_url (pp);
1367 free (url);
1368 pp_string (pp, colorize_stop (pp_show_color (pp)));
1369 pp_character (pp, ']');
1370 free (desc);
1375 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1376 printer, e.g. " [-Werror=uninitialized]".
1377 Subroutine of diagnostic_report_diagnostic. */
1379 static void
1380 print_option_information (diagnostic_context *context,
1381 const diagnostic_info *diagnostic,
1382 diagnostic_t orig_diag_kind)
1384 char *option_text;
1386 option_text = context->option_name (context, diagnostic->option_index,
1387 orig_diag_kind, diagnostic->kind);
1389 if (option_text)
1391 char *option_url = NULL;
1392 if (context->get_option_url
1393 && context->printer->url_format != URL_FORMAT_NONE)
1394 option_url = context->get_option_url (context,
1395 diagnostic->option_index);
1396 pretty_printer *pp = context->printer;
1397 pp_string (pp, " [");
1398 pp_string (pp, colorize_start (pp_show_color (pp),
1399 diagnostic_kind_color[diagnostic->kind]));
1400 if (option_url)
1401 pp_begin_url (pp, option_url);
1402 pp_string (pp, option_text);
1403 if (option_url)
1405 pp_end_url (pp);
1406 free (option_url);
1408 pp_string (pp, colorize_stop (pp_show_color (pp)));
1409 pp_character (pp, ']');
1410 free (option_text);
1414 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1415 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1417 static bool
1418 diagnostic_enabled (diagnostic_context *context,
1419 diagnostic_info *diagnostic)
1421 /* Update the inlining stack for this diagnostic. */
1422 get_any_inlining_info (context, diagnostic);
1424 /* Diagnostics with no option or -fpermissive are always enabled. */
1425 if (!diagnostic->option_index
1426 || diagnostic->option_index == permissive_error_option (context))
1427 return true;
1429 /* This tests if the user provided the appropriate -Wfoo or
1430 -Wno-foo option. */
1431 if (! context->option_enabled (diagnostic->option_index,
1432 context->lang_mask,
1433 context->option_state))
1434 return false;
1436 /* This tests for #pragma diagnostic changes. */
1437 diagnostic_t diag_class
1438 = update_effective_level_from_pragmas (context, diagnostic);
1440 /* This tests if the user provided the appropriate -Werror=foo
1441 option. */
1442 if (diag_class == DK_UNSPECIFIED
1443 && (context->classify_diagnostic[diagnostic->option_index]
1444 != DK_UNSPECIFIED))
1445 diagnostic->kind
1446 = context->classify_diagnostic[diagnostic->option_index];
1448 /* This allows for future extensions, like temporarily disabling
1449 warnings for ranges of source code. */
1450 if (diagnostic->kind == DK_IGNORED)
1451 return false;
1453 return true;
1456 /* Returns whether warning OPT is enabled at LOC. */
1458 bool
1459 warning_enabled_at (location_t loc, int opt)
1461 if (!diagnostic_report_warnings_p (global_dc, loc))
1462 return false;
1464 rich_location richloc (line_table, loc);
1465 diagnostic_info diagnostic = {};
1466 diagnostic.option_index = opt;
1467 diagnostic.richloc = &richloc;
1468 diagnostic.message.m_richloc = &richloc;
1469 diagnostic.kind = DK_WARNING;
1470 return diagnostic_enabled (global_dc, &diagnostic);
1473 /* Report a diagnostic message (an error or a warning) as specified by
1474 DC. This function is *the* subroutine in terms of which front-ends
1475 should implement their specific diagnostic handling modules. The
1476 front-end independent format specifiers are exactly those described
1477 in the documentation of output_format.
1478 Return true if a diagnostic was printed, false otherwise. */
1480 bool
1481 diagnostic_report_diagnostic (diagnostic_context *context,
1482 diagnostic_info *diagnostic)
1484 diagnostic_t orig_diag_kind = diagnostic->kind;
1486 gcc_assert (context->m_output_format);
1488 /* Give preference to being able to inhibit warnings, before they
1489 get reclassified to something else. */
1490 bool was_warning = (diagnostic->kind == DK_WARNING
1491 || diagnostic->kind == DK_PEDWARN);
1492 if (was_warning && context->dc_inhibit_warnings)
1493 return false;
1495 if (diagnostic->kind == DK_PEDWARN)
1497 diagnostic->kind = pedantic_warning_kind (context);
1498 /* We do this to avoid giving the message for -pedantic-errors. */
1499 orig_diag_kind = diagnostic->kind;
1502 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1503 return false;
1505 if (context->lock > 0)
1507 /* If we're reporting an ICE in the middle of some other error,
1508 try to flush out the previous error, then let this one
1509 through. Don't do this more than once. */
1510 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1511 && context->lock == 1)
1512 pp_newline_and_flush (context->printer);
1513 else
1514 error_recursion (context);
1517 /* If the user requested that warnings be treated as errors, so be
1518 it. Note that we do this before the next block so that
1519 individual warnings can be overridden back to warnings with
1520 -Wno-error=*. */
1521 if (context->warning_as_error_requested
1522 && diagnostic->kind == DK_WARNING)
1523 diagnostic->kind = DK_ERROR;
1525 diagnostic->message.m_data = &diagnostic->x_data;
1527 /* Check to see if the diagnostic is enabled at the location and
1528 not disabled by #pragma GCC diagnostic anywhere along the inlining
1529 stack. . */
1530 if (!diagnostic_enabled (context, diagnostic))
1531 return false;
1533 if ((was_warning || diagnostic->kind == DK_WARNING)
1534 && ((!context->dc_warn_system_headers
1535 && diagnostic->m_iinfo.m_allsyslocs)
1536 || context->dc_inhibit_warnings))
1537 /* Bail if the warning is not to be reported because all locations in the
1538 inlining stack (if there is one) are in system headers. */
1539 return false;
1541 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1542 diagnostic_check_max_errors (context);
1544 context->lock++;
1546 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1548 /* When not checking, ICEs are converted to fatal errors when an
1549 error has already occurred. This is counteracted by
1550 abort_on_error. */
1551 if (!CHECKING_P
1552 && (diagnostic_kind_count (context, DK_ERROR) > 0
1553 || diagnostic_kind_count (context, DK_SORRY) > 0)
1554 && !context->abort_on_error)
1556 expanded_location s
1557 = expand_location (diagnostic_location (diagnostic));
1558 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1559 s.file, s.line);
1560 exit (ICE_EXIT_CODE);
1562 if (context->internal_error)
1563 (*context->internal_error) (context,
1564 diagnostic->message.m_format_spec,
1565 diagnostic->message.m_args_ptr);
1567 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1568 ++diagnostic_kind_count (context, DK_WERROR);
1569 else
1570 ++diagnostic_kind_count (context, diagnostic->kind);
1572 /* Is this the initial diagnostic within the stack of groups? */
1573 if (context->diagnostic_group_emission_count == 0)
1574 context->m_output_format->on_begin_group ();
1575 context->diagnostic_group_emission_count++;
1577 pp_format (context->printer, &diagnostic->message);
1578 context->m_output_format->on_begin_diagnostic (diagnostic);
1579 pp_output_formatted_text (context->printer);
1580 if (context->show_cwe)
1581 print_any_cwe (context, diagnostic);
1582 if (context->show_rules)
1583 print_any_rules (context, diagnostic);
1584 if (context->show_option_requested)
1585 print_option_information (context, diagnostic, orig_diag_kind);
1586 context->m_output_format->on_end_diagnostic (diagnostic, orig_diag_kind);
1587 switch (context->extra_output_kind)
1589 default:
1590 break;
1591 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1592 print_parseable_fixits (context->printer, diagnostic->richloc,
1593 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1594 context->tabstop);
1595 pp_flush (context->printer);
1596 break;
1597 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1598 print_parseable_fixits (context->printer, diagnostic->richloc,
1599 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1600 context->tabstop);
1601 pp_flush (context->printer);
1602 break;
1604 diagnostic_action_after_output (context, diagnostic->kind);
1605 diagnostic->x_data = NULL;
1607 if (context->edit_context_ptr)
1608 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1609 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1611 context->lock--;
1613 diagnostic_show_any_path (context, diagnostic);
1615 return true;
1618 /* Get the number of digits in the decimal representation of VALUE. */
1621 num_digits (int value)
1623 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1624 using floating point. */
1625 gcc_assert (value >= 0);
1627 if (value == 0)
1628 return 1;
1630 int digits = 0;
1631 while (value > 0)
1633 digits++;
1634 value /= 10;
1636 return digits;
1639 /* Given a partial pathname as input, return another pathname that
1640 shares no directory elements with the pathname of __FILE__. This
1641 is used by fancy_abort() to print `internal compiler error in expr.cc'
1642 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1644 const char *
1645 trim_filename (const char *name)
1647 static const char this_file[] = __FILE__;
1648 const char *p = name, *q = this_file;
1650 /* First skip any "../" in each filename. This allows us to give a proper
1651 reference to a file in a subdirectory. */
1652 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1653 p += 3;
1655 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1656 q += 3;
1658 /* Now skip any parts the two filenames have in common. */
1659 while (*p == *q && *p != 0 && *q != 0)
1660 p++, q++;
1662 /* Now go backwards until the previous directory separator. */
1663 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1664 p--;
1666 return p;
1669 /* Standard error reporting routines in increasing order of severity.
1670 All of these take arguments like printf. */
1672 /* Text to be emitted verbatim to the error message stream; this
1673 produces no prefix and disables line-wrapping. Use rarely. */
1674 void
1675 verbatim (const char *gmsgid, ...)
1677 va_list ap;
1679 va_start (ap, gmsgid);
1680 text_info text (_(gmsgid), &ap, errno);
1681 pp_format_verbatim (global_dc->printer, &text);
1682 pp_newline_and_flush (global_dc->printer);
1683 va_end (ap);
1686 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1687 void
1688 diagnostic_append_note (diagnostic_context *context,
1689 location_t location,
1690 const char * gmsgid, ...)
1692 diagnostic_info diagnostic;
1693 va_list ap;
1694 rich_location richloc (line_table, location);
1696 va_start (ap, gmsgid);
1697 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1698 if (context->inhibit_notes_p)
1700 va_end (ap);
1701 return;
1703 char *saved_prefix = pp_take_prefix (context->printer);
1704 pp_set_prefix (context->printer,
1705 diagnostic_build_prefix (context, &diagnostic));
1706 pp_format (context->printer, &diagnostic.message);
1707 pp_output_formatted_text (context->printer);
1708 pp_destroy_prefix (context->printer);
1709 pp_set_prefix (context->printer, saved_prefix);
1710 pp_newline (context->printer);
1711 diagnostic_show_locus (context, &richloc, DK_NOTE);
1712 va_end (ap);
1715 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1716 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1717 and internal_error_no_backtrace, as documented and defined below. */
1718 static bool
1719 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1720 int opt, const char *gmsgid,
1721 va_list *ap, diagnostic_t kind)
1723 diagnostic_info diagnostic;
1724 if (kind == DK_PERMERROR)
1726 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1727 permissive_error_kind (global_dc));
1728 diagnostic.option_index = (opt != -1 ? opt
1729 : permissive_error_option (global_dc));
1731 else
1733 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1734 if (kind == DK_WARNING || kind == DK_PEDWARN)
1735 diagnostic.option_index = opt;
1737 diagnostic.metadata = metadata;
1738 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1741 /* Implement inform_n, warning_n, and error_n, as documented and
1742 defined below. */
1743 static bool
1744 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1745 int opt, unsigned HOST_WIDE_INT n,
1746 const char *singular_gmsgid,
1747 const char *plural_gmsgid,
1748 va_list *ap, diagnostic_t kind)
1750 diagnostic_info diagnostic;
1751 unsigned long gtn;
1753 if (sizeof n <= sizeof gtn)
1754 gtn = n;
1755 else
1756 /* Use the largest number ngettext can handle, otherwise
1757 preserve the six least significant decimal digits for
1758 languages where the plural form depends on them. */
1759 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1761 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1762 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1763 if (kind == DK_WARNING)
1764 diagnostic.option_index = opt;
1765 diagnostic.metadata = metadata;
1766 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1769 /* Wrapper around diagnostic_impl taking a variable argument list. */
1771 bool
1772 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1773 const char *gmsgid, ...)
1775 auto_diagnostic_group d;
1776 va_list ap;
1777 va_start (ap, gmsgid);
1778 rich_location richloc (line_table, location);
1779 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1780 va_end (ap);
1781 return ret;
1784 /* As above, but for rich_location *. */
1786 bool
1787 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1788 const char *gmsgid, ...)
1790 auto_diagnostic_group d;
1791 va_list ap;
1792 va_start (ap, gmsgid);
1793 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1794 va_end (ap);
1795 return ret;
1798 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1800 bool
1801 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1802 const char *gmsgid, va_list *ap)
1804 rich_location richloc (line_table, location);
1805 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1808 /* An informative note at LOCATION. Use this for additional details on an error
1809 message. */
1810 void
1811 inform (location_t location, const char *gmsgid, ...)
1813 auto_diagnostic_group d;
1814 va_list ap;
1815 va_start (ap, gmsgid);
1816 rich_location richloc (line_table, location);
1817 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1818 va_end (ap);
1821 /* Same as "inform" above, but at RICHLOC. */
1822 void
1823 inform (rich_location *richloc, const char *gmsgid, ...)
1825 gcc_assert (richloc);
1827 auto_diagnostic_group d;
1828 va_list ap;
1829 va_start (ap, gmsgid);
1830 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1831 va_end (ap);
1834 /* An informative note at LOCATION. Use this for additional details on an
1835 error message. */
1836 void
1837 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1838 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1840 va_list ap;
1841 va_start (ap, plural_gmsgid);
1842 auto_diagnostic_group d;
1843 rich_location richloc (line_table, location);
1844 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1845 &ap, DK_NOTE);
1846 va_end (ap);
1849 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1850 to the relevant language specification but is likely to be buggy anyway.
1851 Returns true if the warning was printed, false if it was inhibited. */
1852 bool
1853 warning (int opt, const char *gmsgid, ...)
1855 auto_diagnostic_group d;
1856 va_list ap;
1857 va_start (ap, gmsgid);
1858 rich_location richloc (line_table, input_location);
1859 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1860 va_end (ap);
1861 return ret;
1864 /* A warning at LOCATION. Use this for code which is correct according to the
1865 relevant language specification but is likely to be buggy anyway.
1866 Returns true if the warning was printed, false if it was inhibited. */
1868 bool
1869 warning_at (location_t location, int opt, const char *gmsgid, ...)
1871 auto_diagnostic_group d;
1872 va_list ap;
1873 va_start (ap, gmsgid);
1874 rich_location richloc (line_table, location);
1875 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1876 va_end (ap);
1877 return ret;
1880 /* Same as "warning at" above, but using RICHLOC. */
1882 bool
1883 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1885 gcc_assert (richloc);
1887 auto_diagnostic_group d;
1888 va_list ap;
1889 va_start (ap, gmsgid);
1890 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1891 va_end (ap);
1892 return ret;
1895 /* Same as "warning at" above, but using METADATA. */
1897 bool
1898 warning_meta (rich_location *richloc,
1899 const diagnostic_metadata &metadata,
1900 int opt, const char *gmsgid, ...)
1902 gcc_assert (richloc);
1904 auto_diagnostic_group d;
1905 va_list ap;
1906 va_start (ap, gmsgid);
1907 bool ret
1908 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1909 DK_WARNING);
1910 va_end (ap);
1911 return ret;
1914 /* Same as warning_n plural variant below, but using RICHLOC. */
1916 bool
1917 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1918 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1920 gcc_assert (richloc);
1922 auto_diagnostic_group d;
1923 va_list ap;
1924 va_start (ap, plural_gmsgid);
1925 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1926 singular_gmsgid, plural_gmsgid,
1927 &ap, DK_WARNING);
1928 va_end (ap);
1929 return ret;
1932 /* A warning at LOCATION. Use this for code which is correct according to the
1933 relevant language specification but is likely to be buggy anyway.
1934 Returns true if the warning was printed, false if it was inhibited. */
1936 bool
1937 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1938 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1940 auto_diagnostic_group d;
1941 va_list ap;
1942 va_start (ap, plural_gmsgid);
1943 rich_location richloc (line_table, location);
1944 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1945 singular_gmsgid, plural_gmsgid,
1946 &ap, DK_WARNING);
1947 va_end (ap);
1948 return ret;
1951 /* A "pedantic" warning at LOCATION: issues a warning unless
1952 -pedantic-errors was given on the command line, in which case it
1953 issues an error. Use this for diagnostics required by the relevant
1954 language standard, if you have chosen not to make them errors.
1956 Note that these diagnostics are issued independent of the setting
1957 of the -Wpedantic command-line switch. To get a warning enabled
1958 only with that switch, use either "if (pedantic) pedwarn
1959 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1960 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1962 Returns true if the warning was printed, false if it was inhibited. */
1964 bool
1965 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1967 auto_diagnostic_group d;
1968 va_list ap;
1969 va_start (ap, gmsgid);
1970 rich_location richloc (line_table, location);
1971 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1972 va_end (ap);
1973 return ret;
1976 /* Same as pedwarn above, but using RICHLOC. */
1978 bool
1979 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1981 gcc_assert (richloc);
1983 auto_diagnostic_group d;
1984 va_list ap;
1985 va_start (ap, gmsgid);
1986 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1987 va_end (ap);
1988 return ret;
1991 /* A "permissive" error at LOCATION: issues an error unless
1992 -fpermissive was given on the command line, in which case it issues
1993 a warning. Use this for things that really should be errors but we
1994 want to support legacy code.
1996 Returns true if the warning was printed, false if it was inhibited. */
1998 bool
1999 permerror (location_t location, const char *gmsgid, ...)
2001 auto_diagnostic_group d;
2002 va_list ap;
2003 va_start (ap, gmsgid);
2004 rich_location richloc (line_table, location);
2005 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2006 va_end (ap);
2007 return ret;
2010 /* Same as "permerror" above, but at RICHLOC. */
2012 bool
2013 permerror (rich_location *richloc, const char *gmsgid, ...)
2015 gcc_assert (richloc);
2017 auto_diagnostic_group d;
2018 va_list ap;
2019 va_start (ap, gmsgid);
2020 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2021 va_end (ap);
2022 return ret;
2025 /* Similar to the above, but controlled by a flag other than -fpermissive.
2026 As above, an error by default or a warning with -fpermissive, but this
2027 diagnostic can also be downgraded by -Wno-error=opt. */
2029 bool
2030 permerror_opt (location_t location, int opt, const char *gmsgid, ...)
2032 auto_diagnostic_group d;
2033 va_list ap;
2034 va_start (ap, gmsgid);
2035 rich_location richloc (line_table, location);
2036 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2037 va_end (ap);
2038 return ret;
2041 /* Same as "permerror" above, but at RICHLOC. */
2043 bool
2044 permerror_opt (rich_location *richloc, int opt, const char *gmsgid, ...)
2046 gcc_assert (richloc);
2048 auto_diagnostic_group d;
2049 va_list ap;
2050 va_start (ap, gmsgid);
2051 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PERMERROR);
2052 va_end (ap);
2053 return ret;
2056 /* A hard error: the code is definitely ill-formed, and an object file
2057 will not be produced. */
2058 void
2059 error (const char *gmsgid, ...)
2061 auto_diagnostic_group d;
2062 va_list ap;
2063 va_start (ap, gmsgid);
2064 rich_location richloc (line_table, input_location);
2065 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2066 va_end (ap);
2069 /* A hard error: the code is definitely ill-formed, and an object file
2070 will not be produced. */
2071 void
2072 error_n (location_t location, unsigned HOST_WIDE_INT n,
2073 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2075 auto_diagnostic_group d;
2076 va_list ap;
2077 va_start (ap, plural_gmsgid);
2078 rich_location richloc (line_table, location);
2079 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2080 &ap, DK_ERROR);
2081 va_end (ap);
2084 /* Same as above, but use location LOC instead of input_location. */
2085 void
2086 error_at (location_t loc, const char *gmsgid, ...)
2088 auto_diagnostic_group d;
2089 va_list ap;
2090 va_start (ap, gmsgid);
2091 rich_location richloc (line_table, loc);
2092 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2093 va_end (ap);
2096 /* Same as above, but use RICH_LOC. */
2098 void
2099 error_at (rich_location *richloc, const char *gmsgid, ...)
2101 gcc_assert (richloc);
2103 auto_diagnostic_group d;
2104 va_list ap;
2105 va_start (ap, gmsgid);
2106 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2107 va_end (ap);
2110 /* Same as above, but with metadata. */
2112 void
2113 error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
2114 const char *gmsgid, ...)
2116 gcc_assert (richloc);
2118 auto_diagnostic_group d;
2119 va_list ap;
2120 va_start (ap, gmsgid);
2121 diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
2122 va_end (ap);
2125 /* "Sorry, not implemented." Use for a language feature which is
2126 required by the relevant specification but not implemented by GCC.
2127 An object file will not be produced. */
2128 void
2129 sorry (const char *gmsgid, ...)
2131 auto_diagnostic_group d;
2132 va_list ap;
2133 va_start (ap, gmsgid);
2134 rich_location richloc (line_table, input_location);
2135 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2136 va_end (ap);
2139 /* Same as above, but use location LOC instead of input_location. */
2140 void
2141 sorry_at (location_t loc, const char *gmsgid, ...)
2143 auto_diagnostic_group d;
2144 va_list ap;
2145 va_start (ap, gmsgid);
2146 rich_location richloc (line_table, loc);
2147 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2148 va_end (ap);
2151 /* Return true if an error or a "sorry" has been seen. Various
2152 processing is disabled after errors. */
2153 bool
2154 seen_error (void)
2156 return errorcount || sorrycount;
2159 /* An error which is severe enough that we make no attempt to
2160 continue. Do not use this for internal consistency checks; that's
2161 internal_error. Use of this function should be rare. */
2162 void
2163 fatal_error (location_t loc, const char *gmsgid, ...)
2165 auto_diagnostic_group d;
2166 va_list ap;
2167 va_start (ap, gmsgid);
2168 rich_location richloc (line_table, loc);
2169 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2170 va_end (ap);
2172 gcc_unreachable ();
2175 /* An internal consistency check has failed. We make no attempt to
2176 continue. */
2177 void
2178 internal_error (const char *gmsgid, ...)
2180 auto_diagnostic_group d;
2181 va_list ap;
2182 va_start (ap, gmsgid);
2183 rich_location richloc (line_table, input_location);
2184 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2185 va_end (ap);
2187 gcc_unreachable ();
2190 /* Like internal_error, but no backtrace will be printed. Used when
2191 the internal error does not happen at the current location, but happened
2192 somewhere else. */
2193 void
2194 internal_error_no_backtrace (const char *gmsgid, ...)
2196 auto_diagnostic_group d;
2197 va_list ap;
2198 va_start (ap, gmsgid);
2199 rich_location richloc (line_table, input_location);
2200 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2201 va_end (ap);
2203 gcc_unreachable ();
2206 /* Emit DIAGRAM to CONTEXT, respecting the output format. */
2208 void
2209 diagnostic_emit_diagram (diagnostic_context *context,
2210 const diagnostic_diagram &diagram)
2212 if (context->m_diagrams.m_theme == nullptr)
2213 return;
2215 gcc_assert (context->m_output_format);
2216 context->m_output_format->on_diagram (diagram);
2219 /* Special case error functions. Most are implemented in terms of the
2220 above, or should be. */
2222 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2223 runs its second argument through gettext. */
2224 void
2225 fnotice (FILE *file, const char *cmsgid, ...)
2227 va_list ap;
2229 va_start (ap, cmsgid);
2230 vfprintf (file, _(cmsgid), ap);
2231 va_end (ap);
2234 /* Inform the user that an error occurred while trying to report some
2235 other error. This indicates catastrophic internal inconsistencies,
2236 so give up now. But do try to flush out the previous error.
2237 This mustn't use internal_error, that will cause infinite recursion. */
2239 static void
2240 error_recursion (diagnostic_context *context)
2242 if (context->lock < 3)
2243 pp_newline_and_flush (context->printer);
2245 fnotice (stderr,
2246 "internal compiler error: error reporting routines re-entered.\n");
2248 /* Call diagnostic_action_after_output to get the "please submit a bug
2249 report" message. */
2250 diagnostic_action_after_output (context, DK_ICE);
2252 /* Do not use gcc_unreachable here; that goes through internal_error
2253 and therefore would cause infinite recursion. */
2254 real_abort ();
2257 /* Report an internal compiler error in a friendly manner. This is
2258 the function that gets called upon use of abort() in the source
2259 code generally, thanks to a special macro. */
2261 void
2262 fancy_abort (const char *file, int line, const char *function)
2264 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2265 internal_error will crash internally in a way that prevents a
2266 useful message reaching the user.
2267 This can happen with libgccjit in the case of gcc_assert failures
2268 that occur outside of the libgccjit mutex that guards the rest of
2269 gcc's state, including global_dc (when global_dc may not be
2270 initialized yet, or might be in use by another thread).
2271 Handle such cases as gracefully as possible by falling back to a
2272 minimal abort handler that only relies on i18n. */
2273 if (global_dc->printer == NULL)
2275 /* Print the error message. */
2276 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2277 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2278 fputc ('\n', stderr);
2280 /* Attempt to print a backtrace. */
2281 struct backtrace_state *state
2282 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2283 int count = 0;
2284 if (state != NULL)
2285 backtrace_full (state, 2, bt_callback, bt_err_callback,
2286 (void *) &count);
2288 /* We can't call warn_if_plugins or emergency_dump_function as these
2289 rely on GCC state that might not be initialized, or might be in
2290 use by another thread. */
2292 /* Abort the process. */
2293 real_abort ();
2296 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2299 /* class auto_diagnostic_group. */
2301 /* Constructor: "push" this group into global_dc. */
2303 auto_diagnostic_group::auto_diagnostic_group ()
2305 global_dc->diagnostic_group_nesting_depth++;
2308 /* Destructor: "pop" this group from global_dc. */
2310 auto_diagnostic_group::~auto_diagnostic_group ()
2312 if (--global_dc->diagnostic_group_nesting_depth == 0)
2314 /* Handle the case where we've popped the final diagnostic group.
2315 If any diagnostics were emitted, give the context a chance
2316 to do something. */
2317 if (global_dc->diagnostic_group_emission_count > 0)
2318 global_dc->m_output_format->on_end_group ();
2319 global_dc->diagnostic_group_emission_count = 0;
2323 /* class diagnostic_text_output_format : public diagnostic_output_format. */
2325 diagnostic_text_output_format::~diagnostic_text_output_format ()
2327 /* Some of the errors may actually have been warnings. */
2328 if (diagnostic_kind_count (&m_context, DK_WERROR))
2330 /* -Werror was given. */
2331 if (m_context.warning_as_error_requested)
2332 pp_verbatim (m_context.printer,
2333 _("%s: all warnings being treated as errors"),
2334 progname);
2335 /* At least one -Werror= was given. */
2336 else
2337 pp_verbatim (m_context.printer,
2338 _("%s: some warnings being treated as errors"),
2339 progname);
2340 pp_newline_and_flush (m_context.printer);
2344 void
2345 diagnostic_text_output_format::on_begin_diagnostic (diagnostic_info *diagnostic)
2347 (*diagnostic_starter (&m_context)) (&m_context, diagnostic);
2350 void
2351 diagnostic_text_output_format::on_end_diagnostic (diagnostic_info *diagnostic,
2352 diagnostic_t orig_diag_kind)
2354 (*diagnostic_finalizer (&m_context)) (&m_context, diagnostic, orig_diag_kind);
2357 void
2358 diagnostic_text_output_format::on_diagram (const diagnostic_diagram &diagram)
2360 char *saved_prefix = pp_take_prefix (m_context.printer);
2361 pp_set_prefix (m_context.printer, NULL);
2362 /* Use a newline before and after and a two-space indent
2363 to make the diagram stand out a little from the wall of text. */
2364 pp_newline (m_context.printer);
2365 diagram.get_canvas ().print_to_pp (m_context.printer, " ");
2366 pp_newline (m_context.printer);
2367 pp_set_prefix (m_context.printer, saved_prefix);
2368 pp_flush (m_context.printer);
2371 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2372 file-based output formats. */
2374 void
2375 diagnostic_output_format_init (diagnostic_context *context,
2376 const char *base_file_name,
2377 enum diagnostics_output_format format)
2379 switch (format)
2381 default:
2382 gcc_unreachable ();
2383 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2384 /* The default; do nothing. */
2385 break;
2387 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2388 diagnostic_output_format_init_json_stderr (context);
2389 break;
2391 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2392 diagnostic_output_format_init_json_file (context, base_file_name);
2393 break;
2395 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2396 diagnostic_output_format_init_sarif_stderr (context);
2397 break;
2399 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2400 diagnostic_output_format_init_sarif_file (context, base_file_name);
2401 break;
2405 /* Initialize CONTEXT->m_diagrams based on CHARSET.
2406 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2407 (or NULL for "no diagrams"). */
2409 void
2410 diagnostics_text_art_charset_init (diagnostic_context *context,
2411 enum diagnostic_text_art_charset charset)
2413 delete context->m_diagrams.m_theme;
2414 switch (charset)
2416 default:
2417 gcc_unreachable ();
2419 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
2420 context->m_diagrams.m_theme = NULL;
2421 break;
2423 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
2424 context->m_diagrams.m_theme = new text_art::ascii_theme ();
2425 break;
2427 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
2428 context->m_diagrams.m_theme = new text_art::unicode_theme ();
2429 break;
2431 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
2432 context->m_diagrams.m_theme = new text_art::emoji_theme ();
2433 break;
2437 /* class simple_diagnostic_path : public diagnostic_path. */
2439 simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
2440 : m_event_pp (event_pp)
2442 add_thread ("main");
2445 /* Implementation of diagnostic_path::num_events vfunc for
2446 simple_diagnostic_path: simply get the number of events in the vec. */
2448 unsigned
2449 simple_diagnostic_path::num_events () const
2451 return m_events.length ();
2454 /* Implementation of diagnostic_path::get_event vfunc for
2455 simple_diagnostic_path: simply return the event in the vec. */
2457 const diagnostic_event &
2458 simple_diagnostic_path::get_event (int idx) const
2460 return *m_events[idx];
2463 unsigned
2464 simple_diagnostic_path::num_threads () const
2466 return m_threads.length ();
2469 const diagnostic_thread &
2470 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
2472 return *m_threads[idx];
2475 diagnostic_thread_id_t
2476 simple_diagnostic_path::add_thread (const char *name)
2478 m_threads.safe_push (new simple_diagnostic_thread (name));
2479 return m_threads.length () - 1;
2482 /* Add an event to this path at LOC within function FNDECL at
2483 stack depth DEPTH.
2485 Use m_context's printer to format FMT, as the text of the new
2486 event.
2488 Return the id of the new event. */
2490 diagnostic_event_id_t
2491 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2492 const char *fmt, ...)
2494 pretty_printer *pp = m_event_pp;
2495 pp_clear_output_area (pp);
2497 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2499 va_list ap;
2501 va_start (ap, fmt);
2503 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2504 pp_format (pp, &ti);
2505 pp_output_formatted_text (pp);
2507 va_end (ap);
2509 simple_diagnostic_event *new_event
2510 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2511 m_events.safe_push (new_event);
2513 pp_clear_output_area (pp);
2515 return diagnostic_event_id_t (m_events.length () - 1);
2518 diagnostic_event_id_t
2519 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
2520 location_t loc,
2521 tree fndecl,
2522 int depth,
2523 const char *fmt, ...)
2525 pretty_printer *pp = m_event_pp;
2526 pp_clear_output_area (pp);
2528 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2530 va_list ap;
2532 va_start (ap, fmt);
2534 text_info ti (_(fmt), &ap, 0, nullptr, &rich_loc);
2536 pp_format (pp, &ti);
2537 pp_output_formatted_text (pp);
2539 va_end (ap);
2541 simple_diagnostic_event *new_event
2542 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
2543 thread_id);
2544 m_events.safe_push (new_event);
2546 pp_clear_output_area (pp);
2548 return diagnostic_event_id_t (m_events.length () - 1);
2551 /* struct simple_diagnostic_event. */
2553 /* simple_diagnostic_event's ctor. */
2555 simple_diagnostic_event::
2556 simple_diagnostic_event (location_t loc,
2557 tree fndecl,
2558 int depth,
2559 const char *desc,
2560 diagnostic_thread_id_t thread_id)
2561 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
2562 m_thread_id (thread_id)
2566 /* simple_diagnostic_event's dtor. */
2568 simple_diagnostic_event::~simple_diagnostic_event ()
2570 free (m_desc);
2573 /* Print PATH by emitting a dummy "note" associated with it. */
2575 DEBUG_FUNCTION
2576 void debug (diagnostic_path *path)
2578 rich_location richloc (line_table, UNKNOWN_LOCATION);
2579 richloc.set_path (path);
2580 inform (&richloc, "debug path");
2583 /* Really call the system 'abort'. This has to go right at the end of
2584 this file, so that there are no functions after it that call abort
2585 and get the system abort instead of our macro. */
2586 #undef abort
2587 static void
2588 real_abort (void)
2590 abort ();
2593 #if CHECKING_P
2595 namespace selftest {
2597 /* Helper function for test_print_escaped_string. */
2599 static void
2600 assert_print_escaped_string (const location &loc, const char *expected_output,
2601 const char *input)
2603 pretty_printer pp;
2604 print_escaped_string (&pp, input);
2605 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2608 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2609 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2611 /* Tests of print_escaped_string. */
2613 static void
2614 test_print_escaped_string ()
2616 /* Empty string. */
2617 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2619 /* Non-empty string. */
2620 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2622 /* Various things that need to be escaped: */
2623 /* Backslash. */
2624 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2625 "before\\after");
2626 /* Tab. */
2627 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2628 "before\tafter");
2629 /* Newline. */
2630 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2631 "before\nafter");
2632 /* Double quote. */
2633 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2634 "before\"after");
2636 /* Non-printable characters: BEL: '\a': 0x07 */
2637 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2638 "before\aafter");
2639 /* Non-printable characters: vertical tab: '\v': 0x0b */
2640 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2641 "before\vafter");
2644 /* Tests of print_parseable_fixits. */
2646 /* Verify that print_parseable_fixits emits the empty string if there
2647 are no fixits. */
2649 static void
2650 test_print_parseable_fixits_none ()
2652 pretty_printer pp;
2653 rich_location richloc (line_table, UNKNOWN_LOCATION);
2655 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2656 ASSERT_STREQ ("", pp_formatted_text (&pp));
2659 /* Verify that print_parseable_fixits does the right thing if there
2660 is an insertion fixit hint. */
2662 static void
2663 test_print_parseable_fixits_insert ()
2665 pretty_printer pp;
2666 rich_location richloc (line_table, UNKNOWN_LOCATION);
2668 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2669 linemap_line_start (line_table, 5, 100);
2670 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2671 location_t where = linemap_position_for_column (line_table, 10);
2672 richloc.add_fixit_insert_before (where, "added content");
2674 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2675 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2676 pp_formatted_text (&pp));
2679 /* Verify that print_parseable_fixits does the right thing if there
2680 is an removal fixit hint. */
2682 static void
2683 test_print_parseable_fixits_remove ()
2685 pretty_printer pp;
2686 rich_location richloc (line_table, UNKNOWN_LOCATION);
2688 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2689 linemap_line_start (line_table, 5, 100);
2690 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2691 source_range where;
2692 where.m_start = linemap_position_for_column (line_table, 10);
2693 where.m_finish = linemap_position_for_column (line_table, 20);
2694 richloc.add_fixit_remove (where);
2696 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2697 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2698 pp_formatted_text (&pp));
2701 /* Verify that print_parseable_fixits does the right thing if there
2702 is an replacement fixit hint. */
2704 static void
2705 test_print_parseable_fixits_replace ()
2707 pretty_printer pp;
2708 rich_location richloc (line_table, UNKNOWN_LOCATION);
2710 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2711 linemap_line_start (line_table, 5, 100);
2712 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2713 source_range where;
2714 where.m_start = linemap_position_for_column (line_table, 10);
2715 where.m_finish = linemap_position_for_column (line_table, 20);
2716 richloc.add_fixit_replace (where, "replacement");
2718 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2719 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2720 pp_formatted_text (&pp));
2723 /* Verify that print_parseable_fixits correctly handles
2724 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2726 static void
2727 test_print_parseable_fixits_bytes_vs_display_columns ()
2729 line_table_test ltt;
2730 rich_location richloc (line_table, UNKNOWN_LOCATION);
2732 /* 1-based byte offsets: 12345677778888999900001234567. */
2733 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2734 /* 1-based display cols: 123456[......7-8.....]9012345. */
2735 const int tabstop = 8;
2737 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2738 const char *const fname = tmp.get_filename ();
2740 linemap_add (line_table, LC_ENTER, false, fname, 0);
2741 linemap_line_start (line_table, 1, 100);
2742 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2743 source_range where;
2744 where.m_start = linemap_position_for_column (line_table, 12);
2745 where.m_finish = linemap_position_for_column (line_table, 17);
2746 richloc.add_fixit_replace (where, "color");
2748 /* Escape fname. */
2749 pretty_printer tmp_pp;
2750 print_escaped_string (&tmp_pp, fname);
2751 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2753 const int buf_len = strlen (escaped_fname) + 100;
2754 char *const expected = XNEWVEC (char, buf_len);
2757 pretty_printer pp;
2758 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2759 tabstop);
2760 snprintf (expected, buf_len,
2761 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2762 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2765 pretty_printer pp;
2766 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2767 tabstop);
2768 snprintf (expected, buf_len,
2769 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2770 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2773 XDELETEVEC (expected);
2774 free (escaped_fname);
2777 /* Verify that
2778 diagnostic_get_location_text (..., SHOW_COLUMN)
2779 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2780 colorization disabled. */
2782 static void
2783 assert_location_text (const char *expected_loc_text,
2784 const char *filename, int line, int column,
2785 bool show_column,
2786 int origin = 1,
2787 enum diagnostics_column_unit column_unit
2788 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2790 test_diagnostic_context dc;
2791 dc.show_column = show_column;
2792 dc.column_unit = column_unit;
2793 dc.column_origin = origin;
2795 expanded_location xloc;
2796 xloc.file = filename;
2797 xloc.line = line;
2798 xloc.column = column;
2799 xloc.data = NULL;
2800 xloc.sysp = false;
2802 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2803 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2804 free (actual_loc_text);
2807 /* Verify that diagnostic_get_location_text works as expected. */
2809 static void
2810 test_diagnostic_get_location_text ()
2812 const char *old_progname = progname;
2813 progname = "PROGNAME";
2814 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2815 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2816 assert_location_text (built_in_colon, special_fname_builtin (),
2817 42, 10, true);
2818 free (built_in_colon);
2819 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2820 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2821 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2822 for (int origin = 0; origin != 2; ++origin)
2823 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2824 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2825 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2826 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2828 maybe_line_and_column (INT_MAX, INT_MAX);
2829 maybe_line_and_column (INT_MIN, INT_MIN);
2832 /* In order to test display columns vs byte columns, we need to create a
2833 file for location_get_source_line() to read. */
2835 const char *const content = "smile \xf0\x9f\x98\x82\n";
2836 const int line_bytes = strlen (content) - 1;
2837 const int def_tabstop = 8;
2838 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2839 const int display_width = cpp_display_width (content, line_bytes, policy);
2840 ASSERT_EQ (line_bytes - 2, display_width);
2841 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2842 const char *const fname = tmp.get_filename ();
2843 const int buf_len = strlen (fname) + 16;
2844 char *const expected = XNEWVEC (char, buf_len);
2846 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2847 assert_location_text (expected, fname, 1, line_bytes, true,
2848 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2850 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2851 assert_location_text (expected, fname, 1, line_bytes, true,
2852 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2854 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2855 assert_location_text (expected, fname, 1, line_bytes, true,
2856 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2858 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2859 assert_location_text (expected, fname, 1, line_bytes, true,
2860 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2862 XDELETEVEC (expected);
2866 progname = old_progname;
2869 /* Selftest for num_digits. */
2871 static void
2872 test_num_digits ()
2874 ASSERT_EQ (1, num_digits (0));
2875 ASSERT_EQ (1, num_digits (9));
2876 ASSERT_EQ (2, num_digits (10));
2877 ASSERT_EQ (2, num_digits (99));
2878 ASSERT_EQ (3, num_digits (100));
2879 ASSERT_EQ (3, num_digits (999));
2880 ASSERT_EQ (4, num_digits (1000));
2881 ASSERT_EQ (4, num_digits (9999));
2882 ASSERT_EQ (5, num_digits (10000));
2883 ASSERT_EQ (5, num_digits (99999));
2884 ASSERT_EQ (6, num_digits (100000));
2885 ASSERT_EQ (6, num_digits (999999));
2886 ASSERT_EQ (7, num_digits (1000000));
2887 ASSERT_EQ (7, num_digits (9999999));
2888 ASSERT_EQ (8, num_digits (10000000));
2889 ASSERT_EQ (8, num_digits (99999999));
2892 /* Run all of the selftests within this file. */
2894 void
2895 c_diagnostic_cc_tests ()
2897 test_print_escaped_string ();
2898 test_print_parseable_fixits_none ();
2899 test_print_parseable_fixits_insert ();
2900 test_print_parseable_fixits_remove ();
2901 test_print_parseable_fixits_replace ();
2902 test_print_parseable_fixits_bytes_vs_display_columns ();
2903 test_diagnostic_get_location_text ();
2904 test_num_digits ();
2908 } // namespace selftest
2910 #endif /* #if CHECKING_P */
2912 #if __GNUC__ >= 10
2913 # pragma GCC diagnostic pop
2914 #endif