Suppress -fstack-protector warning on hppa.
[official-gcc.git] / gcc / diagnostic.cc
blob322515b32428ab19f28cff6513707d93ae6420ba
1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2022 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->includes_seen = NULL;
245 context->m_client_data_hooks = NULL;
248 /* Maybe initialize the color support. We require clients to do this
249 explicitly, since most clients don't want color. When called
250 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
252 void
253 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
255 /* value == -1 is the default value. */
256 if (value < 0)
258 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
259 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
260 otherwise default to -fdiagnostics-color=never, for other
261 values default to that
262 -fdiagnostics-color={never,auto,always}. */
263 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
265 if (!getenv ("GCC_COLORS"))
266 return;
267 value = DIAGNOSTICS_COLOR_AUTO;
269 else
270 value = DIAGNOSTICS_COLOR_DEFAULT;
272 pp_show_color (context->printer)
273 = colorize_init ((diagnostic_color_rule_t) value);
276 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
278 void
279 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
281 /* value == -1 is the default value. */
282 if (value < 0)
284 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
285 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
286 environment, otherwise default to -fdiagnostics-urls=never,
287 for other values default to that
288 -fdiagnostics-urls={never,auto,always}. */
289 if (DIAGNOSTICS_URLS_DEFAULT == -1)
291 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
292 return;
293 value = DIAGNOSTICS_URL_AUTO;
295 else
296 value = DIAGNOSTICS_URLS_DEFAULT;
299 context->printer->url_format
300 = determine_url_format ((diagnostic_url_rule_t) value);
303 /* Create the file_cache, if not already created, and tell it how to
304 translate files on input. */
305 void diagnostic_initialize_input_context (diagnostic_context *context,
306 diagnostic_input_charset_callback ccb,
307 bool should_skip_bom)
309 if (!context->m_file_cache)
310 context->m_file_cache = new file_cache;
311 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
314 /* Do any cleaning up required after the last diagnostic is emitted. */
316 void
317 diagnostic_finish (diagnostic_context *context)
319 if (context->final_cb)
320 context->final_cb (context);
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.err_no = errno;
361 diagnostic->message.args_ptr = args;
362 diagnostic->message.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 struct backtrace_state *state = NULL;
669 if (diag_kind == DK_ICE)
670 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
671 int count = 0;
672 if (state != NULL)
673 backtrace_full (state, 2, bt_callback, bt_err_callback,
674 (void *) &count);
676 if (context->abort_on_error)
677 real_abort ();
679 if (context->report_bug)
680 fnotice (stderr, "Please submit a full bug report, "
681 "with preprocessed source.\n");
682 else
683 fnotice (stderr, "Please submit a full bug report, "
684 "with preprocessed source (by using -freport-bug).\n");
686 if (count > 0)
687 fnotice (stderr, "Please include the complete backtrace "
688 "with any bug report.\n");
689 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
691 exit (ICE_EXIT_CODE);
694 case DK_FATAL:
695 if (context->abort_on_error)
696 real_abort ();
697 diagnostic_finish (context);
698 fnotice (stderr, "compilation terminated.\n");
699 exit (FATAL_EXIT_CODE);
701 default:
702 gcc_unreachable ();
706 /* True if the last module or file in which a diagnostic was reported is
707 different from the current one. */
709 static bool
710 last_module_changed_p (diagnostic_context *context,
711 const line_map_ordinary *map)
713 return context->last_module != map;
716 /* Remember the current module or file as being the last one in which we
717 report a diagnostic. */
719 static void
720 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
722 context->last_module = map;
725 /* Only dump the "In file included from..." stack once for each file. */
727 static bool
728 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
730 /* No include path for main. */
731 if (MAIN_FILE_P (map))
732 return true;
734 /* Always identify C++ modules, at least for now. */
735 auto probe = map;
736 if (linemap_check_ordinary (map)->reason == LC_RENAME)
737 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
738 probe = linemap_included_from_linemap (line_table, map);
739 if (MAP_MODULE_P (probe))
740 return false;
742 if (!context->includes_seen)
743 context->includes_seen = new hash_set<location_t, false, location_hash>;
745 /* Hash the location of the #include directive to better handle files
746 that are included multiple times with different macros defined. */
747 return context->includes_seen->add (linemap_included_from (map));
750 void
751 diagnostic_report_current_module (diagnostic_context *context, location_t where)
753 const line_map_ordinary *map = NULL;
755 if (pp_needs_newline (context->printer))
757 pp_newline (context->printer);
758 pp_needs_newline (context->printer) = false;
761 if (where <= BUILTINS_LOCATION)
762 return;
764 linemap_resolve_location (line_table, where,
765 LRK_MACRO_DEFINITION_LOCATION,
766 &map);
768 if (map && last_module_changed_p (context, map))
770 set_last_module (context, map);
771 if (!includes_seen (context, map))
773 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
774 expanded_location s = {};
777 where = linemap_included_from (map);
778 map = linemap_included_from_linemap (line_table, map);
779 bool is_module = MAP_MODULE_P (map);
780 s.file = LINEMAP_FILE (map);
781 s.line = SOURCE_LINE (map, where);
782 int col = -1;
783 if (first && context->show_column)
785 s.column = SOURCE_COLUMN (map, where);
786 col = diagnostic_converted_column (context, s);
788 const char *line_col = maybe_line_and_column (s.line, col);
789 static const char *const msgs[] =
791 NULL,
792 N_(" from"),
793 N_("In file included from"), /* 2 */
794 N_(" included from"),
795 N_("In module"), /* 4 */
796 N_("of module"),
797 N_("In module imported at"), /* 6 */
798 N_("imported at"),
801 unsigned index = (was_module ? 6 : is_module ? 4
802 : need_inc ? 2 : 0) + !first;
804 pp_verbatim (context->printer, "%s%s %r%s%s%R",
805 first ? "" : was_module ? ", " : ",\n",
806 _(msgs[index]),
807 "locus", s.file, line_col);
808 first = false, need_inc = was_module, was_module = is_module;
810 while (!includes_seen (context, map));
811 pp_verbatim (context->printer, ":");
812 pp_newline (context->printer);
817 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
818 print the path. */
820 void
821 diagnostic_show_any_path (diagnostic_context *context,
822 diagnostic_info *diagnostic)
824 const diagnostic_path *path = diagnostic->richloc->get_path ();
825 if (!path)
826 return;
828 if (context->print_path)
829 context->print_path (context, path);
832 /* class diagnostic_event. */
834 /* struct diagnostic_event::meaning. */
836 void
837 diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
839 bool need_comma = false;
840 pp_character (pp, '{');
841 if (const char *verb_str = maybe_get_verb_str (m_verb))
843 pp_printf (pp, "verb: %qs", verb_str);
844 need_comma = true;
846 if (const char *noun_str = maybe_get_noun_str (m_noun))
848 if (need_comma)
849 pp_string (pp, ", ");
850 pp_printf (pp, "noun: %qs", noun_str);
851 need_comma = true;
853 if (const char *property_str = maybe_get_property_str (m_property))
855 if (need_comma)
856 pp_string (pp, ", ");
857 pp_printf (pp, "property: %qs", property_str);
858 need_comma = true;
860 pp_character (pp, '}');
863 /* Get a string (or NULL) for V suitable for use within a SARIF
864 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
866 const char *
867 diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
869 switch (v)
871 default:
872 gcc_unreachable ();
873 case VERB_unknown:
874 return NULL;
875 case VERB_acquire:
876 return "acquire";
877 case VERB_release:
878 return "release";
879 case VERB_enter:
880 return "enter";
881 case VERB_exit:
882 return "exit";
883 case VERB_call:
884 return "call";
885 case VERB_return:
886 return "return";
887 case VERB_branch:
888 return "branch";
889 case VERB_danger:
890 return "danger";
894 /* Get a string (or NULL) for N suitable for use within a SARIF
895 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
897 const char *
898 diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
900 switch (n)
902 default:
903 gcc_unreachable ();
904 case NOUN_unknown:
905 return NULL;
906 case NOUN_taint:
907 return "taint";
908 case NOUN_sensitive:
909 return "sensitive";
910 case NOUN_function:
911 return "function";
912 case NOUN_lock:
913 return "lock";
914 case NOUN_memory:
915 return "memory";
916 case NOUN_resource:
917 return "resource";
921 /* Get a string (or NULL) for P suitable for use within a SARIF
922 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
924 const char *
925 diagnostic_event::meaning::maybe_get_property_str (enum property p)
927 switch (p)
929 default:
930 gcc_unreachable ();
931 case PROPERTY_unknown:
932 return NULL;
933 case PROPERTY_true:
934 return "true";
935 case PROPERTY_false:
936 return "false";
940 /* class diagnostic_path. */
942 /* Subroutint of diagnostic_path::interprocedural_p.
943 Look for the first event in this path that is within a function
944 i.e. has a non-NULL fndecl, and a non-zero stack depth.
945 If found, write its index to *OUT_IDX and return true.
946 Otherwise return false. */
948 bool
949 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
951 const unsigned num = num_events ();
952 for (unsigned i = 0; i < num; i++)
954 if (!(get_event (i).get_fndecl () == NULL
955 && get_event (i).get_stack_depth () == 0))
957 *out_idx = i;
958 return true;
961 return false;
964 /* Return true if the events in this path involve more than one
965 function, or false if it is purely intraprocedural. */
967 bool
968 diagnostic_path::interprocedural_p () const
970 /* Ignore leading events that are outside of any function. */
971 unsigned first_fn_event_idx;
972 if (!get_first_event_in_a_function (&first_fn_event_idx))
973 return false;
975 const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
976 tree first_fndecl = first_fn_event.get_fndecl ();
977 int first_fn_stack_depth = first_fn_event.get_stack_depth ();
979 const unsigned num = num_events ();
980 for (unsigned i = first_fn_event_idx + 1; i < num; i++)
982 if (get_event (i).get_fndecl () != first_fndecl)
983 return true;
984 if (get_event (i).get_stack_depth () != first_fn_stack_depth)
985 return true;
987 return false;
990 void
991 default_diagnostic_starter (diagnostic_context *context,
992 diagnostic_info *diagnostic)
994 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
995 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
996 diagnostic));
999 void
1000 default_diagnostic_start_span_fn (diagnostic_context *context,
1001 expanded_location exploc)
1003 char *text = diagnostic_get_location_text (context, exploc);
1004 pp_string (context->printer, text);
1005 free (text);
1006 pp_newline (context->printer);
1009 void
1010 default_diagnostic_finalizer (diagnostic_context *context,
1011 diagnostic_info *diagnostic,
1012 diagnostic_t)
1014 char *saved_prefix = pp_take_prefix (context->printer);
1015 pp_set_prefix (context->printer, NULL);
1016 pp_newline (context->printer);
1017 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
1018 pp_set_prefix (context->printer, saved_prefix);
1019 pp_flush (context->printer);
1022 /* Interface to specify diagnostic kind overrides. Returns the
1023 previous setting, or DK_UNSPECIFIED if the parameters are out of
1024 range. If OPTION_INDEX is zero, the new setting is for all the
1025 diagnostics. */
1026 diagnostic_t
1027 diagnostic_classify_diagnostic (diagnostic_context *context,
1028 int option_index,
1029 diagnostic_t new_kind,
1030 location_t where)
1032 diagnostic_t old_kind;
1034 if (option_index < 0
1035 || option_index >= context->n_opts
1036 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1037 return DK_UNSPECIFIED;
1039 old_kind = context->classify_diagnostic[option_index];
1041 /* Handle pragmas separately, since we need to keep track of *where*
1042 the pragmas were. */
1043 if (where != UNKNOWN_LOCATION)
1045 int i;
1047 /* Record the command-line status, so we can reset it back on DK_POP. */
1048 if (old_kind == DK_UNSPECIFIED)
1050 old_kind = !context->option_enabled (option_index,
1051 context->lang_mask,
1052 context->option_state)
1053 ? DK_IGNORED : (context->warning_as_error_requested
1054 ? DK_ERROR : DK_WARNING);
1055 context->classify_diagnostic[option_index] = old_kind;
1058 for (i = context->n_classification_history - 1; i >= 0; i --)
1059 if (context->classification_history[i].option == option_index)
1061 old_kind = context->classification_history[i].kind;
1062 break;
1065 i = context->n_classification_history;
1066 context->classification_history =
1067 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1068 * sizeof (diagnostic_classification_change_t));
1069 context->classification_history[i].location = where;
1070 context->classification_history[i].option = option_index;
1071 context->classification_history[i].kind = new_kind;
1072 context->n_classification_history ++;
1074 else
1075 context->classify_diagnostic[option_index] = new_kind;
1077 return old_kind;
1080 /* Save all diagnostic classifications in a stack. */
1081 void
1082 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
1084 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
1085 context->push_list[context->n_push ++] = context->n_classification_history;
1088 /* Restore the topmost classification set off the stack. If the stack
1089 is empty, revert to the state based on command line parameters. */
1090 void
1091 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
1093 int jump_to;
1094 int i;
1096 if (context->n_push)
1097 jump_to = context->push_list [-- context->n_push];
1098 else
1099 jump_to = 0;
1101 i = context->n_classification_history;
1102 context->classification_history =
1103 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1104 * sizeof (diagnostic_classification_change_t));
1105 context->classification_history[i].location = where;
1106 context->classification_history[i].option = jump_to;
1107 context->classification_history[i].kind = DK_POP;
1108 context->n_classification_history ++;
1111 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1112 escaping rules for -fdiagnostics-parseable-fixits. */
1114 static void
1115 print_escaped_string (pretty_printer *pp, const char *text)
1117 gcc_assert (pp);
1118 gcc_assert (text);
1120 pp_character (pp, '"');
1121 for (const char *ch = text; *ch; ch++)
1123 switch (*ch)
1125 case '\\':
1126 /* Escape backslash as two backslashes. */
1127 pp_string (pp, "\\\\");
1128 break;
1129 case '\t':
1130 /* Escape tab as "\t". */
1131 pp_string (pp, "\\t");
1132 break;
1133 case '\n':
1134 /* Escape newline as "\n". */
1135 pp_string (pp, "\\n");
1136 break;
1137 case '"':
1138 /* Escape doublequotes as \". */
1139 pp_string (pp, "\\\"");
1140 break;
1141 default:
1142 if (ISPRINT (*ch))
1143 pp_character (pp, *ch);
1144 else
1145 /* Use octal for non-printable chars. */
1147 unsigned char c = (*ch & 0xff);
1148 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1150 break;
1153 pp_character (pp, '"');
1156 /* Implementation of -fdiagnostics-parseable-fixits and
1157 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1158 Print a machine-parseable version of all fixits in RICHLOC to PP,
1159 using COLUMN_UNIT to express columns.
1160 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1162 static void
1163 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1164 enum diagnostics_column_unit column_unit,
1165 int tabstop)
1167 gcc_assert (pp);
1168 gcc_assert (richloc);
1170 char *saved_prefix = pp_take_prefix (pp);
1171 pp_set_prefix (pp, NULL);
1173 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1175 const fixit_hint *hint = richloc->get_fixit_hint (i);
1176 location_t start_loc = hint->get_start_loc ();
1177 expanded_location start_exploc = expand_location (start_loc);
1178 pp_string (pp, "fix-it:");
1179 print_escaped_string (pp, start_exploc.file);
1180 /* For compatibility with clang, print as a half-open range. */
1181 location_t next_loc = hint->get_next_loc ();
1182 expanded_location next_exploc = expand_location (next_loc);
1183 int start_col
1184 = convert_column_unit (column_unit, tabstop, start_exploc);
1185 int next_col
1186 = convert_column_unit (column_unit, tabstop, next_exploc);
1187 pp_printf (pp, ":{%i:%i-%i:%i}:",
1188 start_exploc.line, start_col,
1189 next_exploc.line, next_col);
1190 print_escaped_string (pp, hint->get_string ());
1191 pp_newline (pp);
1194 pp_set_prefix (pp, saved_prefix);
1197 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1199 static void
1200 get_any_inlining_info (diagnostic_context *context,
1201 diagnostic_info *diagnostic)
1203 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1205 if (context->set_locations_cb)
1206 /* Retrieve the locations into which the expression about to be
1207 diagnosed has been inlined, including those of all the callers
1208 all the way down the inlining stack. */
1209 context->set_locations_cb (context, diagnostic);
1210 else
1212 /* When there's no callback use just the one location provided
1213 by the caller of the diagnostic function. */
1214 location_t loc = diagnostic_location (diagnostic);
1215 ilocs.safe_push (loc);
1216 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1220 /* Update the kind of DIAGNOSTIC based on its location(s), including
1221 any of those in its inlining stack, relative to any
1222 #pragma GCC diagnostic
1223 directives recorded within CONTEXT.
1225 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1226 otherwise. */
1228 static diagnostic_t
1229 update_effective_level_from_pragmas (diagnostic_context *context,
1230 diagnostic_info *diagnostic)
1232 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1234 /* Ignore the diagnostic if all the inlined locations are
1235 in system headers and -Wno-system-headers is in effect. */
1236 diagnostic->kind = DK_IGNORED;
1237 return DK_IGNORED;
1240 if (context->n_classification_history <= 0)
1241 return DK_UNSPECIFIED;
1243 /* Iterate over the locations, checking the diagnostic disposition
1244 for the diagnostic at each. If it's explicitly set as opposed
1245 to unspecified, update the disposition for this instance of
1246 the diagnostic and return it. */
1247 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1249 /* FIXME: Stupid search. Optimize later. */
1250 for (int i = context->n_classification_history - 1; i >= 0; i --)
1252 const diagnostic_classification_change_t &hist
1253 = context->classification_history[i];
1255 location_t pragloc = hist.location;
1256 if (!linemap_location_before_p (line_table, pragloc, loc))
1257 continue;
1259 if (hist.kind == (int) DK_POP)
1261 /* Move on to the next region. */
1262 i = hist.option;
1263 continue;
1266 int option = hist.option;
1267 /* The option 0 is for all the diagnostics. */
1268 if (option == 0 || option == diagnostic->option_index)
1270 diagnostic_t kind = hist.kind;
1271 if (kind != DK_UNSPECIFIED)
1272 diagnostic->kind = kind;
1273 return kind;
1278 return DK_UNSPECIFIED;
1281 /* Generate a URL string describing CWE. The caller is responsible for
1282 freeing the string. */
1284 char *
1285 get_cwe_url (int cwe)
1287 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1290 /* If DIAGNOSTIC has a CWE identifier, print it.
1292 For example, if the diagnostic metadata associates it with CWE-119,
1293 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1294 description of the security issue. */
1296 static void
1297 print_any_cwe (diagnostic_context *context,
1298 const diagnostic_info *diagnostic)
1300 if (diagnostic->metadata == NULL)
1301 return;
1303 int cwe = diagnostic->metadata->get_cwe ();
1304 if (cwe)
1306 pretty_printer *pp = context->printer;
1307 char *saved_prefix = pp_take_prefix (context->printer);
1308 pp_string (pp, " [");
1309 pp_string (pp, colorize_start (pp_show_color (pp),
1310 diagnostic_kind_color[diagnostic->kind]));
1311 if (pp->url_format != URL_FORMAT_NONE)
1313 char *cwe_url = get_cwe_url (cwe);
1314 pp_begin_url (pp, cwe_url);
1315 free (cwe_url);
1317 pp_printf (pp, "CWE-%i", cwe);
1318 pp_set_prefix (context->printer, saved_prefix);
1319 if (pp->url_format != URL_FORMAT_NONE)
1320 pp_end_url (pp);
1321 pp_string (pp, colorize_stop (pp_show_color (pp)));
1322 pp_character (pp, ']');
1326 /* If DIAGNOSTIC has any rules associated with it, print them.
1328 For example, if the diagnostic metadata associates it with a rule
1329 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1330 with any URL provided by the rule. */
1332 static void
1333 print_any_rules (diagnostic_context *context,
1334 const diagnostic_info *diagnostic)
1336 if (diagnostic->metadata == NULL)
1337 return;
1339 for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
1341 const diagnostic_metadata::rule &rule
1342 = diagnostic->metadata->get_rule (idx);
1343 if (char *desc = rule.make_description ())
1345 pretty_printer *pp = context->printer;
1346 char *saved_prefix = pp_take_prefix (context->printer);
1347 pp_string (pp, " [");
1348 pp_string (pp,
1349 colorize_start (pp_show_color (pp),
1350 diagnostic_kind_color[diagnostic->kind]));
1351 char *url = NULL;
1352 if (pp->url_format != URL_FORMAT_NONE)
1354 url = rule.make_url ();
1355 if (url)
1356 pp_begin_url (pp, url);
1358 pp_string (pp, desc);
1359 pp_set_prefix (context->printer, saved_prefix);
1360 if (pp->url_format != URL_FORMAT_NONE)
1361 if (url)
1362 pp_end_url (pp);
1363 free (url);
1364 pp_string (pp, colorize_stop (pp_show_color (pp)));
1365 pp_character (pp, ']');
1366 free (desc);
1371 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1372 printer, e.g. " [-Werror=uninitialized]".
1373 Subroutine of diagnostic_report_diagnostic. */
1375 static void
1376 print_option_information (diagnostic_context *context,
1377 const diagnostic_info *diagnostic,
1378 diagnostic_t orig_diag_kind)
1380 char *option_text;
1382 option_text = context->option_name (context, diagnostic->option_index,
1383 orig_diag_kind, diagnostic->kind);
1385 if (option_text)
1387 char *option_url = NULL;
1388 if (context->get_option_url
1389 && context->printer->url_format != URL_FORMAT_NONE)
1390 option_url = context->get_option_url (context,
1391 diagnostic->option_index);
1392 pretty_printer *pp = context->printer;
1393 pp_string (pp, " [");
1394 pp_string (pp, colorize_start (pp_show_color (pp),
1395 diagnostic_kind_color[diagnostic->kind]));
1396 if (option_url)
1397 pp_begin_url (pp, option_url);
1398 pp_string (pp, option_text);
1399 if (option_url)
1401 pp_end_url (pp);
1402 free (option_url);
1404 pp_string (pp, colorize_stop (pp_show_color (pp)));
1405 pp_character (pp, ']');
1406 free (option_text);
1410 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1411 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1413 static bool
1414 diagnostic_enabled (diagnostic_context *context,
1415 diagnostic_info *diagnostic)
1417 /* Update the inlining stack for this diagnostic. */
1418 get_any_inlining_info (context, diagnostic);
1420 /* Diagnostics with no option or -fpermissive are always enabled. */
1421 if (!diagnostic->option_index
1422 || diagnostic->option_index == permissive_error_option (context))
1423 return true;
1425 /* This tests if the user provided the appropriate -Wfoo or
1426 -Wno-foo option. */
1427 if (! context->option_enabled (diagnostic->option_index,
1428 context->lang_mask,
1429 context->option_state))
1430 return false;
1432 /* This tests for #pragma diagnostic changes. */
1433 diagnostic_t diag_class
1434 = update_effective_level_from_pragmas (context, diagnostic);
1436 /* This tests if the user provided the appropriate -Werror=foo
1437 option. */
1438 if (diag_class == DK_UNSPECIFIED
1439 && (context->classify_diagnostic[diagnostic->option_index]
1440 != DK_UNSPECIFIED))
1441 diagnostic->kind
1442 = context->classify_diagnostic[diagnostic->option_index];
1444 /* This allows for future extensions, like temporarily disabling
1445 warnings for ranges of source code. */
1446 if (diagnostic->kind == DK_IGNORED)
1447 return false;
1449 return true;
1452 /* Returns whether warning OPT is enabled at LOC. */
1454 bool
1455 warning_enabled_at (location_t loc, int opt)
1457 if (!diagnostic_report_warnings_p (global_dc, loc))
1458 return false;
1460 rich_location richloc (line_table, loc);
1461 diagnostic_info diagnostic = {};
1462 diagnostic.option_index = opt;
1463 diagnostic.richloc = &richloc;
1464 diagnostic.message.m_richloc = &richloc;
1465 diagnostic.kind = DK_WARNING;
1466 return diagnostic_enabled (global_dc, &diagnostic);
1469 /* Report a diagnostic message (an error or a warning) as specified by
1470 DC. This function is *the* subroutine in terms of which front-ends
1471 should implement their specific diagnostic handling modules. The
1472 front-end independent format specifiers are exactly those described
1473 in the documentation of output_format.
1474 Return true if a diagnostic was printed, false otherwise. */
1476 bool
1477 diagnostic_report_diagnostic (diagnostic_context *context,
1478 diagnostic_info *diagnostic)
1480 location_t location = diagnostic_location (diagnostic);
1481 diagnostic_t orig_diag_kind = diagnostic->kind;
1483 /* Give preference to being able to inhibit warnings, before they
1484 get reclassified to something else. */
1485 bool report_warning_p = true;
1486 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1488 if (context->dc_inhibit_warnings)
1489 return false;
1490 /* Remember the result of the overall system header warning setting
1491 but proceed to also check the inlining context. */
1492 report_warning_p = diagnostic_report_warnings_p (context, location);
1493 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1494 return false;
1497 if (diagnostic->kind == DK_PEDWARN)
1499 diagnostic->kind = pedantic_warning_kind (context);
1500 /* We do this to avoid giving the message for -pedantic-errors. */
1501 orig_diag_kind = diagnostic->kind;
1504 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1505 return false;
1507 if (context->lock > 0)
1509 /* If we're reporting an ICE in the middle of some other error,
1510 try to flush out the previous error, then let this one
1511 through. Don't do this more than once. */
1512 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1513 && context->lock == 1)
1514 pp_newline_and_flush (context->printer);
1515 else
1516 error_recursion (context);
1519 /* If the user requested that warnings be treated as errors, so be
1520 it. Note that we do this before the next block so that
1521 individual warnings can be overridden back to warnings with
1522 -Wno-error=*. */
1523 if (context->warning_as_error_requested
1524 && diagnostic->kind == DK_WARNING)
1525 diagnostic->kind = DK_ERROR;
1527 diagnostic->message.x_data = &diagnostic->x_data;
1529 /* Check to see if the diagnostic is enabled at the location and
1530 not disabled by #pragma GCC diagnostic anywhere along the inlining
1531 stack. . */
1532 if (!diagnostic_enabled (context, diagnostic))
1533 return false;
1535 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1536 /* Bail if the warning is not to be reported because all locations
1537 in the inlining stack (if there is one) are in system headers. */
1538 return false;
1540 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1541 diagnostic_check_max_errors (context);
1543 context->lock++;
1545 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1547 /* When not checking, ICEs are converted to fatal errors when an
1548 error has already occurred. This is counteracted by
1549 abort_on_error. */
1550 if (!CHECKING_P
1551 && (diagnostic_kind_count (context, DK_ERROR) > 0
1552 || diagnostic_kind_count (context, DK_SORRY) > 0)
1553 && !context->abort_on_error)
1555 expanded_location s
1556 = expand_location (diagnostic_location (diagnostic));
1557 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1558 s.file, s.line);
1559 exit (ICE_EXIT_CODE);
1561 if (context->internal_error)
1562 (*context->internal_error) (context,
1563 diagnostic->message.format_spec,
1564 diagnostic->message.args_ptr);
1566 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1567 ++diagnostic_kind_count (context, DK_WERROR);
1568 else
1569 ++diagnostic_kind_count (context, diagnostic->kind);
1571 /* Is this the initial diagnostic within the stack of groups? */
1572 if (context->diagnostic_group_emission_count == 0)
1574 if (context->begin_group_cb)
1575 context->begin_group_cb (context);
1577 context->diagnostic_group_emission_count++;
1579 pp_format (context->printer, &diagnostic->message);
1580 (*diagnostic_starter (context)) (context, diagnostic);
1581 pp_output_formatted_text (context->printer);
1582 if (context->show_cwe)
1583 print_any_cwe (context, diagnostic);
1584 if (context->show_rules)
1585 print_any_rules (context, diagnostic);
1586 if (context->show_option_requested)
1587 print_option_information (context, diagnostic, orig_diag_kind);
1588 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1589 switch (context->extra_output_kind)
1591 default:
1592 break;
1593 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1594 print_parseable_fixits (context->printer, diagnostic->richloc,
1595 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1596 context->tabstop);
1597 pp_flush (context->printer);
1598 break;
1599 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1600 print_parseable_fixits (context->printer, diagnostic->richloc,
1601 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1602 context->tabstop);
1603 pp_flush (context->printer);
1604 break;
1606 diagnostic_action_after_output (context, diagnostic->kind);
1607 diagnostic->x_data = NULL;
1609 if (context->edit_context_ptr)
1610 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1611 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1613 context->lock--;
1615 diagnostic_show_any_path (context, diagnostic);
1617 return true;
1620 /* Get the number of digits in the decimal representation of VALUE. */
1623 num_digits (int value)
1625 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1626 using floating point. */
1627 gcc_assert (value >= 0);
1629 if (value == 0)
1630 return 1;
1632 int digits = 0;
1633 while (value > 0)
1635 digits++;
1636 value /= 10;
1638 return digits;
1641 /* Given a partial pathname as input, return another pathname that
1642 shares no directory elements with the pathname of __FILE__. This
1643 is used by fancy_abort() to print `internal compiler error in expr.cc'
1644 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1646 const char *
1647 trim_filename (const char *name)
1649 static const char this_file[] = __FILE__;
1650 const char *p = name, *q = this_file;
1652 /* First skip any "../" in each filename. This allows us to give a proper
1653 reference to a file in a subdirectory. */
1654 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1655 p += 3;
1657 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1658 q += 3;
1660 /* Now skip any parts the two filenames have in common. */
1661 while (*p == *q && *p != 0 && *q != 0)
1662 p++, q++;
1664 /* Now go backwards until the previous directory separator. */
1665 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1666 p--;
1668 return p;
1671 /* Standard error reporting routines in increasing order of severity.
1672 All of these take arguments like printf. */
1674 /* Text to be emitted verbatim to the error message stream; this
1675 produces no prefix and disables line-wrapping. Use rarely. */
1676 void
1677 verbatim (const char *gmsgid, ...)
1679 text_info text;
1680 va_list ap;
1682 va_start (ap, gmsgid);
1683 text.err_no = errno;
1684 text.args_ptr = &ap;
1685 text.format_spec = _(gmsgid);
1686 text.x_data = NULL;
1687 pp_format_verbatim (global_dc->printer, &text);
1688 pp_newline_and_flush (global_dc->printer);
1689 va_end (ap);
1692 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1693 void
1694 diagnostic_append_note (diagnostic_context *context,
1695 location_t location,
1696 const char * gmsgid, ...)
1698 diagnostic_info diagnostic;
1699 va_list ap;
1700 rich_location richloc (line_table, location);
1702 va_start (ap, gmsgid);
1703 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1704 if (context->inhibit_notes_p)
1706 va_end (ap);
1707 return;
1709 char *saved_prefix = pp_take_prefix (context->printer);
1710 pp_set_prefix (context->printer,
1711 diagnostic_build_prefix (context, &diagnostic));
1712 pp_format (context->printer, &diagnostic.message);
1713 pp_output_formatted_text (context->printer);
1714 pp_destroy_prefix (context->printer);
1715 pp_set_prefix (context->printer, saved_prefix);
1716 pp_newline (context->printer);
1717 diagnostic_show_locus (context, &richloc, DK_NOTE);
1718 va_end (ap);
1721 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1722 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1723 and internal_error_no_backtrace, as documented and defined below. */
1724 static bool
1725 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1726 int opt, const char *gmsgid,
1727 va_list *ap, diagnostic_t kind)
1729 diagnostic_info diagnostic;
1730 if (kind == DK_PERMERROR)
1732 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1733 permissive_error_kind (global_dc));
1734 diagnostic.option_index = permissive_error_option (global_dc);
1736 else
1738 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1739 if (kind == DK_WARNING || kind == DK_PEDWARN)
1740 diagnostic.option_index = opt;
1742 diagnostic.metadata = metadata;
1743 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1746 /* Implement inform_n, warning_n, and error_n, as documented and
1747 defined below. */
1748 static bool
1749 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1750 int opt, unsigned HOST_WIDE_INT n,
1751 const char *singular_gmsgid,
1752 const char *plural_gmsgid,
1753 va_list *ap, diagnostic_t kind)
1755 diagnostic_info diagnostic;
1756 unsigned long gtn;
1758 if (sizeof n <= sizeof gtn)
1759 gtn = n;
1760 else
1761 /* Use the largest number ngettext can handle, otherwise
1762 preserve the six least significant decimal digits for
1763 languages where the plural form depends on them. */
1764 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1766 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1767 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1768 if (kind == DK_WARNING)
1769 diagnostic.option_index = opt;
1770 diagnostic.metadata = metadata;
1771 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1774 /* Wrapper around diagnostic_impl taking a variable argument list. */
1776 bool
1777 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1778 const char *gmsgid, ...)
1780 auto_diagnostic_group d;
1781 va_list ap;
1782 va_start (ap, gmsgid);
1783 rich_location richloc (line_table, location);
1784 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1785 va_end (ap);
1786 return ret;
1789 /* As above, but for rich_location *. */
1791 bool
1792 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1793 const char *gmsgid, ...)
1795 auto_diagnostic_group d;
1796 va_list ap;
1797 va_start (ap, gmsgid);
1798 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1799 va_end (ap);
1800 return ret;
1803 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1805 bool
1806 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1807 const char *gmsgid, va_list *ap)
1809 rich_location richloc (line_table, location);
1810 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1813 /* An informative note at LOCATION. Use this for additional details on an error
1814 message. */
1815 void
1816 inform (location_t location, const char *gmsgid, ...)
1818 auto_diagnostic_group d;
1819 va_list ap;
1820 va_start (ap, gmsgid);
1821 rich_location richloc (line_table, location);
1822 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1823 va_end (ap);
1826 /* Same as "inform" above, but at RICHLOC. */
1827 void
1828 inform (rich_location *richloc, const char *gmsgid, ...)
1830 gcc_assert (richloc);
1832 auto_diagnostic_group d;
1833 va_list ap;
1834 va_start (ap, gmsgid);
1835 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1836 va_end (ap);
1839 /* An informative note at LOCATION. Use this for additional details on an
1840 error message. */
1841 void
1842 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1843 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1845 va_list ap;
1846 va_start (ap, plural_gmsgid);
1847 auto_diagnostic_group d;
1848 rich_location richloc (line_table, location);
1849 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1850 &ap, DK_NOTE);
1851 va_end (ap);
1854 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1855 to the relevant language specification but is likely to be buggy anyway.
1856 Returns true if the warning was printed, false if it was inhibited. */
1857 bool
1858 warning (int opt, const char *gmsgid, ...)
1860 auto_diagnostic_group d;
1861 va_list ap;
1862 va_start (ap, gmsgid);
1863 rich_location richloc (line_table, input_location);
1864 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1865 va_end (ap);
1866 return ret;
1869 /* A warning at LOCATION. Use this for code which is correct according to the
1870 relevant language specification but is likely to be buggy anyway.
1871 Returns true if the warning was printed, false if it was inhibited. */
1873 bool
1874 warning_at (location_t location, int opt, const char *gmsgid, ...)
1876 auto_diagnostic_group d;
1877 va_list ap;
1878 va_start (ap, gmsgid);
1879 rich_location richloc (line_table, location);
1880 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1881 va_end (ap);
1882 return ret;
1885 /* Same as "warning at" above, but using RICHLOC. */
1887 bool
1888 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1890 gcc_assert (richloc);
1892 auto_diagnostic_group d;
1893 va_list ap;
1894 va_start (ap, gmsgid);
1895 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1896 va_end (ap);
1897 return ret;
1900 /* Same as "warning at" above, but using METADATA. */
1902 bool
1903 warning_meta (rich_location *richloc,
1904 const diagnostic_metadata &metadata,
1905 int opt, const char *gmsgid, ...)
1907 gcc_assert (richloc);
1909 auto_diagnostic_group d;
1910 va_list ap;
1911 va_start (ap, gmsgid);
1912 bool ret
1913 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1914 DK_WARNING);
1915 va_end (ap);
1916 return ret;
1919 /* Same as warning_n plural variant below, but using RICHLOC. */
1921 bool
1922 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1923 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1925 gcc_assert (richloc);
1927 auto_diagnostic_group d;
1928 va_list ap;
1929 va_start (ap, plural_gmsgid);
1930 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1931 singular_gmsgid, plural_gmsgid,
1932 &ap, DK_WARNING);
1933 va_end (ap);
1934 return ret;
1937 /* A warning at LOCATION. Use this for code which is correct according to the
1938 relevant language specification but is likely to be buggy anyway.
1939 Returns true if the warning was printed, false if it was inhibited. */
1941 bool
1942 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1943 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1945 auto_diagnostic_group d;
1946 va_list ap;
1947 va_start (ap, plural_gmsgid);
1948 rich_location richloc (line_table, location);
1949 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1950 singular_gmsgid, plural_gmsgid,
1951 &ap, DK_WARNING);
1952 va_end (ap);
1953 return ret;
1956 /* A "pedantic" warning at LOCATION: issues a warning unless
1957 -pedantic-errors was given on the command line, in which case it
1958 issues an error. Use this for diagnostics required by the relevant
1959 language standard, if you have chosen not to make them errors.
1961 Note that these diagnostics are issued independent of the setting
1962 of the -Wpedantic command-line switch. To get a warning enabled
1963 only with that switch, use either "if (pedantic) pedwarn
1964 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1965 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1967 Returns true if the warning was printed, false if it was inhibited. */
1969 bool
1970 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1972 auto_diagnostic_group d;
1973 va_list ap;
1974 va_start (ap, gmsgid);
1975 rich_location richloc (line_table, location);
1976 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1977 va_end (ap);
1978 return ret;
1981 /* Same as pedwarn above, but using RICHLOC. */
1983 bool
1984 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1986 gcc_assert (richloc);
1988 auto_diagnostic_group d;
1989 va_list ap;
1990 va_start (ap, gmsgid);
1991 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1992 va_end (ap);
1993 return ret;
1996 /* A "permissive" error at LOCATION: issues an error unless
1997 -fpermissive was given on the command line, in which case it issues
1998 a warning. Use this for things that really should be errors but we
1999 want to support legacy code.
2001 Returns true if the warning was printed, false if it was inhibited. */
2003 bool
2004 permerror (location_t location, const char *gmsgid, ...)
2006 auto_diagnostic_group d;
2007 va_list ap;
2008 va_start (ap, gmsgid);
2009 rich_location richloc (line_table, location);
2010 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2011 va_end (ap);
2012 return ret;
2015 /* Same as "permerror" above, but at RICHLOC. */
2017 bool
2018 permerror (rich_location *richloc, const char *gmsgid, ...)
2020 gcc_assert (richloc);
2022 auto_diagnostic_group d;
2023 va_list ap;
2024 va_start (ap, gmsgid);
2025 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
2026 va_end (ap);
2027 return ret;
2030 /* A hard error: the code is definitely ill-formed, and an object file
2031 will not be produced. */
2032 void
2033 error (const char *gmsgid, ...)
2035 auto_diagnostic_group d;
2036 va_list ap;
2037 va_start (ap, gmsgid);
2038 rich_location richloc (line_table, input_location);
2039 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2040 va_end (ap);
2043 /* A hard error: the code is definitely ill-formed, and an object file
2044 will not be produced. */
2045 void
2046 error_n (location_t location, unsigned HOST_WIDE_INT n,
2047 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2049 auto_diagnostic_group d;
2050 va_list ap;
2051 va_start (ap, plural_gmsgid);
2052 rich_location richloc (line_table, location);
2053 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2054 &ap, DK_ERROR);
2055 va_end (ap);
2058 /* Same as above, but use location LOC instead of input_location. */
2059 void
2060 error_at (location_t loc, const char *gmsgid, ...)
2062 auto_diagnostic_group d;
2063 va_list ap;
2064 va_start (ap, gmsgid);
2065 rich_location richloc (line_table, loc);
2066 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2067 va_end (ap);
2070 /* Same as above, but use RICH_LOC. */
2072 void
2073 error_at (rich_location *richloc, const char *gmsgid, ...)
2075 gcc_assert (richloc);
2077 auto_diagnostic_group d;
2078 va_list ap;
2079 va_start (ap, gmsgid);
2080 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2081 va_end (ap);
2084 /* "Sorry, not implemented." Use for a language feature which is
2085 required by the relevant specification but not implemented by GCC.
2086 An object file will not be produced. */
2087 void
2088 sorry (const char *gmsgid, ...)
2090 auto_diagnostic_group d;
2091 va_list ap;
2092 va_start (ap, gmsgid);
2093 rich_location richloc (line_table, input_location);
2094 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2095 va_end (ap);
2098 /* Same as above, but use location LOC instead of input_location. */
2099 void
2100 sorry_at (location_t loc, const char *gmsgid, ...)
2102 auto_diagnostic_group d;
2103 va_list ap;
2104 va_start (ap, gmsgid);
2105 rich_location richloc (line_table, loc);
2106 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2107 va_end (ap);
2110 /* Return true if an error or a "sorry" has been seen. Various
2111 processing is disabled after errors. */
2112 bool
2113 seen_error (void)
2115 return errorcount || sorrycount;
2118 /* An error which is severe enough that we make no attempt to
2119 continue. Do not use this for internal consistency checks; that's
2120 internal_error. Use of this function should be rare. */
2121 void
2122 fatal_error (location_t loc, const char *gmsgid, ...)
2124 auto_diagnostic_group d;
2125 va_list ap;
2126 va_start (ap, gmsgid);
2127 rich_location richloc (line_table, loc);
2128 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2129 va_end (ap);
2131 gcc_unreachable ();
2134 /* An internal consistency check has failed. We make no attempt to
2135 continue. */
2136 void
2137 internal_error (const char *gmsgid, ...)
2139 auto_diagnostic_group d;
2140 va_list ap;
2141 va_start (ap, gmsgid);
2142 rich_location richloc (line_table, input_location);
2143 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2144 va_end (ap);
2146 gcc_unreachable ();
2149 /* Like internal_error, but no backtrace will be printed. Used when
2150 the internal error does not happen at the current location, but happened
2151 somewhere else. */
2152 void
2153 internal_error_no_backtrace (const char *gmsgid, ...)
2155 auto_diagnostic_group d;
2156 va_list ap;
2157 va_start (ap, gmsgid);
2158 rich_location richloc (line_table, input_location);
2159 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2160 va_end (ap);
2162 gcc_unreachable ();
2165 /* Special case error functions. Most are implemented in terms of the
2166 above, or should be. */
2168 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2169 runs its second argument through gettext. */
2170 void
2171 fnotice (FILE *file, const char *cmsgid, ...)
2173 va_list ap;
2175 va_start (ap, cmsgid);
2176 vfprintf (file, _(cmsgid), ap);
2177 va_end (ap);
2180 /* Inform the user that an error occurred while trying to report some
2181 other error. This indicates catastrophic internal inconsistencies,
2182 so give up now. But do try to flush out the previous error.
2183 This mustn't use internal_error, that will cause infinite recursion. */
2185 static void
2186 error_recursion (diagnostic_context *context)
2188 if (context->lock < 3)
2189 pp_newline_and_flush (context->printer);
2191 fnotice (stderr,
2192 "internal compiler error: error reporting routines re-entered.\n");
2194 /* Call diagnostic_action_after_output to get the "please submit a bug
2195 report" message. */
2196 diagnostic_action_after_output (context, DK_ICE);
2198 /* Do not use gcc_unreachable here; that goes through internal_error
2199 and therefore would cause infinite recursion. */
2200 real_abort ();
2203 /* Report an internal compiler error in a friendly manner. This is
2204 the function that gets called upon use of abort() in the source
2205 code generally, thanks to a special macro. */
2207 void
2208 fancy_abort (const char *file, int line, const char *function)
2210 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2211 internal_error will crash internally in a way that prevents a
2212 useful message reaching the user.
2213 This can happen with libgccjit in the case of gcc_assert failures
2214 that occur outside of the libgccjit mutex that guards the rest of
2215 gcc's state, including global_dc (when global_dc may not be
2216 initialized yet, or might be in use by another thread).
2217 Handle such cases as gracefully as possible by falling back to a
2218 minimal abort handler that only relies on i18n. */
2219 if (global_dc->printer == NULL)
2221 /* Print the error message. */
2222 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2223 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2224 fputc ('\n', stderr);
2226 /* Attempt to print a backtrace. */
2227 struct backtrace_state *state
2228 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2229 int count = 0;
2230 if (state != NULL)
2231 backtrace_full (state, 2, bt_callback, bt_err_callback,
2232 (void *) &count);
2234 /* We can't call warn_if_plugins or emergency_dump_function as these
2235 rely on GCC state that might not be initialized, or might be in
2236 use by another thread. */
2238 /* Abort the process. */
2239 real_abort ();
2242 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2245 /* class auto_diagnostic_group. */
2247 /* Constructor: "push" this group into global_dc. */
2249 auto_diagnostic_group::auto_diagnostic_group ()
2251 global_dc->diagnostic_group_nesting_depth++;
2254 /* Destructor: "pop" this group from global_dc. */
2256 auto_diagnostic_group::~auto_diagnostic_group ()
2258 if (--global_dc->diagnostic_group_nesting_depth == 0)
2260 /* Handle the case where we've popped the final diagnostic group.
2261 If any diagnostics were emitted, give the context a chance
2262 to do something. */
2263 if (global_dc->diagnostic_group_emission_count > 0)
2265 if (global_dc->end_group_cb)
2266 global_dc->end_group_cb (global_dc);
2268 global_dc->diagnostic_group_emission_count = 0;
2272 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2273 file-based output formats. */
2275 void
2276 diagnostic_output_format_init (diagnostic_context *context,
2277 const char *base_file_name,
2278 enum diagnostics_output_format format)
2280 switch (format)
2282 default:
2283 gcc_unreachable ();
2284 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2285 /* The default; do nothing. */
2286 break;
2288 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2289 diagnostic_output_format_init_json_stderr (context);
2290 break;
2292 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2293 diagnostic_output_format_init_json_file (context, base_file_name);
2294 break;
2296 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2297 diagnostic_output_format_init_sarif_stderr (context);
2298 break;
2300 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2301 diagnostic_output_format_init_sarif_file (context, base_file_name);
2302 break;
2306 /* Implementation of diagnostic_path::num_events vfunc for
2307 simple_diagnostic_path: simply get the number of events in the vec. */
2309 unsigned
2310 simple_diagnostic_path::num_events () const
2312 return m_events.length ();
2315 /* Implementation of diagnostic_path::get_event vfunc for
2316 simple_diagnostic_path: simply return the event in the vec. */
2318 const diagnostic_event &
2319 simple_diagnostic_path::get_event (int idx) const
2321 return *m_events[idx];
2324 /* Add an event to this path at LOC within function FNDECL at
2325 stack depth DEPTH.
2327 Use m_context's printer to format FMT, as the text of the new
2328 event.
2330 Return the id of the new event. */
2332 diagnostic_event_id_t
2333 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2334 const char *fmt, ...)
2336 pretty_printer *pp = m_event_pp;
2337 pp_clear_output_area (pp);
2339 text_info ti;
2340 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2342 va_list ap;
2344 va_start (ap, fmt);
2346 ti.format_spec = _(fmt);
2347 ti.args_ptr = &ap;
2348 ti.err_no = 0;
2349 ti.x_data = NULL;
2350 ti.m_richloc = &rich_loc;
2352 pp_format (pp, &ti);
2353 pp_output_formatted_text (pp);
2355 va_end (ap);
2357 simple_diagnostic_event *new_event
2358 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2359 m_events.safe_push (new_event);
2361 pp_clear_output_area (pp);
2363 return diagnostic_event_id_t (m_events.length () - 1);
2366 /* struct simple_diagnostic_event. */
2368 /* simple_diagnostic_event's ctor. */
2370 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2371 tree fndecl,
2372 int depth,
2373 const char *desc)
2374 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2378 /* simple_diagnostic_event's dtor. */
2380 simple_diagnostic_event::~simple_diagnostic_event ()
2382 free (m_desc);
2385 /* Print PATH by emitting a dummy "note" associated with it. */
2387 DEBUG_FUNCTION
2388 void debug (diagnostic_path *path)
2390 rich_location richloc (line_table, UNKNOWN_LOCATION);
2391 richloc.set_path (path);
2392 inform (&richloc, "debug path");
2395 /* Really call the system 'abort'. This has to go right at the end of
2396 this file, so that there are no functions after it that call abort
2397 and get the system abort instead of our macro. */
2398 #undef abort
2399 static void
2400 real_abort (void)
2402 abort ();
2405 #if CHECKING_P
2407 namespace selftest {
2409 /* Helper function for test_print_escaped_string. */
2411 static void
2412 assert_print_escaped_string (const location &loc, const char *expected_output,
2413 const char *input)
2415 pretty_printer pp;
2416 print_escaped_string (&pp, input);
2417 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2420 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2421 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2423 /* Tests of print_escaped_string. */
2425 static void
2426 test_print_escaped_string ()
2428 /* Empty string. */
2429 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2431 /* Non-empty string. */
2432 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2434 /* Various things that need to be escaped: */
2435 /* Backslash. */
2436 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2437 "before\\after");
2438 /* Tab. */
2439 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2440 "before\tafter");
2441 /* Newline. */
2442 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2443 "before\nafter");
2444 /* Double quote. */
2445 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2446 "before\"after");
2448 /* Non-printable characters: BEL: '\a': 0x07 */
2449 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2450 "before\aafter");
2451 /* Non-printable characters: vertical tab: '\v': 0x0b */
2452 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2453 "before\vafter");
2456 /* Tests of print_parseable_fixits. */
2458 /* Verify that print_parseable_fixits emits the empty string if there
2459 are no fixits. */
2461 static void
2462 test_print_parseable_fixits_none ()
2464 pretty_printer pp;
2465 rich_location richloc (line_table, UNKNOWN_LOCATION);
2467 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2468 ASSERT_STREQ ("", pp_formatted_text (&pp));
2471 /* Verify that print_parseable_fixits does the right thing if there
2472 is an insertion fixit hint. */
2474 static void
2475 test_print_parseable_fixits_insert ()
2477 pretty_printer pp;
2478 rich_location richloc (line_table, UNKNOWN_LOCATION);
2480 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2481 linemap_line_start (line_table, 5, 100);
2482 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2483 location_t where = linemap_position_for_column (line_table, 10);
2484 richloc.add_fixit_insert_before (where, "added content");
2486 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2487 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2488 pp_formatted_text (&pp));
2491 /* Verify that print_parseable_fixits does the right thing if there
2492 is an removal fixit hint. */
2494 static void
2495 test_print_parseable_fixits_remove ()
2497 pretty_printer pp;
2498 rich_location richloc (line_table, UNKNOWN_LOCATION);
2500 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2501 linemap_line_start (line_table, 5, 100);
2502 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2503 source_range where;
2504 where.m_start = linemap_position_for_column (line_table, 10);
2505 where.m_finish = linemap_position_for_column (line_table, 20);
2506 richloc.add_fixit_remove (where);
2508 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2509 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2510 pp_formatted_text (&pp));
2513 /* Verify that print_parseable_fixits does the right thing if there
2514 is an replacement fixit hint. */
2516 static void
2517 test_print_parseable_fixits_replace ()
2519 pretty_printer pp;
2520 rich_location richloc (line_table, UNKNOWN_LOCATION);
2522 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2523 linemap_line_start (line_table, 5, 100);
2524 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2525 source_range where;
2526 where.m_start = linemap_position_for_column (line_table, 10);
2527 where.m_finish = linemap_position_for_column (line_table, 20);
2528 richloc.add_fixit_replace (where, "replacement");
2530 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2531 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2532 pp_formatted_text (&pp));
2535 /* Verify that print_parseable_fixits correctly handles
2536 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2538 static void
2539 test_print_parseable_fixits_bytes_vs_display_columns ()
2541 line_table_test ltt;
2542 rich_location richloc (line_table, UNKNOWN_LOCATION);
2544 /* 1-based byte offsets: 12345677778888999900001234567. */
2545 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2546 /* 1-based display cols: 123456[......7-8.....]9012345. */
2547 const int tabstop = 8;
2549 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2550 const char *const fname = tmp.get_filename ();
2552 linemap_add (line_table, LC_ENTER, false, fname, 0);
2553 linemap_line_start (line_table, 1, 100);
2554 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2555 source_range where;
2556 where.m_start = linemap_position_for_column (line_table, 12);
2557 where.m_finish = linemap_position_for_column (line_table, 17);
2558 richloc.add_fixit_replace (where, "color");
2560 /* Escape fname. */
2561 pretty_printer tmp_pp;
2562 print_escaped_string (&tmp_pp, fname);
2563 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2565 const int buf_len = strlen (escaped_fname) + 100;
2566 char *const expected = XNEWVEC (char, buf_len);
2569 pretty_printer pp;
2570 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2571 tabstop);
2572 snprintf (expected, buf_len,
2573 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2574 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2577 pretty_printer pp;
2578 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2579 tabstop);
2580 snprintf (expected, buf_len,
2581 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2582 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2585 XDELETEVEC (expected);
2586 free (escaped_fname);
2589 /* Verify that
2590 diagnostic_get_location_text (..., SHOW_COLUMN)
2591 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2592 colorization disabled. */
2594 static void
2595 assert_location_text (const char *expected_loc_text,
2596 const char *filename, int line, int column,
2597 bool show_column,
2598 int origin = 1,
2599 enum diagnostics_column_unit column_unit
2600 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2602 test_diagnostic_context dc;
2603 dc.show_column = show_column;
2604 dc.column_unit = column_unit;
2605 dc.column_origin = origin;
2607 expanded_location xloc;
2608 xloc.file = filename;
2609 xloc.line = line;
2610 xloc.column = column;
2611 xloc.data = NULL;
2612 xloc.sysp = false;
2614 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2615 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2616 free (actual_loc_text);
2619 /* Verify that diagnostic_get_location_text works as expected. */
2621 static void
2622 test_diagnostic_get_location_text ()
2624 const char *old_progname = progname;
2625 progname = "PROGNAME";
2626 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2627 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2628 assert_location_text (built_in_colon, special_fname_builtin (),
2629 42, 10, true);
2630 free (built_in_colon);
2631 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2632 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2633 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2634 for (int origin = 0; origin != 2; ++origin)
2635 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2636 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2637 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2638 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2640 maybe_line_and_column (INT_MAX, INT_MAX);
2641 maybe_line_and_column (INT_MIN, INT_MIN);
2644 /* In order to test display columns vs byte columns, we need to create a
2645 file for location_get_source_line() to read. */
2647 const char *const content = "smile \xf0\x9f\x98\x82\n";
2648 const int line_bytes = strlen (content) - 1;
2649 const int def_tabstop = 8;
2650 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2651 const int display_width = cpp_display_width (content, line_bytes, policy);
2652 ASSERT_EQ (line_bytes - 2, display_width);
2653 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2654 const char *const fname = tmp.get_filename ();
2655 const int buf_len = strlen (fname) + 16;
2656 char *const expected = XNEWVEC (char, buf_len);
2658 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2659 assert_location_text (expected, fname, 1, line_bytes, true,
2660 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2662 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2663 assert_location_text (expected, fname, 1, line_bytes, true,
2664 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2666 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2667 assert_location_text (expected, fname, 1, line_bytes, true,
2668 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2670 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2671 assert_location_text (expected, fname, 1, line_bytes, true,
2672 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2674 XDELETEVEC (expected);
2678 progname = old_progname;
2681 /* Selftest for num_digits. */
2683 static void
2684 test_num_digits ()
2686 ASSERT_EQ (1, num_digits (0));
2687 ASSERT_EQ (1, num_digits (9));
2688 ASSERT_EQ (2, num_digits (10));
2689 ASSERT_EQ (2, num_digits (99));
2690 ASSERT_EQ (3, num_digits (100));
2691 ASSERT_EQ (3, num_digits (999));
2692 ASSERT_EQ (4, num_digits (1000));
2693 ASSERT_EQ (4, num_digits (9999));
2694 ASSERT_EQ (5, num_digits (10000));
2695 ASSERT_EQ (5, num_digits (99999));
2696 ASSERT_EQ (6, num_digits (100000));
2697 ASSERT_EQ (6, num_digits (999999));
2698 ASSERT_EQ (7, num_digits (1000000));
2699 ASSERT_EQ (7, num_digits (9999999));
2700 ASSERT_EQ (8, num_digits (10000000));
2701 ASSERT_EQ (8, num_digits (99999999));
2704 /* Run all of the selftests within this file. */
2706 void
2707 c_diagnostic_cc_tests ()
2709 test_print_escaped_string ();
2710 test_print_parseable_fixits_none ();
2711 test_print_parseable_fixits_insert ();
2712 test_print_parseable_fixits_remove ();
2713 test_print_parseable_fixits_replace ();
2714 test_print_parseable_fixits_bytes_vs_display_columns ();
2715 test_diagnostic_get_location_text ();
2716 test_num_digits ();
2720 } // namespace selftest
2722 #endif /* #if CHECKING_P */
2724 #if __GNUC__ >= 10
2725 # pragma GCC diagnostic pop
2726 #endif