c++: top level bind when rewriting coroutines [PR106188]
[official-gcc.git] / gcc / diagnostic.cc
blob22f7b0b6d6ed8d1faeb540ed0e85d0f267f82a9c
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, N_("<built-in>")))
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 /* Return true if the events in this path involve more than one
943 function, or false if it is purely intraprocedural. */
945 bool
946 diagnostic_path::interprocedural_p () const
948 const unsigned num = num_events ();
949 for (unsigned i = 0; i < num; i++)
951 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
952 return true;
953 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
954 return true;
956 return false;
959 void
960 default_diagnostic_starter (diagnostic_context *context,
961 diagnostic_info *diagnostic)
963 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
964 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
965 diagnostic));
968 void
969 default_diagnostic_start_span_fn (diagnostic_context *context,
970 expanded_location exploc)
972 char *text = diagnostic_get_location_text (context, exploc);
973 pp_string (context->printer, text);
974 free (text);
975 pp_newline (context->printer);
978 void
979 default_diagnostic_finalizer (diagnostic_context *context,
980 diagnostic_info *diagnostic,
981 diagnostic_t)
983 char *saved_prefix = pp_take_prefix (context->printer);
984 pp_set_prefix (context->printer, NULL);
985 pp_newline (context->printer);
986 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
987 pp_set_prefix (context->printer, saved_prefix);
988 pp_flush (context->printer);
991 /* Interface to specify diagnostic kind overrides. Returns the
992 previous setting, or DK_UNSPECIFIED if the parameters are out of
993 range. If OPTION_INDEX is zero, the new setting is for all the
994 diagnostics. */
995 diagnostic_t
996 diagnostic_classify_diagnostic (diagnostic_context *context,
997 int option_index,
998 diagnostic_t new_kind,
999 location_t where)
1001 diagnostic_t old_kind;
1003 if (option_index < 0
1004 || option_index >= context->n_opts
1005 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1006 return DK_UNSPECIFIED;
1008 old_kind = context->classify_diagnostic[option_index];
1010 /* Handle pragmas separately, since we need to keep track of *where*
1011 the pragmas were. */
1012 if (where != UNKNOWN_LOCATION)
1014 int i;
1016 /* Record the command-line status, so we can reset it back on DK_POP. */
1017 if (old_kind == DK_UNSPECIFIED)
1019 old_kind = !context->option_enabled (option_index,
1020 context->lang_mask,
1021 context->option_state)
1022 ? DK_IGNORED : (context->warning_as_error_requested
1023 ? DK_ERROR : DK_WARNING);
1024 context->classify_diagnostic[option_index] = old_kind;
1027 for (i = context->n_classification_history - 1; i >= 0; i --)
1028 if (context->classification_history[i].option == option_index)
1030 old_kind = context->classification_history[i].kind;
1031 break;
1034 i = context->n_classification_history;
1035 context->classification_history =
1036 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1037 * sizeof (diagnostic_classification_change_t));
1038 context->classification_history[i].location = where;
1039 context->classification_history[i].option = option_index;
1040 context->classification_history[i].kind = new_kind;
1041 context->n_classification_history ++;
1043 else
1044 context->classify_diagnostic[option_index] = new_kind;
1046 return old_kind;
1049 /* Save all diagnostic classifications in a stack. */
1050 void
1051 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
1053 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
1054 context->push_list[context->n_push ++] = context->n_classification_history;
1057 /* Restore the topmost classification set off the stack. If the stack
1058 is empty, revert to the state based on command line parameters. */
1059 void
1060 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
1062 int jump_to;
1063 int i;
1065 if (context->n_push)
1066 jump_to = context->push_list [-- context->n_push];
1067 else
1068 jump_to = 0;
1070 i = context->n_classification_history;
1071 context->classification_history =
1072 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1073 * sizeof (diagnostic_classification_change_t));
1074 context->classification_history[i].location = where;
1075 context->classification_history[i].option = jump_to;
1076 context->classification_history[i].kind = DK_POP;
1077 context->n_classification_history ++;
1080 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1081 escaping rules for -fdiagnostics-parseable-fixits. */
1083 static void
1084 print_escaped_string (pretty_printer *pp, const char *text)
1086 gcc_assert (pp);
1087 gcc_assert (text);
1089 pp_character (pp, '"');
1090 for (const char *ch = text; *ch; ch++)
1092 switch (*ch)
1094 case '\\':
1095 /* Escape backslash as two backslashes. */
1096 pp_string (pp, "\\\\");
1097 break;
1098 case '\t':
1099 /* Escape tab as "\t". */
1100 pp_string (pp, "\\t");
1101 break;
1102 case '\n':
1103 /* Escape newline as "\n". */
1104 pp_string (pp, "\\n");
1105 break;
1106 case '"':
1107 /* Escape doublequotes as \". */
1108 pp_string (pp, "\\\"");
1109 break;
1110 default:
1111 if (ISPRINT (*ch))
1112 pp_character (pp, *ch);
1113 else
1114 /* Use octal for non-printable chars. */
1116 unsigned char c = (*ch & 0xff);
1117 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1119 break;
1122 pp_character (pp, '"');
1125 /* Implementation of -fdiagnostics-parseable-fixits and
1126 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1127 Print a machine-parseable version of all fixits in RICHLOC to PP,
1128 using COLUMN_UNIT to express columns.
1129 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1131 static void
1132 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1133 enum diagnostics_column_unit column_unit,
1134 int tabstop)
1136 gcc_assert (pp);
1137 gcc_assert (richloc);
1139 char *saved_prefix = pp_take_prefix (pp);
1140 pp_set_prefix (pp, NULL);
1142 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1144 const fixit_hint *hint = richloc->get_fixit_hint (i);
1145 location_t start_loc = hint->get_start_loc ();
1146 expanded_location start_exploc = expand_location (start_loc);
1147 pp_string (pp, "fix-it:");
1148 print_escaped_string (pp, start_exploc.file);
1149 /* For compatibility with clang, print as a half-open range. */
1150 location_t next_loc = hint->get_next_loc ();
1151 expanded_location next_exploc = expand_location (next_loc);
1152 int start_col
1153 = convert_column_unit (column_unit, tabstop, start_exploc);
1154 int next_col
1155 = convert_column_unit (column_unit, tabstop, next_exploc);
1156 pp_printf (pp, ":{%i:%i-%i:%i}:",
1157 start_exploc.line, start_col,
1158 next_exploc.line, next_col);
1159 print_escaped_string (pp, hint->get_string ());
1160 pp_newline (pp);
1163 pp_set_prefix (pp, saved_prefix);
1166 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1168 static void
1169 get_any_inlining_info (diagnostic_context *context,
1170 diagnostic_info *diagnostic)
1172 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1174 if (context->set_locations_cb)
1175 /* Retrieve the locations into which the expression about to be
1176 diagnosed has been inlined, including those of all the callers
1177 all the way down the inlining stack. */
1178 context->set_locations_cb (context, diagnostic);
1179 else
1181 /* When there's no callback use just the one location provided
1182 by the caller of the diagnostic function. */
1183 location_t loc = diagnostic_location (diagnostic);
1184 ilocs.safe_push (loc);
1185 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1189 /* Update the kind of DIAGNOSTIC based on its location(s), including
1190 any of those in its inlining stack, relative to any
1191 #pragma GCC diagnostic
1192 directives recorded within CONTEXT.
1194 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1195 otherwise. */
1197 static diagnostic_t
1198 update_effective_level_from_pragmas (diagnostic_context *context,
1199 diagnostic_info *diagnostic)
1201 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1203 /* Ignore the diagnostic if all the inlined locations are
1204 in system headers and -Wno-system-headers is in effect. */
1205 diagnostic->kind = DK_IGNORED;
1206 return DK_IGNORED;
1209 if (context->n_classification_history <= 0)
1210 return DK_UNSPECIFIED;
1212 /* Iterate over the locations, checking the diagnostic disposition
1213 for the diagnostic at each. If it's explicitly set as opposed
1214 to unspecified, update the disposition for this instance of
1215 the diagnostic and return it. */
1216 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1218 /* FIXME: Stupid search. Optimize later. */
1219 for (int i = context->n_classification_history - 1; i >= 0; i --)
1221 const diagnostic_classification_change_t &hist
1222 = context->classification_history[i];
1224 location_t pragloc = hist.location;
1225 if (!linemap_location_before_p (line_table, pragloc, loc))
1226 continue;
1228 if (hist.kind == (int) DK_POP)
1230 /* Move on to the next region. */
1231 i = hist.option;
1232 continue;
1235 int option = hist.option;
1236 /* The option 0 is for all the diagnostics. */
1237 if (option == 0 || option == diagnostic->option_index)
1239 diagnostic_t kind = hist.kind;
1240 if (kind != DK_UNSPECIFIED)
1241 diagnostic->kind = kind;
1242 return kind;
1247 return DK_UNSPECIFIED;
1250 /* Generate a URL string describing CWE. The caller is responsible for
1251 freeing the string. */
1253 char *
1254 get_cwe_url (int cwe)
1256 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1259 /* If DIAGNOSTIC has a CWE identifier, print it.
1261 For example, if the diagnostic metadata associates it with CWE-119,
1262 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1263 description of the security issue. */
1265 static void
1266 print_any_cwe (diagnostic_context *context,
1267 const diagnostic_info *diagnostic)
1269 if (diagnostic->metadata == NULL)
1270 return;
1272 int cwe = diagnostic->metadata->get_cwe ();
1273 if (cwe)
1275 pretty_printer *pp = context->printer;
1276 char *saved_prefix = pp_take_prefix (context->printer);
1277 pp_string (pp, " [");
1278 pp_string (pp, colorize_start (pp_show_color (pp),
1279 diagnostic_kind_color[diagnostic->kind]));
1280 if (pp->url_format != URL_FORMAT_NONE)
1282 char *cwe_url = get_cwe_url (cwe);
1283 pp_begin_url (pp, cwe_url);
1284 free (cwe_url);
1286 pp_printf (pp, "CWE-%i", cwe);
1287 pp_set_prefix (context->printer, saved_prefix);
1288 if (pp->url_format != URL_FORMAT_NONE)
1289 pp_end_url (pp);
1290 pp_string (pp, colorize_stop (pp_show_color (pp)));
1291 pp_character (pp, ']');
1295 /* If DIAGNOSTIC has any rules associated with it, print them.
1297 For example, if the diagnostic metadata associates it with a rule
1298 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1299 with any URL provided by the rule. */
1301 static void
1302 print_any_rules (diagnostic_context *context,
1303 const diagnostic_info *diagnostic)
1305 if (diagnostic->metadata == NULL)
1306 return;
1308 for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
1310 const diagnostic_metadata::rule &rule
1311 = diagnostic->metadata->get_rule (idx);
1312 if (char *desc = rule.make_description ())
1314 pretty_printer *pp = context->printer;
1315 char *saved_prefix = pp_take_prefix (context->printer);
1316 pp_string (pp, " [");
1317 pp_string (pp,
1318 colorize_start (pp_show_color (pp),
1319 diagnostic_kind_color[diagnostic->kind]));
1320 char *url = NULL;
1321 if (pp->url_format != URL_FORMAT_NONE)
1323 url = rule.make_url ();
1324 if (url)
1325 pp_begin_url (pp, url);
1327 pp_string (pp, desc);
1328 pp_set_prefix (context->printer, saved_prefix);
1329 if (pp->url_format != URL_FORMAT_NONE)
1330 if (url)
1331 pp_end_url (pp);
1332 free (url);
1333 pp_string (pp, colorize_stop (pp_show_color (pp)));
1334 pp_character (pp, ']');
1335 free (desc);
1340 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1341 printer, e.g. " [-Werror=uninitialized]".
1342 Subroutine of diagnostic_report_diagnostic. */
1344 static void
1345 print_option_information (diagnostic_context *context,
1346 const diagnostic_info *diagnostic,
1347 diagnostic_t orig_diag_kind)
1349 char *option_text;
1351 option_text = context->option_name (context, diagnostic->option_index,
1352 orig_diag_kind, diagnostic->kind);
1354 if (option_text)
1356 char *option_url = NULL;
1357 if (context->get_option_url
1358 && context->printer->url_format != URL_FORMAT_NONE)
1359 option_url = context->get_option_url (context,
1360 diagnostic->option_index);
1361 pretty_printer *pp = context->printer;
1362 pp_string (pp, " [");
1363 pp_string (pp, colorize_start (pp_show_color (pp),
1364 diagnostic_kind_color[diagnostic->kind]));
1365 if (option_url)
1366 pp_begin_url (pp, option_url);
1367 pp_string (pp, option_text);
1368 if (option_url)
1370 pp_end_url (pp);
1371 free (option_url);
1373 pp_string (pp, colorize_stop (pp_show_color (pp)));
1374 pp_character (pp, ']');
1375 free (option_text);
1379 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1380 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1382 static bool
1383 diagnostic_enabled (diagnostic_context *context,
1384 diagnostic_info *diagnostic)
1386 /* Update the inlining stack for this diagnostic. */
1387 get_any_inlining_info (context, diagnostic);
1389 /* Diagnostics with no option or -fpermissive are always enabled. */
1390 if (!diagnostic->option_index
1391 || diagnostic->option_index == permissive_error_option (context))
1392 return true;
1394 /* This tests if the user provided the appropriate -Wfoo or
1395 -Wno-foo option. */
1396 if (! context->option_enabled (diagnostic->option_index,
1397 context->lang_mask,
1398 context->option_state))
1399 return false;
1401 /* This tests for #pragma diagnostic changes. */
1402 diagnostic_t diag_class
1403 = update_effective_level_from_pragmas (context, diagnostic);
1405 /* This tests if the user provided the appropriate -Werror=foo
1406 option. */
1407 if (diag_class == DK_UNSPECIFIED
1408 && (context->classify_diagnostic[diagnostic->option_index]
1409 != DK_UNSPECIFIED))
1410 diagnostic->kind
1411 = context->classify_diagnostic[diagnostic->option_index];
1413 /* This allows for future extensions, like temporarily disabling
1414 warnings for ranges of source code. */
1415 if (diagnostic->kind == DK_IGNORED)
1416 return false;
1418 return true;
1421 /* Returns whether warning OPT is enabled at LOC. */
1423 bool
1424 warning_enabled_at (location_t loc, int opt)
1426 if (!diagnostic_report_warnings_p (global_dc, loc))
1427 return false;
1429 rich_location richloc (line_table, loc);
1430 diagnostic_info diagnostic = {};
1431 diagnostic.option_index = opt;
1432 diagnostic.richloc = &richloc;
1433 diagnostic.message.m_richloc = &richloc;
1434 diagnostic.kind = DK_WARNING;
1435 return diagnostic_enabled (global_dc, &diagnostic);
1438 /* Report a diagnostic message (an error or a warning) as specified by
1439 DC. This function is *the* subroutine in terms of which front-ends
1440 should implement their specific diagnostic handling modules. The
1441 front-end independent format specifiers are exactly those described
1442 in the documentation of output_format.
1443 Return true if a diagnostic was printed, false otherwise. */
1445 bool
1446 diagnostic_report_diagnostic (diagnostic_context *context,
1447 diagnostic_info *diagnostic)
1449 location_t location = diagnostic_location (diagnostic);
1450 diagnostic_t orig_diag_kind = diagnostic->kind;
1452 /* Give preference to being able to inhibit warnings, before they
1453 get reclassified to something else. */
1454 bool report_warning_p = true;
1455 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1457 if (context->dc_inhibit_warnings)
1458 return false;
1459 /* Remember the result of the overall system header warning setting
1460 but proceed to also check the inlining context. */
1461 report_warning_p = diagnostic_report_warnings_p (context, location);
1462 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1463 return false;
1466 if (diagnostic->kind == DK_PEDWARN)
1468 diagnostic->kind = pedantic_warning_kind (context);
1469 /* We do this to avoid giving the message for -pedantic-errors. */
1470 orig_diag_kind = diagnostic->kind;
1473 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1474 return false;
1476 if (context->lock > 0)
1478 /* If we're reporting an ICE in the middle of some other error,
1479 try to flush out the previous error, then let this one
1480 through. Don't do this more than once. */
1481 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1482 && context->lock == 1)
1483 pp_newline_and_flush (context->printer);
1484 else
1485 error_recursion (context);
1488 /* If the user requested that warnings be treated as errors, so be
1489 it. Note that we do this before the next block so that
1490 individual warnings can be overridden back to warnings with
1491 -Wno-error=*. */
1492 if (context->warning_as_error_requested
1493 && diagnostic->kind == DK_WARNING)
1494 diagnostic->kind = DK_ERROR;
1496 diagnostic->message.x_data = &diagnostic->x_data;
1498 /* Check to see if the diagnostic is enabled at the location and
1499 not disabled by #pragma GCC diagnostic anywhere along the inlining
1500 stack. . */
1501 if (!diagnostic_enabled (context, diagnostic))
1502 return false;
1504 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1505 /* Bail if the warning is not to be reported because all locations
1506 in the inlining stack (if there is one) are in system headers. */
1507 return false;
1509 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1510 diagnostic_check_max_errors (context);
1512 context->lock++;
1514 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1516 /* When not checking, ICEs are converted to fatal errors when an
1517 error has already occurred. This is counteracted by
1518 abort_on_error. */
1519 if (!CHECKING_P
1520 && (diagnostic_kind_count (context, DK_ERROR) > 0
1521 || diagnostic_kind_count (context, DK_SORRY) > 0)
1522 && !context->abort_on_error)
1524 expanded_location s
1525 = expand_location (diagnostic_location (diagnostic));
1526 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1527 s.file, s.line);
1528 exit (ICE_EXIT_CODE);
1530 if (context->internal_error)
1531 (*context->internal_error) (context,
1532 diagnostic->message.format_spec,
1533 diagnostic->message.args_ptr);
1535 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1536 ++diagnostic_kind_count (context, DK_WERROR);
1537 else
1538 ++diagnostic_kind_count (context, diagnostic->kind);
1540 /* Is this the initial diagnostic within the stack of groups? */
1541 if (context->diagnostic_group_emission_count == 0)
1543 if (context->begin_group_cb)
1544 context->begin_group_cb (context);
1546 context->diagnostic_group_emission_count++;
1548 pp_format (context->printer, &diagnostic->message);
1549 (*diagnostic_starter (context)) (context, diagnostic);
1550 pp_output_formatted_text (context->printer);
1551 if (context->show_cwe)
1552 print_any_cwe (context, diagnostic);
1553 if (context->show_rules)
1554 print_any_rules (context, diagnostic);
1555 if (context->show_option_requested)
1556 print_option_information (context, diagnostic, orig_diag_kind);
1557 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1558 switch (context->extra_output_kind)
1560 default:
1561 break;
1562 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1563 print_parseable_fixits (context->printer, diagnostic->richloc,
1564 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1565 context->tabstop);
1566 pp_flush (context->printer);
1567 break;
1568 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1569 print_parseable_fixits (context->printer, diagnostic->richloc,
1570 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1571 context->tabstop);
1572 pp_flush (context->printer);
1573 break;
1575 diagnostic_action_after_output (context, diagnostic->kind);
1576 diagnostic->x_data = NULL;
1578 if (context->edit_context_ptr)
1579 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1580 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1582 context->lock--;
1584 diagnostic_show_any_path (context, diagnostic);
1586 return true;
1589 /* Get the number of digits in the decimal representation of VALUE. */
1592 num_digits (int value)
1594 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1595 using floating point. */
1596 gcc_assert (value >= 0);
1598 if (value == 0)
1599 return 1;
1601 int digits = 0;
1602 while (value > 0)
1604 digits++;
1605 value /= 10;
1607 return digits;
1610 /* Given a partial pathname as input, return another pathname that
1611 shares no directory elements with the pathname of __FILE__. This
1612 is used by fancy_abort() to print `internal compiler error in expr.cc'
1613 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1615 const char *
1616 trim_filename (const char *name)
1618 static const char this_file[] = __FILE__;
1619 const char *p = name, *q = this_file;
1621 /* First skip any "../" in each filename. This allows us to give a proper
1622 reference to a file in a subdirectory. */
1623 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1624 p += 3;
1626 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1627 q += 3;
1629 /* Now skip any parts the two filenames have in common. */
1630 while (*p == *q && *p != 0 && *q != 0)
1631 p++, q++;
1633 /* Now go backwards until the previous directory separator. */
1634 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1635 p--;
1637 return p;
1640 /* Standard error reporting routines in increasing order of severity.
1641 All of these take arguments like printf. */
1643 /* Text to be emitted verbatim to the error message stream; this
1644 produces no prefix and disables line-wrapping. Use rarely. */
1645 void
1646 verbatim (const char *gmsgid, ...)
1648 text_info text;
1649 va_list ap;
1651 va_start (ap, gmsgid);
1652 text.err_no = errno;
1653 text.args_ptr = &ap;
1654 text.format_spec = _(gmsgid);
1655 text.x_data = NULL;
1656 pp_format_verbatim (global_dc->printer, &text);
1657 pp_newline_and_flush (global_dc->printer);
1658 va_end (ap);
1661 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1662 void
1663 diagnostic_append_note (diagnostic_context *context,
1664 location_t location,
1665 const char * gmsgid, ...)
1667 diagnostic_info diagnostic;
1668 va_list ap;
1669 rich_location richloc (line_table, location);
1671 va_start (ap, gmsgid);
1672 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1673 if (context->inhibit_notes_p)
1675 va_end (ap);
1676 return;
1678 char *saved_prefix = pp_take_prefix (context->printer);
1679 pp_set_prefix (context->printer,
1680 diagnostic_build_prefix (context, &diagnostic));
1681 pp_format (context->printer, &diagnostic.message);
1682 pp_output_formatted_text (context->printer);
1683 pp_destroy_prefix (context->printer);
1684 pp_set_prefix (context->printer, saved_prefix);
1685 pp_newline (context->printer);
1686 diagnostic_show_locus (context, &richloc, DK_NOTE);
1687 va_end (ap);
1690 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1691 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1692 and internal_error_no_backtrace, as documented and defined below. */
1693 static bool
1694 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1695 int opt, const char *gmsgid,
1696 va_list *ap, diagnostic_t kind)
1698 diagnostic_info diagnostic;
1699 if (kind == DK_PERMERROR)
1701 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1702 permissive_error_kind (global_dc));
1703 diagnostic.option_index = permissive_error_option (global_dc);
1705 else
1707 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1708 if (kind == DK_WARNING || kind == DK_PEDWARN)
1709 diagnostic.option_index = opt;
1711 diagnostic.metadata = metadata;
1712 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1715 /* Implement inform_n, warning_n, and error_n, as documented and
1716 defined below. */
1717 static bool
1718 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1719 int opt, unsigned HOST_WIDE_INT n,
1720 const char *singular_gmsgid,
1721 const char *plural_gmsgid,
1722 va_list *ap, diagnostic_t kind)
1724 diagnostic_info diagnostic;
1725 unsigned long gtn;
1727 if (sizeof n <= sizeof gtn)
1728 gtn = n;
1729 else
1730 /* Use the largest number ngettext can handle, otherwise
1731 preserve the six least significant decimal digits for
1732 languages where the plural form depends on them. */
1733 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1735 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1736 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1737 if (kind == DK_WARNING)
1738 diagnostic.option_index = opt;
1739 diagnostic.metadata = metadata;
1740 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1743 /* Wrapper around diagnostic_impl taking a variable argument list. */
1745 bool
1746 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1747 const char *gmsgid, ...)
1749 auto_diagnostic_group d;
1750 va_list ap;
1751 va_start (ap, gmsgid);
1752 rich_location richloc (line_table, location);
1753 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1754 va_end (ap);
1755 return ret;
1758 /* As above, but for rich_location *. */
1760 bool
1761 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1762 const char *gmsgid, ...)
1764 auto_diagnostic_group d;
1765 va_list ap;
1766 va_start (ap, gmsgid);
1767 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1768 va_end (ap);
1769 return ret;
1772 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1774 bool
1775 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1776 const char *gmsgid, va_list *ap)
1778 rich_location richloc (line_table, location);
1779 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1782 /* An informative note at LOCATION. Use this for additional details on an error
1783 message. */
1784 void
1785 inform (location_t location, const char *gmsgid, ...)
1787 auto_diagnostic_group d;
1788 va_list ap;
1789 va_start (ap, gmsgid);
1790 rich_location richloc (line_table, location);
1791 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1792 va_end (ap);
1795 /* Same as "inform" above, but at RICHLOC. */
1796 void
1797 inform (rich_location *richloc, const char *gmsgid, ...)
1799 gcc_assert (richloc);
1801 auto_diagnostic_group d;
1802 va_list ap;
1803 va_start (ap, gmsgid);
1804 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1805 va_end (ap);
1808 /* An informative note at LOCATION. Use this for additional details on an
1809 error message. */
1810 void
1811 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1812 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1814 va_list ap;
1815 va_start (ap, plural_gmsgid);
1816 auto_diagnostic_group d;
1817 rich_location richloc (line_table, location);
1818 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1819 &ap, DK_NOTE);
1820 va_end (ap);
1823 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1824 to the relevant language specification but is likely to be buggy anyway.
1825 Returns true if the warning was printed, false if it was inhibited. */
1826 bool
1827 warning (int opt, const char *gmsgid, ...)
1829 auto_diagnostic_group d;
1830 va_list ap;
1831 va_start (ap, gmsgid);
1832 rich_location richloc (line_table, input_location);
1833 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1834 va_end (ap);
1835 return ret;
1838 /* A warning at LOCATION. Use this for code which is correct according to the
1839 relevant language specification but is likely to be buggy anyway.
1840 Returns true if the warning was printed, false if it was inhibited. */
1842 bool
1843 warning_at (location_t location, int opt, const char *gmsgid, ...)
1845 auto_diagnostic_group d;
1846 va_list ap;
1847 va_start (ap, gmsgid);
1848 rich_location richloc (line_table, location);
1849 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1850 va_end (ap);
1851 return ret;
1854 /* Same as "warning at" above, but using RICHLOC. */
1856 bool
1857 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1859 gcc_assert (richloc);
1861 auto_diagnostic_group d;
1862 va_list ap;
1863 va_start (ap, gmsgid);
1864 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1865 va_end (ap);
1866 return ret;
1869 /* Same as "warning at" above, but using METADATA. */
1871 bool
1872 warning_meta (rich_location *richloc,
1873 const diagnostic_metadata &metadata,
1874 int opt, const char *gmsgid, ...)
1876 gcc_assert (richloc);
1878 auto_diagnostic_group d;
1879 va_list ap;
1880 va_start (ap, gmsgid);
1881 bool ret
1882 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1883 DK_WARNING);
1884 va_end (ap);
1885 return ret;
1888 /* Same as warning_n plural variant below, but using RICHLOC. */
1890 bool
1891 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1892 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1894 gcc_assert (richloc);
1896 auto_diagnostic_group d;
1897 va_list ap;
1898 va_start (ap, plural_gmsgid);
1899 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1900 singular_gmsgid, plural_gmsgid,
1901 &ap, DK_WARNING);
1902 va_end (ap);
1903 return ret;
1906 /* A warning at LOCATION. Use this for code which is correct according to the
1907 relevant language specification but is likely to be buggy anyway.
1908 Returns true if the warning was printed, false if it was inhibited. */
1910 bool
1911 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1912 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1914 auto_diagnostic_group d;
1915 va_list ap;
1916 va_start (ap, plural_gmsgid);
1917 rich_location richloc (line_table, location);
1918 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1919 singular_gmsgid, plural_gmsgid,
1920 &ap, DK_WARNING);
1921 va_end (ap);
1922 return ret;
1925 /* A "pedantic" warning at LOCATION: issues a warning unless
1926 -pedantic-errors was given on the command line, in which case it
1927 issues an error. Use this for diagnostics required by the relevant
1928 language standard, if you have chosen not to make them errors.
1930 Note that these diagnostics are issued independent of the setting
1931 of the -Wpedantic command-line switch. To get a warning enabled
1932 only with that switch, use either "if (pedantic) pedwarn
1933 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1934 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1936 Returns true if the warning was printed, false if it was inhibited. */
1938 bool
1939 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1941 auto_diagnostic_group d;
1942 va_list ap;
1943 va_start (ap, gmsgid);
1944 rich_location richloc (line_table, location);
1945 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1946 va_end (ap);
1947 return ret;
1950 /* Same as pedwarn above, but using RICHLOC. */
1952 bool
1953 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1955 gcc_assert (richloc);
1957 auto_diagnostic_group d;
1958 va_list ap;
1959 va_start (ap, gmsgid);
1960 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1961 va_end (ap);
1962 return ret;
1965 /* A "permissive" error at LOCATION: issues an error unless
1966 -fpermissive was given on the command line, in which case it issues
1967 a warning. Use this for things that really should be errors but we
1968 want to support legacy code.
1970 Returns true if the warning was printed, false if it was inhibited. */
1972 bool
1973 permerror (location_t location, const char *gmsgid, ...)
1975 auto_diagnostic_group d;
1976 va_list ap;
1977 va_start (ap, gmsgid);
1978 rich_location richloc (line_table, location);
1979 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1980 va_end (ap);
1981 return ret;
1984 /* Same as "permerror" above, but at RICHLOC. */
1986 bool
1987 permerror (rich_location *richloc, const char *gmsgid, ...)
1989 gcc_assert (richloc);
1991 auto_diagnostic_group d;
1992 va_list ap;
1993 va_start (ap, gmsgid);
1994 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1995 va_end (ap);
1996 return ret;
1999 /* A hard error: the code is definitely ill-formed, and an object file
2000 will not be produced. */
2001 void
2002 error (const char *gmsgid, ...)
2004 auto_diagnostic_group d;
2005 va_list ap;
2006 va_start (ap, gmsgid);
2007 rich_location richloc (line_table, input_location);
2008 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2009 va_end (ap);
2012 /* A hard error: the code is definitely ill-formed, and an object file
2013 will not be produced. */
2014 void
2015 error_n (location_t location, unsigned HOST_WIDE_INT n,
2016 const char *singular_gmsgid, const char *plural_gmsgid, ...)
2018 auto_diagnostic_group d;
2019 va_list ap;
2020 va_start (ap, plural_gmsgid);
2021 rich_location richloc (line_table, location);
2022 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
2023 &ap, DK_ERROR);
2024 va_end (ap);
2027 /* Same as above, but use location LOC instead of input_location. */
2028 void
2029 error_at (location_t loc, const char *gmsgid, ...)
2031 auto_diagnostic_group d;
2032 va_list ap;
2033 va_start (ap, gmsgid);
2034 rich_location richloc (line_table, loc);
2035 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2036 va_end (ap);
2039 /* Same as above, but use RICH_LOC. */
2041 void
2042 error_at (rich_location *richloc, const char *gmsgid, ...)
2044 gcc_assert (richloc);
2046 auto_diagnostic_group d;
2047 va_list ap;
2048 va_start (ap, gmsgid);
2049 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2050 va_end (ap);
2053 /* "Sorry, not implemented." Use for a language feature which is
2054 required by the relevant specification but not implemented by GCC.
2055 An object file will not be produced. */
2056 void
2057 sorry (const char *gmsgid, ...)
2059 auto_diagnostic_group d;
2060 va_list ap;
2061 va_start (ap, gmsgid);
2062 rich_location richloc (line_table, input_location);
2063 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2064 va_end (ap);
2067 /* Same as above, but use location LOC instead of input_location. */
2068 void
2069 sorry_at (location_t loc, const char *gmsgid, ...)
2071 auto_diagnostic_group d;
2072 va_list ap;
2073 va_start (ap, gmsgid);
2074 rich_location richloc (line_table, loc);
2075 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2076 va_end (ap);
2079 /* Return true if an error or a "sorry" has been seen. Various
2080 processing is disabled after errors. */
2081 bool
2082 seen_error (void)
2084 return errorcount || sorrycount;
2087 /* An error which is severe enough that we make no attempt to
2088 continue. Do not use this for internal consistency checks; that's
2089 internal_error. Use of this function should be rare. */
2090 void
2091 fatal_error (location_t loc, const char *gmsgid, ...)
2093 auto_diagnostic_group d;
2094 va_list ap;
2095 va_start (ap, gmsgid);
2096 rich_location richloc (line_table, loc);
2097 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2098 va_end (ap);
2100 gcc_unreachable ();
2103 /* An internal consistency check has failed. We make no attempt to
2104 continue. */
2105 void
2106 internal_error (const char *gmsgid, ...)
2108 auto_diagnostic_group d;
2109 va_list ap;
2110 va_start (ap, gmsgid);
2111 rich_location richloc (line_table, input_location);
2112 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2113 va_end (ap);
2115 gcc_unreachable ();
2118 /* Like internal_error, but no backtrace will be printed. Used when
2119 the internal error does not happen at the current location, but happened
2120 somewhere else. */
2121 void
2122 internal_error_no_backtrace (const char *gmsgid, ...)
2124 auto_diagnostic_group d;
2125 va_list ap;
2126 va_start (ap, gmsgid);
2127 rich_location richloc (line_table, input_location);
2128 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2129 va_end (ap);
2131 gcc_unreachable ();
2134 /* Special case error functions. Most are implemented in terms of the
2135 above, or should be. */
2137 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2138 runs its second argument through gettext. */
2139 void
2140 fnotice (FILE *file, const char *cmsgid, ...)
2142 va_list ap;
2144 va_start (ap, cmsgid);
2145 vfprintf (file, _(cmsgid), ap);
2146 va_end (ap);
2149 /* Inform the user that an error occurred while trying to report some
2150 other error. This indicates catastrophic internal inconsistencies,
2151 so give up now. But do try to flush out the previous error.
2152 This mustn't use internal_error, that will cause infinite recursion. */
2154 static void
2155 error_recursion (diagnostic_context *context)
2157 if (context->lock < 3)
2158 pp_newline_and_flush (context->printer);
2160 fnotice (stderr,
2161 "internal compiler error: error reporting routines re-entered.\n");
2163 /* Call diagnostic_action_after_output to get the "please submit a bug
2164 report" message. */
2165 diagnostic_action_after_output (context, DK_ICE);
2167 /* Do not use gcc_unreachable here; that goes through internal_error
2168 and therefore would cause infinite recursion. */
2169 real_abort ();
2172 /* Report an internal compiler error in a friendly manner. This is
2173 the function that gets called upon use of abort() in the source
2174 code generally, thanks to a special macro. */
2176 void
2177 fancy_abort (const char *file, int line, const char *function)
2179 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2180 internal_error will crash internally in a way that prevents a
2181 useful message reaching the user.
2182 This can happen with libgccjit in the case of gcc_assert failures
2183 that occur outside of the libgccjit mutex that guards the rest of
2184 gcc's state, including global_dc (when global_dc may not be
2185 initialized yet, or might be in use by another thread).
2186 Handle such cases as gracefully as possible by falling back to a
2187 minimal abort handler that only relies on i18n. */
2188 if (global_dc->printer == NULL)
2190 /* Print the error message. */
2191 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2192 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2193 fputc ('\n', stderr);
2195 /* Attempt to print a backtrace. */
2196 struct backtrace_state *state
2197 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2198 int count = 0;
2199 if (state != NULL)
2200 backtrace_full (state, 2, bt_callback, bt_err_callback,
2201 (void *) &count);
2203 /* We can't call warn_if_plugins or emergency_dump_function as these
2204 rely on GCC state that might not be initialized, or might be in
2205 use by another thread. */
2207 /* Abort the process. */
2208 real_abort ();
2211 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2214 /* class auto_diagnostic_group. */
2216 /* Constructor: "push" this group into global_dc. */
2218 auto_diagnostic_group::auto_diagnostic_group ()
2220 global_dc->diagnostic_group_nesting_depth++;
2223 /* Destructor: "pop" this group from global_dc. */
2225 auto_diagnostic_group::~auto_diagnostic_group ()
2227 if (--global_dc->diagnostic_group_nesting_depth == 0)
2229 /* Handle the case where we've popped the final diagnostic group.
2230 If any diagnostics were emitted, give the context a chance
2231 to do something. */
2232 if (global_dc->diagnostic_group_emission_count > 0)
2234 if (global_dc->end_group_cb)
2235 global_dc->end_group_cb (global_dc);
2237 global_dc->diagnostic_group_emission_count = 0;
2241 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2242 file-based output formats. */
2244 void
2245 diagnostic_output_format_init (diagnostic_context *context,
2246 const char *base_file_name,
2247 enum diagnostics_output_format format)
2249 switch (format)
2251 default:
2252 gcc_unreachable ();
2253 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2254 /* The default; do nothing. */
2255 break;
2257 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2258 diagnostic_output_format_init_json_stderr (context);
2259 break;
2261 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2262 diagnostic_output_format_init_json_file (context, base_file_name);
2263 break;
2265 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2266 diagnostic_output_format_init_sarif_stderr (context);
2267 break;
2269 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2270 diagnostic_output_format_init_sarif_file (context, base_file_name);
2271 break;
2275 /* Implementation of diagnostic_path::num_events vfunc for
2276 simple_diagnostic_path: simply get the number of events in the vec. */
2278 unsigned
2279 simple_diagnostic_path::num_events () const
2281 return m_events.length ();
2284 /* Implementation of diagnostic_path::get_event vfunc for
2285 simple_diagnostic_path: simply return the event in the vec. */
2287 const diagnostic_event &
2288 simple_diagnostic_path::get_event (int idx) const
2290 return *m_events[idx];
2293 /* Add an event to this path at LOC within function FNDECL at
2294 stack depth DEPTH.
2296 Use m_context's printer to format FMT, as the text of the new
2297 event.
2299 Return the id of the new event. */
2301 diagnostic_event_id_t
2302 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2303 const char *fmt, ...)
2305 pretty_printer *pp = m_event_pp;
2306 pp_clear_output_area (pp);
2308 text_info ti;
2309 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2311 va_list ap;
2313 va_start (ap, fmt);
2315 ti.format_spec = _(fmt);
2316 ti.args_ptr = &ap;
2317 ti.err_no = 0;
2318 ti.x_data = NULL;
2319 ti.m_richloc = &rich_loc;
2321 pp_format (pp, &ti);
2322 pp_output_formatted_text (pp);
2324 va_end (ap);
2326 simple_diagnostic_event *new_event
2327 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2328 m_events.safe_push (new_event);
2330 pp_clear_output_area (pp);
2332 return diagnostic_event_id_t (m_events.length () - 1);
2335 /* struct simple_diagnostic_event. */
2337 /* simple_diagnostic_event's ctor. */
2339 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2340 tree fndecl,
2341 int depth,
2342 const char *desc)
2343 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2347 /* simple_diagnostic_event's dtor. */
2349 simple_diagnostic_event::~simple_diagnostic_event ()
2351 free (m_desc);
2354 /* Print PATH by emitting a dummy "note" associated with it. */
2356 DEBUG_FUNCTION
2357 void debug (diagnostic_path *path)
2359 rich_location richloc (line_table, UNKNOWN_LOCATION);
2360 richloc.set_path (path);
2361 inform (&richloc, "debug path");
2364 /* Really call the system 'abort'. This has to go right at the end of
2365 this file, so that there are no functions after it that call abort
2366 and get the system abort instead of our macro. */
2367 #undef abort
2368 static void
2369 real_abort (void)
2371 abort ();
2374 #if CHECKING_P
2376 namespace selftest {
2378 /* Helper function for test_print_escaped_string. */
2380 static void
2381 assert_print_escaped_string (const location &loc, const char *expected_output,
2382 const char *input)
2384 pretty_printer pp;
2385 print_escaped_string (&pp, input);
2386 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2389 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2390 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2392 /* Tests of print_escaped_string. */
2394 static void
2395 test_print_escaped_string ()
2397 /* Empty string. */
2398 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2400 /* Non-empty string. */
2401 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2403 /* Various things that need to be escaped: */
2404 /* Backslash. */
2405 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2406 "before\\after");
2407 /* Tab. */
2408 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2409 "before\tafter");
2410 /* Newline. */
2411 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2412 "before\nafter");
2413 /* Double quote. */
2414 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2415 "before\"after");
2417 /* Non-printable characters: BEL: '\a': 0x07 */
2418 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2419 "before\aafter");
2420 /* Non-printable characters: vertical tab: '\v': 0x0b */
2421 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2422 "before\vafter");
2425 /* Tests of print_parseable_fixits. */
2427 /* Verify that print_parseable_fixits emits the empty string if there
2428 are no fixits. */
2430 static void
2431 test_print_parseable_fixits_none ()
2433 pretty_printer pp;
2434 rich_location richloc (line_table, UNKNOWN_LOCATION);
2436 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2437 ASSERT_STREQ ("", pp_formatted_text (&pp));
2440 /* Verify that print_parseable_fixits does the right thing if there
2441 is an insertion fixit hint. */
2443 static void
2444 test_print_parseable_fixits_insert ()
2446 pretty_printer pp;
2447 rich_location richloc (line_table, UNKNOWN_LOCATION);
2449 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2450 linemap_line_start (line_table, 5, 100);
2451 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2452 location_t where = linemap_position_for_column (line_table, 10);
2453 richloc.add_fixit_insert_before (where, "added content");
2455 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2456 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2457 pp_formatted_text (&pp));
2460 /* Verify that print_parseable_fixits does the right thing if there
2461 is an removal fixit hint. */
2463 static void
2464 test_print_parseable_fixits_remove ()
2466 pretty_printer pp;
2467 rich_location richloc (line_table, UNKNOWN_LOCATION);
2469 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2470 linemap_line_start (line_table, 5, 100);
2471 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2472 source_range where;
2473 where.m_start = linemap_position_for_column (line_table, 10);
2474 where.m_finish = linemap_position_for_column (line_table, 20);
2475 richloc.add_fixit_remove (where);
2477 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2478 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2479 pp_formatted_text (&pp));
2482 /* Verify that print_parseable_fixits does the right thing if there
2483 is an replacement fixit hint. */
2485 static void
2486 test_print_parseable_fixits_replace ()
2488 pretty_printer pp;
2489 rich_location richloc (line_table, UNKNOWN_LOCATION);
2491 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2492 linemap_line_start (line_table, 5, 100);
2493 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2494 source_range where;
2495 where.m_start = linemap_position_for_column (line_table, 10);
2496 where.m_finish = linemap_position_for_column (line_table, 20);
2497 richloc.add_fixit_replace (where, "replacement");
2499 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2500 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2501 pp_formatted_text (&pp));
2504 /* Verify that print_parseable_fixits correctly handles
2505 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2507 static void
2508 test_print_parseable_fixits_bytes_vs_display_columns ()
2510 line_table_test ltt;
2511 rich_location richloc (line_table, UNKNOWN_LOCATION);
2513 /* 1-based byte offsets: 12345677778888999900001234567. */
2514 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2515 /* 1-based display cols: 123456[......7-8.....]9012345. */
2516 const int tabstop = 8;
2518 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2519 const char *const fname = tmp.get_filename ();
2521 linemap_add (line_table, LC_ENTER, false, fname, 0);
2522 linemap_line_start (line_table, 1, 100);
2523 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2524 source_range where;
2525 where.m_start = linemap_position_for_column (line_table, 12);
2526 where.m_finish = linemap_position_for_column (line_table, 17);
2527 richloc.add_fixit_replace (where, "color");
2529 /* Escape fname. */
2530 pretty_printer tmp_pp;
2531 print_escaped_string (&tmp_pp, fname);
2532 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2534 const int buf_len = strlen (escaped_fname) + 100;
2535 char *const expected = XNEWVEC (char, buf_len);
2538 pretty_printer pp;
2539 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2540 tabstop);
2541 snprintf (expected, buf_len,
2542 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2543 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2546 pretty_printer pp;
2547 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2548 tabstop);
2549 snprintf (expected, buf_len,
2550 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2551 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2554 XDELETEVEC (expected);
2555 free (escaped_fname);
2558 /* Verify that
2559 diagnostic_get_location_text (..., SHOW_COLUMN)
2560 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2561 colorization disabled. */
2563 static void
2564 assert_location_text (const char *expected_loc_text,
2565 const char *filename, int line, int column,
2566 bool show_column,
2567 int origin = 1,
2568 enum diagnostics_column_unit column_unit
2569 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2571 test_diagnostic_context dc;
2572 dc.show_column = show_column;
2573 dc.column_unit = column_unit;
2574 dc.column_origin = origin;
2576 expanded_location xloc;
2577 xloc.file = filename;
2578 xloc.line = line;
2579 xloc.column = column;
2580 xloc.data = NULL;
2581 xloc.sysp = false;
2583 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2584 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2585 free (actual_loc_text);
2588 /* Verify that diagnostic_get_location_text works as expected. */
2590 static void
2591 test_diagnostic_get_location_text ()
2593 const char *old_progname = progname;
2594 progname = "PROGNAME";
2595 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2596 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2597 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2598 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2599 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2600 for (int origin = 0; origin != 2; ++origin)
2601 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2602 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2603 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2604 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2606 maybe_line_and_column (INT_MAX, INT_MAX);
2607 maybe_line_and_column (INT_MIN, INT_MIN);
2610 /* In order to test display columns vs byte columns, we need to create a
2611 file for location_get_source_line() to read. */
2613 const char *const content = "smile \xf0\x9f\x98\x82\n";
2614 const int line_bytes = strlen (content) - 1;
2615 const int def_tabstop = 8;
2616 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2617 const int display_width = cpp_display_width (content, line_bytes, policy);
2618 ASSERT_EQ (line_bytes - 2, display_width);
2619 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2620 const char *const fname = tmp.get_filename ();
2621 const int buf_len = strlen (fname) + 16;
2622 char *const expected = XNEWVEC (char, buf_len);
2624 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2625 assert_location_text (expected, fname, 1, line_bytes, true,
2626 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2628 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2629 assert_location_text (expected, fname, 1, line_bytes, true,
2630 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2632 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2633 assert_location_text (expected, fname, 1, line_bytes, true,
2634 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2636 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2637 assert_location_text (expected, fname, 1, line_bytes, true,
2638 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2640 XDELETEVEC (expected);
2644 progname = old_progname;
2647 /* Selftest for num_digits. */
2649 static void
2650 test_num_digits ()
2652 ASSERT_EQ (1, num_digits (0));
2653 ASSERT_EQ (1, num_digits (9));
2654 ASSERT_EQ (2, num_digits (10));
2655 ASSERT_EQ (2, num_digits (99));
2656 ASSERT_EQ (3, num_digits (100));
2657 ASSERT_EQ (3, num_digits (999));
2658 ASSERT_EQ (4, num_digits (1000));
2659 ASSERT_EQ (4, num_digits (9999));
2660 ASSERT_EQ (5, num_digits (10000));
2661 ASSERT_EQ (5, num_digits (99999));
2662 ASSERT_EQ (6, num_digits (100000));
2663 ASSERT_EQ (6, num_digits (999999));
2664 ASSERT_EQ (7, num_digits (1000000));
2665 ASSERT_EQ (7, num_digits (9999999));
2666 ASSERT_EQ (8, num_digits (10000000));
2667 ASSERT_EQ (8, num_digits (99999999));
2670 /* Run all of the selftests within this file. */
2672 void
2673 c_diagnostic_cc_tests ()
2675 test_print_escaped_string ();
2676 test_print_parseable_fixits_none ();
2677 test_print_parseable_fixits_insert ();
2678 test_print_parseable_fixits_remove ();
2679 test_print_parseable_fixits_replace ();
2680 test_print_parseable_fixits_bytes_vs_display_columns ();
2681 test_diagnostic_get_location_text ();
2682 test_num_digits ();
2686 } // namespace selftest
2688 #endif /* #if CHECKING_P */
2690 #if __GNUC__ >= 10
2691 # pragma GCC diagnostic pop
2692 #endif