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