compiler: don't generate stubs for ambiguous direct interface methods
[official-gcc.git] / gcc / diagnostic.cc
blobf2a82fff46290d2cc56ec8679116de3757e00c0b
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->path_format = DPF_NONE;
194 context->show_path_depths = false;
195 context->show_option_requested = false;
196 context->abort_on_error = false;
197 context->show_column = false;
198 context->pedantic_errors = false;
199 context->permissive = false;
200 context->opt_permissive = 0;
201 context->fatal_errors = false;
202 context->dc_inhibit_warnings = false;
203 context->dc_warn_system_headers = false;
204 context->max_errors = 0;
205 context->internal_error = NULL;
206 diagnostic_starter (context) = default_diagnostic_starter;
207 context->start_span = default_diagnostic_start_span_fn;
208 diagnostic_finalizer (context) = default_diagnostic_finalizer;
209 context->option_enabled = NULL;
210 context->option_state = NULL;
211 context->option_name = NULL;
212 context->get_option_url = NULL;
213 context->last_location = UNKNOWN_LOCATION;
214 context->last_module = 0;
215 context->x_data = NULL;
216 context->lock = 0;
217 context->inhibit_notes_p = false;
218 context->colorize_source_p = false;
219 context->show_labels_p = false;
220 context->show_line_numbers_p = false;
221 context->min_margin_width = 0;
222 context->show_ruler_p = false;
223 context->report_bug = false;
225 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
227 if (!strcmp (var, "fixits-v1"))
228 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
229 else if (!strcmp (var, "fixits-v2"))
230 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
231 /* Silently ignore unrecognized values. */
233 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
234 context->column_origin = 1;
235 context->tabstop = 8;
236 context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
237 context->edit_context_ptr = NULL;
238 context->diagnostic_group_nesting_depth = 0;
239 context->diagnostic_group_emission_count = 0;
240 context->begin_group_cb = NULL;
241 context->end_group_cb = NULL;
242 context->final_cb = default_diagnostic_final_cb;
243 context->includes_seen = NULL;
244 context->m_client_data_hooks = NULL;
247 /* Maybe initialize the color support. We require clients to do this
248 explicitly, since most clients don't want color. When called
249 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
251 void
252 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
254 /* value == -1 is the default value. */
255 if (value < 0)
257 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
258 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
259 otherwise default to -fdiagnostics-color=never, for other
260 values default to that
261 -fdiagnostics-color={never,auto,always}. */
262 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
264 if (!getenv ("GCC_COLORS"))
265 return;
266 value = DIAGNOSTICS_COLOR_AUTO;
268 else
269 value = DIAGNOSTICS_COLOR_DEFAULT;
271 pp_show_color (context->printer)
272 = colorize_init ((diagnostic_color_rule_t) value);
275 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
277 void
278 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
280 /* value == -1 is the default value. */
281 if (value < 0)
283 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
284 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
285 environment, otherwise default to -fdiagnostics-urls=never,
286 for other values default to that
287 -fdiagnostics-urls={never,auto,always}. */
288 if (DIAGNOSTICS_URLS_DEFAULT == -1)
290 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
291 return;
292 value = DIAGNOSTICS_URL_AUTO;
294 else
295 value = DIAGNOSTICS_URLS_DEFAULT;
298 context->printer->url_format
299 = determine_url_format ((diagnostic_url_rule_t) value);
302 /* Create the file_cache, if not already created, and tell it how to
303 translate files on input. */
304 void diagnostic_initialize_input_context (diagnostic_context *context,
305 diagnostic_input_charset_callback ccb,
306 bool should_skip_bom)
308 if (!context->m_file_cache)
309 context->m_file_cache = new file_cache;
310 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
313 /* Do any cleaning up required after the last diagnostic is emitted. */
315 void
316 diagnostic_finish (diagnostic_context *context)
318 if (context->final_cb)
319 context->final_cb (context);
321 diagnostic_file_cache_fini ();
323 XDELETEVEC (context->classify_diagnostic);
324 context->classify_diagnostic = NULL;
326 /* diagnostic_initialize allocates context->printer using XNEW
327 and placement-new. */
328 context->printer->~pretty_printer ();
329 XDELETE (context->printer);
330 context->printer = NULL;
332 if (context->edit_context_ptr)
334 delete context->edit_context_ptr;
335 context->edit_context_ptr = NULL;
338 if (context->includes_seen)
340 delete context->includes_seen;
341 context->includes_seen = nullptr;
344 if (context->m_client_data_hooks)
346 delete context->m_client_data_hooks;
347 context->m_client_data_hooks = NULL;
351 /* Initialize DIAGNOSTIC, where the message MSG has already been
352 translated. */
353 void
354 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
355 va_list *args, rich_location *richloc,
356 diagnostic_t kind)
358 gcc_assert (richloc);
359 diagnostic->message.err_no = errno;
360 diagnostic->message.args_ptr = args;
361 diagnostic->message.format_spec = msg;
362 diagnostic->message.m_richloc = richloc;
363 diagnostic->richloc = richloc;
364 diagnostic->metadata = NULL;
365 diagnostic->kind = kind;
366 diagnostic->option_index = 0;
369 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
370 translated. */
371 void
372 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
373 va_list *args, rich_location *richloc,
374 diagnostic_t kind)
376 gcc_assert (richloc);
377 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
380 static const char *const diagnostic_kind_color[] = {
381 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
382 #include "diagnostic.def"
383 #undef DEFINE_DIAGNOSTIC_KIND
384 NULL
387 /* Get a color name for diagnostics of type KIND
388 Result could be NULL. */
390 const char *
391 diagnostic_get_color_for_kind (diagnostic_t kind)
393 return diagnostic_kind_color[kind];
396 /* Given an expanded_location, convert the column (which is in 1-based bytes)
397 to the requested units, without converting the origin.
398 Return -1 if the column is invalid (<= 0). */
400 static int
401 convert_column_unit (enum diagnostics_column_unit column_unit,
402 int tabstop,
403 expanded_location s)
405 if (s.column <= 0)
406 return -1;
408 switch (column_unit)
410 default:
411 gcc_unreachable ();
413 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
415 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
416 return location_compute_display_column (s, policy);
419 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
420 return s.column;
424 /* Given an expanded_location, convert the column (which is in 1-based bytes)
425 to the requested units and origin. Return -1 if the column is
426 invalid (<= 0). */
428 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
430 int one_based_col
431 = convert_column_unit (context->column_unit, context->tabstop, s);
432 if (one_based_col <= 0)
433 return -1;
434 return one_based_col + (context->column_origin - 1);
437 /* Return a formatted line and column ':%line:%column'. Elided if
438 line == 0 or col < 0. (A column of 0 may be valid due to the
439 -fdiagnostics-column-origin option.)
440 The result is a statically allocated buffer. */
442 static const char *
443 maybe_line_and_column (int line, int col)
445 static char result[32];
447 if (line)
449 size_t l
450 = snprintf (result, sizeof (result),
451 col >= 0 ? ":%d:%d" : ":%d", line, col);
452 gcc_checking_assert (l < sizeof (result));
454 else
455 result[0] = 0;
456 return result;
459 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
460 The caller is responsible for freeing the memory. */
462 static char *
463 diagnostic_get_location_text (diagnostic_context *context,
464 expanded_location s)
466 pretty_printer *pp = context->printer;
467 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
468 const char *locus_ce = colorize_stop (pp_show_color (pp));
469 const char *file = s.file ? s.file : progname;
470 int line = 0;
471 int col = -1;
472 if (strcmp (file, N_("<built-in>")))
474 line = s.line;
475 if (context->show_column)
476 col = diagnostic_converted_column (context, s);
479 const char *line_col = maybe_line_and_column (line, col);
480 return build_message_string ("%s%s%s:%s", locus_cs, file,
481 line_col, locus_ce);
484 static const char *const diagnostic_kind_text[] = {
485 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
486 #include "diagnostic.def"
487 #undef DEFINE_DIAGNOSTIC_KIND
488 "must-not-happen"
491 /* Return a malloc'd string describing a location and the severity of the
492 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
493 freeing the memory. */
494 char *
495 diagnostic_build_prefix (diagnostic_context *context,
496 const diagnostic_info *diagnostic)
498 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
500 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
501 const char *text_cs = "", *text_ce = "";
502 pretty_printer *pp = context->printer;
504 if (diagnostic_kind_color[diagnostic->kind])
506 text_cs = colorize_start (pp_show_color (pp),
507 diagnostic_kind_color[diagnostic->kind]);
508 text_ce = colorize_stop (pp_show_color (pp));
511 expanded_location s = diagnostic_expand_location (diagnostic);
512 char *location_text = diagnostic_get_location_text (context, s);
514 char *result = build_message_string ("%s %s%s%s", location_text,
515 text_cs, text, text_ce);
516 free (location_text);
517 return result;
520 /* Functions at which to stop the backtrace print. It's not
521 particularly helpful to print the callers of these functions. */
523 static const char * const bt_stop[] =
525 "main",
526 "toplev::main",
527 "execute_one_pass",
528 "compile_file",
531 /* A callback function passed to the backtrace_full function. */
533 static int
534 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
535 const char *function)
537 int *pcount = (int *) data;
539 /* If we don't have any useful information, don't print
540 anything. */
541 if (filename == NULL && function == NULL)
542 return 0;
544 /* Skip functions in diagnostic.cc. */
545 if (*pcount == 0
546 && filename != NULL
547 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
548 return 0;
550 /* Print up to 20 functions. We could make this a --param, but
551 since this is only for debugging just use a constant for now. */
552 if (*pcount >= 20)
554 /* Returning a non-zero value stops the backtrace. */
555 return 1;
557 ++*pcount;
559 char *alc = NULL;
560 if (function != NULL)
562 char *str = cplus_demangle_v3 (function,
563 (DMGL_VERBOSE | DMGL_ANSI
564 | DMGL_GNU_V3 | DMGL_PARAMS));
565 if (str != NULL)
567 alc = str;
568 function = str;
571 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
573 size_t len = strlen (bt_stop[i]);
574 if (strncmp (function, bt_stop[i], len) == 0
575 && (function[len] == '\0' || function[len] == '('))
577 if (alc != NULL)
578 free (alc);
579 /* Returning a non-zero value stops the backtrace. */
580 return 1;
585 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
586 (unsigned long) pc,
587 function == NULL ? "???" : function,
588 filename == NULL ? "???" : filename,
589 lineno);
591 if (alc != NULL)
592 free (alc);
594 return 0;
597 /* A callback function passed to the backtrace_full function. This is
598 called if backtrace_full has an error. */
600 static void
601 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
603 if (errnum < 0)
605 /* This means that no debug info was available. Just quietly
606 skip printing backtrace info. */
607 return;
609 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
610 errnum == 0 ? "" : xstrerror (errnum));
613 /* Check if we've met the maximum error limit, and if so fatally exit
614 with a message. CONTEXT is the context to check, and FLUSH
615 indicates whether a diagnostic_finish call is needed. */
617 void
618 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
620 if (!context->max_errors)
621 return;
623 int count = (diagnostic_kind_count (context, DK_ERROR)
624 + diagnostic_kind_count (context, DK_SORRY)
625 + diagnostic_kind_count (context, DK_WERROR));
627 if (count >= context->max_errors)
629 fnotice (stderr,
630 "compilation terminated due to -fmax-errors=%u.\n",
631 context->max_errors);
632 if (flush)
633 diagnostic_finish (context);
634 exit (FATAL_EXIT_CODE);
638 /* Take any action which is expected to happen after the diagnostic
639 is written out. This function does not always return. */
640 void
641 diagnostic_action_after_output (diagnostic_context *context,
642 diagnostic_t diag_kind)
644 switch (diag_kind)
646 case DK_DEBUG:
647 case DK_NOTE:
648 case DK_ANACHRONISM:
649 case DK_WARNING:
650 break;
652 case DK_ERROR:
653 case DK_SORRY:
654 if (context->abort_on_error)
655 real_abort ();
656 if (context->fatal_errors)
658 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
659 diagnostic_finish (context);
660 exit (FATAL_EXIT_CODE);
662 break;
664 case DK_ICE:
665 case DK_ICE_NOBT:
667 struct backtrace_state *state = NULL;
668 if (diag_kind == DK_ICE)
669 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
670 int count = 0;
671 if (state != NULL)
672 backtrace_full (state, 2, bt_callback, bt_err_callback,
673 (void *) &count);
675 if (context->abort_on_error)
676 real_abort ();
678 if (context->report_bug)
679 fnotice (stderr, "Please submit a full bug report, "
680 "with preprocessed source.\n");
681 else
682 fnotice (stderr, "Please submit a full bug report, "
683 "with preprocessed source (by using -freport-bug).\n");
685 if (count > 0)
686 fnotice (stderr, "Please include the complete backtrace "
687 "with any bug report.\n");
688 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
690 exit (ICE_EXIT_CODE);
693 case DK_FATAL:
694 if (context->abort_on_error)
695 real_abort ();
696 diagnostic_finish (context);
697 fnotice (stderr, "compilation terminated.\n");
698 exit (FATAL_EXIT_CODE);
700 default:
701 gcc_unreachable ();
705 /* True if the last module or file in which a diagnostic was reported is
706 different from the current one. */
708 static bool
709 last_module_changed_p (diagnostic_context *context,
710 const line_map_ordinary *map)
712 return context->last_module != map;
715 /* Remember the current module or file as being the last one in which we
716 report a diagnostic. */
718 static void
719 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
721 context->last_module = map;
724 /* Only dump the "In file included from..." stack once for each file. */
726 static bool
727 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
729 /* No include path for main. */
730 if (MAIN_FILE_P (map))
731 return true;
733 /* Always identify C++ modules, at least for now. */
734 auto probe = map;
735 if (linemap_check_ordinary (map)->reason == LC_RENAME)
736 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
737 probe = linemap_included_from_linemap (line_table, map);
738 if (MAP_MODULE_P (probe))
739 return false;
741 if (!context->includes_seen)
742 context->includes_seen = new hash_set<location_t, false, location_hash>;
744 /* Hash the location of the #include directive to better handle files
745 that are included multiple times with different macros defined. */
746 return context->includes_seen->add (linemap_included_from (map));
749 void
750 diagnostic_report_current_module (diagnostic_context *context, location_t where)
752 const line_map_ordinary *map = NULL;
754 if (pp_needs_newline (context->printer))
756 pp_newline (context->printer);
757 pp_needs_newline (context->printer) = false;
760 if (where <= BUILTINS_LOCATION)
761 return;
763 linemap_resolve_location (line_table, where,
764 LRK_MACRO_DEFINITION_LOCATION,
765 &map);
767 if (map && last_module_changed_p (context, map))
769 set_last_module (context, map);
770 if (!includes_seen (context, map))
772 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
773 expanded_location s = {};
776 where = linemap_included_from (map);
777 map = linemap_included_from_linemap (line_table, map);
778 bool is_module = MAP_MODULE_P (map);
779 s.file = LINEMAP_FILE (map);
780 s.line = SOURCE_LINE (map, where);
781 int col = -1;
782 if (first && context->show_column)
784 s.column = SOURCE_COLUMN (map, where);
785 col = diagnostic_converted_column (context, s);
787 const char *line_col = maybe_line_and_column (s.line, col);
788 static const char *const msgs[] =
790 NULL,
791 N_(" from"),
792 N_("In file included from"), /* 2 */
793 N_(" included from"),
794 N_("In module"), /* 4 */
795 N_("of module"),
796 N_("In module imported at"), /* 6 */
797 N_("imported at"),
800 unsigned index = (was_module ? 6 : is_module ? 4
801 : need_inc ? 2 : 0) + !first;
803 pp_verbatim (context->printer, "%s%s %r%s%s%R",
804 first ? "" : was_module ? ", " : ",\n",
805 _(msgs[index]),
806 "locus", s.file, line_col);
807 first = false, need_inc = was_module, was_module = is_module;
809 while (!includes_seen (context, map));
810 pp_verbatim (context->printer, ":");
811 pp_newline (context->printer);
816 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
817 print the path. */
819 void
820 diagnostic_show_any_path (diagnostic_context *context,
821 diagnostic_info *diagnostic)
823 const diagnostic_path *path = diagnostic->richloc->get_path ();
824 if (!path)
825 return;
827 if (context->print_path)
828 context->print_path (context, path);
831 /* class diagnostic_event. */
833 /* struct diagnostic_event::meaning. */
835 void
836 diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
838 bool need_comma = false;
839 pp_character (pp, '{');
840 if (const char *verb_str = maybe_get_verb_str (m_verb))
842 pp_printf (pp, "verb: %qs", verb_str);
843 need_comma = true;
845 if (const char *noun_str = maybe_get_noun_str (m_noun))
847 if (need_comma)
848 pp_string (pp, ", ");
849 pp_printf (pp, "noun: %qs", noun_str);
850 need_comma = true;
852 if (const char *property_str = maybe_get_property_str (m_property))
854 if (need_comma)
855 pp_string (pp, ", ");
856 pp_printf (pp, "property: %qs", property_str);
857 need_comma = true;
859 pp_character (pp, '}');
862 /* Get a string (or NULL) for V suitable for use within a SARIF
863 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
865 const char *
866 diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
868 switch (v)
870 default:
871 gcc_unreachable ();
872 case VERB_unknown:
873 return NULL;
874 case VERB_acquire:
875 return "acquire";
876 case VERB_release:
877 return "release";
878 case VERB_enter:
879 return "enter";
880 case VERB_exit:
881 return "exit";
882 case VERB_call:
883 return "call";
884 case VERB_return:
885 return "return";
886 case VERB_branch:
887 return "branch";
888 case VERB_danger:
889 return "danger";
893 /* Get a string (or NULL) for N suitable for use within a SARIF
894 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
896 const char *
897 diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
899 switch (n)
901 default:
902 gcc_unreachable ();
903 case NOUN_unknown:
904 return NULL;
905 case NOUN_taint:
906 return "taint";
907 case NOUN_sensitive:
908 return "sensitive";
909 case NOUN_function:
910 return "function";
911 case NOUN_lock:
912 return "lock";
913 case NOUN_memory:
914 return "memory";
915 case NOUN_resource:
916 return "resource";
920 /* Get a string (or NULL) for P suitable for use within a SARIF
921 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
923 const char *
924 diagnostic_event::meaning::maybe_get_property_str (enum property p)
926 switch (p)
928 default:
929 gcc_unreachable ();
930 case PROPERTY_unknown:
931 return NULL;
932 case PROPERTY_true:
933 return "true";
934 case PROPERTY_false:
935 return "false";
939 /* class diagnostic_path. */
941 /* Return true if the events in this path involve more than one
942 function, or false if it is purely intraprocedural. */
944 bool
945 diagnostic_path::interprocedural_p () const
947 const unsigned num = num_events ();
948 for (unsigned i = 0; i < num; i++)
950 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
951 return true;
952 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
953 return true;
955 return false;
958 void
959 default_diagnostic_starter (diagnostic_context *context,
960 diagnostic_info *diagnostic)
962 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
963 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
964 diagnostic));
967 void
968 default_diagnostic_start_span_fn (diagnostic_context *context,
969 expanded_location exploc)
971 char *text = diagnostic_get_location_text (context, exploc);
972 pp_string (context->printer, text);
973 free (text);
974 pp_newline (context->printer);
977 void
978 default_diagnostic_finalizer (diagnostic_context *context,
979 diagnostic_info *diagnostic,
980 diagnostic_t)
982 char *saved_prefix = pp_take_prefix (context->printer);
983 pp_set_prefix (context->printer, NULL);
984 pp_newline (context->printer);
985 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
986 pp_set_prefix (context->printer, saved_prefix);
987 pp_flush (context->printer);
990 /* Interface to specify diagnostic kind overrides. Returns the
991 previous setting, or DK_UNSPECIFIED if the parameters are out of
992 range. If OPTION_INDEX is zero, the new setting is for all the
993 diagnostics. */
994 diagnostic_t
995 diagnostic_classify_diagnostic (diagnostic_context *context,
996 int option_index,
997 diagnostic_t new_kind,
998 location_t where)
1000 diagnostic_t old_kind;
1002 if (option_index < 0
1003 || option_index >= context->n_opts
1004 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1005 return DK_UNSPECIFIED;
1007 old_kind = context->classify_diagnostic[option_index];
1009 /* Handle pragmas separately, since we need to keep track of *where*
1010 the pragmas were. */
1011 if (where != UNKNOWN_LOCATION)
1013 int i;
1015 /* Record the command-line status, so we can reset it back on DK_POP. */
1016 if (old_kind == DK_UNSPECIFIED)
1018 old_kind = !context->option_enabled (option_index,
1019 context->lang_mask,
1020 context->option_state)
1021 ? DK_IGNORED : (context->warning_as_error_requested
1022 ? DK_ERROR : DK_WARNING);
1023 context->classify_diagnostic[option_index] = old_kind;
1026 for (i = context->n_classification_history - 1; i >= 0; i --)
1027 if (context->classification_history[i].option == option_index)
1029 old_kind = context->classification_history[i].kind;
1030 break;
1033 i = context->n_classification_history;
1034 context->classification_history =
1035 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1036 * sizeof (diagnostic_classification_change_t));
1037 context->classification_history[i].location = where;
1038 context->classification_history[i].option = option_index;
1039 context->classification_history[i].kind = new_kind;
1040 context->n_classification_history ++;
1042 else
1043 context->classify_diagnostic[option_index] = new_kind;
1045 return old_kind;
1048 /* Save all diagnostic classifications in a stack. */
1049 void
1050 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
1052 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
1053 context->push_list[context->n_push ++] = context->n_classification_history;
1056 /* Restore the topmost classification set off the stack. If the stack
1057 is empty, revert to the state based on command line parameters. */
1058 void
1059 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
1061 int jump_to;
1062 int i;
1064 if (context->n_push)
1065 jump_to = context->push_list [-- context->n_push];
1066 else
1067 jump_to = 0;
1069 i = context->n_classification_history;
1070 context->classification_history =
1071 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1072 * sizeof (diagnostic_classification_change_t));
1073 context->classification_history[i].location = where;
1074 context->classification_history[i].option = jump_to;
1075 context->classification_history[i].kind = DK_POP;
1076 context->n_classification_history ++;
1079 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1080 escaping rules for -fdiagnostics-parseable-fixits. */
1082 static void
1083 print_escaped_string (pretty_printer *pp, const char *text)
1085 gcc_assert (pp);
1086 gcc_assert (text);
1088 pp_character (pp, '"');
1089 for (const char *ch = text; *ch; ch++)
1091 switch (*ch)
1093 case '\\':
1094 /* Escape backslash as two backslashes. */
1095 pp_string (pp, "\\\\");
1096 break;
1097 case '\t':
1098 /* Escape tab as "\t". */
1099 pp_string (pp, "\\t");
1100 break;
1101 case '\n':
1102 /* Escape newline as "\n". */
1103 pp_string (pp, "\\n");
1104 break;
1105 case '"':
1106 /* Escape doublequotes as \". */
1107 pp_string (pp, "\\\"");
1108 break;
1109 default:
1110 if (ISPRINT (*ch))
1111 pp_character (pp, *ch);
1112 else
1113 /* Use octal for non-printable chars. */
1115 unsigned char c = (*ch & 0xff);
1116 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1118 break;
1121 pp_character (pp, '"');
1124 /* Implementation of -fdiagnostics-parseable-fixits and
1125 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1126 Print a machine-parseable version of all fixits in RICHLOC to PP,
1127 using COLUMN_UNIT to express columns.
1128 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1130 static void
1131 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1132 enum diagnostics_column_unit column_unit,
1133 int tabstop)
1135 gcc_assert (pp);
1136 gcc_assert (richloc);
1138 char *saved_prefix = pp_take_prefix (pp);
1139 pp_set_prefix (pp, NULL);
1141 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1143 const fixit_hint *hint = richloc->get_fixit_hint (i);
1144 location_t start_loc = hint->get_start_loc ();
1145 expanded_location start_exploc = expand_location (start_loc);
1146 pp_string (pp, "fix-it:");
1147 print_escaped_string (pp, start_exploc.file);
1148 /* For compatibility with clang, print as a half-open range. */
1149 location_t next_loc = hint->get_next_loc ();
1150 expanded_location next_exploc = expand_location (next_loc);
1151 int start_col
1152 = convert_column_unit (column_unit, tabstop, start_exploc);
1153 int next_col
1154 = convert_column_unit (column_unit, tabstop, next_exploc);
1155 pp_printf (pp, ":{%i:%i-%i:%i}:",
1156 start_exploc.line, start_col,
1157 next_exploc.line, next_col);
1158 print_escaped_string (pp, hint->get_string ());
1159 pp_newline (pp);
1162 pp_set_prefix (pp, saved_prefix);
1165 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1167 static void
1168 get_any_inlining_info (diagnostic_context *context,
1169 diagnostic_info *diagnostic)
1171 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1173 if (context->set_locations_cb)
1174 /* Retrieve the locations into which the expression about to be
1175 diagnosed has been inlined, including those of all the callers
1176 all the way down the inlining stack. */
1177 context->set_locations_cb (context, diagnostic);
1178 else
1180 /* When there's no callback use just the one location provided
1181 by the caller of the diagnostic function. */
1182 location_t loc = diagnostic_location (diagnostic);
1183 ilocs.safe_push (loc);
1184 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1188 /* Update the kind of DIAGNOSTIC based on its location(s), including
1189 any of those in its inlining stack, relative to any
1190 #pragma GCC diagnostic
1191 directives recorded within CONTEXT.
1193 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1194 otherwise. */
1196 static diagnostic_t
1197 update_effective_level_from_pragmas (diagnostic_context *context,
1198 diagnostic_info *diagnostic)
1200 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1202 /* Ignore the diagnostic if all the inlined locations are
1203 in system headers and -Wno-system-headers is in effect. */
1204 diagnostic->kind = DK_IGNORED;
1205 return DK_IGNORED;
1208 if (context->n_classification_history <= 0)
1209 return DK_UNSPECIFIED;
1211 /* Iterate over the locations, checking the diagnostic disposition
1212 for the diagnostic at each. If it's explicitly set as opposed
1213 to unspecified, update the disposition for this instance of
1214 the diagnostic and return it. */
1215 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1217 /* FIXME: Stupid search. Optimize later. */
1218 for (int i = context->n_classification_history - 1; i >= 0; i --)
1220 const diagnostic_classification_change_t &hist
1221 = context->classification_history[i];
1223 location_t pragloc = hist.location;
1224 if (!linemap_location_before_p (line_table, pragloc, loc))
1225 continue;
1227 if (hist.kind == (int) DK_POP)
1229 /* Move on to the next region. */
1230 i = hist.option;
1231 continue;
1234 int option = hist.option;
1235 /* The option 0 is for all the diagnostics. */
1236 if (option == 0 || option == diagnostic->option_index)
1238 diagnostic_t kind = hist.kind;
1239 if (kind != DK_UNSPECIFIED)
1240 diagnostic->kind = kind;
1241 return kind;
1246 return DK_UNSPECIFIED;
1249 /* Generate a URL string describing CWE. The caller is responsible for
1250 freeing the string. */
1252 char *
1253 get_cwe_url (int cwe)
1255 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1258 /* If DIAGNOSTIC has a CWE identifier, print it.
1260 For example, if the diagnostic metadata associates it with CWE-119,
1261 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1262 description of the security issue. */
1264 static void
1265 print_any_cwe (diagnostic_context *context,
1266 const diagnostic_info *diagnostic)
1268 if (diagnostic->metadata == NULL)
1269 return;
1271 int cwe = diagnostic->metadata->get_cwe ();
1272 if (cwe)
1274 pretty_printer *pp = context->printer;
1275 char *saved_prefix = pp_take_prefix (context->printer);
1276 pp_string (pp, " [");
1277 pp_string (pp, colorize_start (pp_show_color (pp),
1278 diagnostic_kind_color[diagnostic->kind]));
1279 if (pp->url_format != URL_FORMAT_NONE)
1281 char *cwe_url = get_cwe_url (cwe);
1282 pp_begin_url (pp, cwe_url);
1283 free (cwe_url);
1285 pp_printf (pp, "CWE-%i", cwe);
1286 pp_set_prefix (context->printer, saved_prefix);
1287 if (pp->url_format != URL_FORMAT_NONE)
1288 pp_end_url (pp);
1289 pp_string (pp, colorize_stop (pp_show_color (pp)));
1290 pp_character (pp, ']');
1294 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1295 printer, e.g. " [-Werror=uninitialized]".
1296 Subroutine of diagnostic_report_diagnostic. */
1298 static void
1299 print_option_information (diagnostic_context *context,
1300 const diagnostic_info *diagnostic,
1301 diagnostic_t orig_diag_kind)
1303 char *option_text;
1305 option_text = context->option_name (context, diagnostic->option_index,
1306 orig_diag_kind, diagnostic->kind);
1308 if (option_text)
1310 char *option_url = NULL;
1311 if (context->get_option_url
1312 && context->printer->url_format != URL_FORMAT_NONE)
1313 option_url = context->get_option_url (context,
1314 diagnostic->option_index);
1315 pretty_printer *pp = context->printer;
1316 pp_string (pp, " [");
1317 pp_string (pp, colorize_start (pp_show_color (pp),
1318 diagnostic_kind_color[diagnostic->kind]));
1319 if (option_url)
1320 pp_begin_url (pp, option_url);
1321 pp_string (pp, option_text);
1322 if (option_url)
1324 pp_end_url (pp);
1325 free (option_url);
1327 pp_string (pp, colorize_stop (pp_show_color (pp)));
1328 pp_character (pp, ']');
1329 free (option_text);
1333 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1334 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1336 static bool
1337 diagnostic_enabled (diagnostic_context *context,
1338 diagnostic_info *diagnostic)
1340 /* Update the inlining stack for this diagnostic. */
1341 get_any_inlining_info (context, diagnostic);
1343 /* Diagnostics with no option or -fpermissive are always enabled. */
1344 if (!diagnostic->option_index
1345 || diagnostic->option_index == permissive_error_option (context))
1346 return true;
1348 /* This tests if the user provided the appropriate -Wfoo or
1349 -Wno-foo option. */
1350 if (! context->option_enabled (diagnostic->option_index,
1351 context->lang_mask,
1352 context->option_state))
1353 return false;
1355 /* This tests for #pragma diagnostic changes. */
1356 diagnostic_t diag_class
1357 = update_effective_level_from_pragmas (context, diagnostic);
1359 /* This tests if the user provided the appropriate -Werror=foo
1360 option. */
1361 if (diag_class == DK_UNSPECIFIED
1362 && (context->classify_diagnostic[diagnostic->option_index]
1363 != DK_UNSPECIFIED))
1364 diagnostic->kind
1365 = context->classify_diagnostic[diagnostic->option_index];
1367 /* This allows for future extensions, like temporarily disabling
1368 warnings for ranges of source code. */
1369 if (diagnostic->kind == DK_IGNORED)
1370 return false;
1372 return true;
1375 /* Returns whether warning OPT is enabled at LOC. */
1377 bool
1378 warning_enabled_at (location_t loc, int opt)
1380 if (!diagnostic_report_warnings_p (global_dc, loc))
1381 return false;
1383 rich_location richloc (line_table, loc);
1384 diagnostic_info diagnostic = {};
1385 diagnostic.option_index = opt;
1386 diagnostic.richloc = &richloc;
1387 diagnostic.message.m_richloc = &richloc;
1388 diagnostic.kind = DK_WARNING;
1389 return diagnostic_enabled (global_dc, &diagnostic);
1392 /* Report a diagnostic message (an error or a warning) as specified by
1393 DC. This function is *the* subroutine in terms of which front-ends
1394 should implement their specific diagnostic handling modules. The
1395 front-end independent format specifiers are exactly those described
1396 in the documentation of output_format.
1397 Return true if a diagnostic was printed, false otherwise. */
1399 bool
1400 diagnostic_report_diagnostic (diagnostic_context *context,
1401 diagnostic_info *diagnostic)
1403 location_t location = diagnostic_location (diagnostic);
1404 diagnostic_t orig_diag_kind = diagnostic->kind;
1406 /* Give preference to being able to inhibit warnings, before they
1407 get reclassified to something else. */
1408 bool report_warning_p = true;
1409 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1411 if (context->dc_inhibit_warnings)
1412 return false;
1413 /* Remember the result of the overall system header warning setting
1414 but proceed to also check the inlining context. */
1415 report_warning_p = diagnostic_report_warnings_p (context, location);
1416 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1417 return false;
1420 if (diagnostic->kind == DK_PEDWARN)
1422 diagnostic->kind = pedantic_warning_kind (context);
1423 /* We do this to avoid giving the message for -pedantic-errors. */
1424 orig_diag_kind = diagnostic->kind;
1427 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1428 return false;
1430 if (context->lock > 0)
1432 /* If we're reporting an ICE in the middle of some other error,
1433 try to flush out the previous error, then let this one
1434 through. Don't do this more than once. */
1435 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1436 && context->lock == 1)
1437 pp_newline_and_flush (context->printer);
1438 else
1439 error_recursion (context);
1442 /* If the user requested that warnings be treated as errors, so be
1443 it. Note that we do this before the next block so that
1444 individual warnings can be overridden back to warnings with
1445 -Wno-error=*. */
1446 if (context->warning_as_error_requested
1447 && diagnostic->kind == DK_WARNING)
1448 diagnostic->kind = DK_ERROR;
1450 diagnostic->message.x_data = &diagnostic->x_data;
1452 /* Check to see if the diagnostic is enabled at the location and
1453 not disabled by #pragma GCC diagnostic anywhere along the inlining
1454 stack. . */
1455 if (!diagnostic_enabled (context, diagnostic))
1456 return false;
1458 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1459 /* Bail if the warning is not to be reported because all locations
1460 in the inlining stack (if there is one) are in system headers. */
1461 return false;
1463 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1464 diagnostic_check_max_errors (context);
1466 context->lock++;
1468 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1470 /* When not checking, ICEs are converted to fatal errors when an
1471 error has already occurred. This is counteracted by
1472 abort_on_error. */
1473 if (!CHECKING_P
1474 && (diagnostic_kind_count (context, DK_ERROR) > 0
1475 || diagnostic_kind_count (context, DK_SORRY) > 0)
1476 && !context->abort_on_error)
1478 expanded_location s
1479 = expand_location (diagnostic_location (diagnostic));
1480 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1481 s.file, s.line);
1482 exit (ICE_EXIT_CODE);
1484 if (context->internal_error)
1485 (*context->internal_error) (context,
1486 diagnostic->message.format_spec,
1487 diagnostic->message.args_ptr);
1489 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1490 ++diagnostic_kind_count (context, DK_WERROR);
1491 else
1492 ++diagnostic_kind_count (context, diagnostic->kind);
1494 /* Is this the initial diagnostic within the stack of groups? */
1495 if (context->diagnostic_group_emission_count == 0)
1497 if (context->begin_group_cb)
1498 context->begin_group_cb (context);
1500 context->diagnostic_group_emission_count++;
1502 pp_format (context->printer, &diagnostic->message);
1503 (*diagnostic_starter (context)) (context, diagnostic);
1504 pp_output_formatted_text (context->printer);
1505 if (context->show_cwe)
1506 print_any_cwe (context, diagnostic);
1507 if (context->show_option_requested)
1508 print_option_information (context, diagnostic, orig_diag_kind);
1509 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1510 switch (context->extra_output_kind)
1512 default:
1513 break;
1514 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1515 print_parseable_fixits (context->printer, diagnostic->richloc,
1516 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1517 context->tabstop);
1518 pp_flush (context->printer);
1519 break;
1520 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1521 print_parseable_fixits (context->printer, diagnostic->richloc,
1522 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1523 context->tabstop);
1524 pp_flush (context->printer);
1525 break;
1527 diagnostic_action_after_output (context, diagnostic->kind);
1528 diagnostic->x_data = NULL;
1530 if (context->edit_context_ptr)
1531 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1532 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1534 context->lock--;
1536 diagnostic_show_any_path (context, diagnostic);
1538 return true;
1541 /* Get the number of digits in the decimal representation of VALUE. */
1544 num_digits (int value)
1546 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1547 using floating point. */
1548 gcc_assert (value >= 0);
1550 if (value == 0)
1551 return 1;
1553 int digits = 0;
1554 while (value > 0)
1556 digits++;
1557 value /= 10;
1559 return digits;
1562 /* Given a partial pathname as input, return another pathname that
1563 shares no directory elements with the pathname of __FILE__. This
1564 is used by fancy_abort() to print `internal compiler error in expr.cc'
1565 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1567 const char *
1568 trim_filename (const char *name)
1570 static const char this_file[] = __FILE__;
1571 const char *p = name, *q = this_file;
1573 /* First skip any "../" in each filename. This allows us to give a proper
1574 reference to a file in a subdirectory. */
1575 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1576 p += 3;
1578 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1579 q += 3;
1581 /* Now skip any parts the two filenames have in common. */
1582 while (*p == *q && *p != 0 && *q != 0)
1583 p++, q++;
1585 /* Now go backwards until the previous directory separator. */
1586 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1587 p--;
1589 return p;
1592 /* Standard error reporting routines in increasing order of severity.
1593 All of these take arguments like printf. */
1595 /* Text to be emitted verbatim to the error message stream; this
1596 produces no prefix and disables line-wrapping. Use rarely. */
1597 void
1598 verbatim (const char *gmsgid, ...)
1600 text_info text;
1601 va_list ap;
1603 va_start (ap, gmsgid);
1604 text.err_no = errno;
1605 text.args_ptr = &ap;
1606 text.format_spec = _(gmsgid);
1607 text.x_data = NULL;
1608 pp_format_verbatim (global_dc->printer, &text);
1609 pp_newline_and_flush (global_dc->printer);
1610 va_end (ap);
1613 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1614 void
1615 diagnostic_append_note (diagnostic_context *context,
1616 location_t location,
1617 const char * gmsgid, ...)
1619 diagnostic_info diagnostic;
1620 va_list ap;
1621 rich_location richloc (line_table, location);
1623 va_start (ap, gmsgid);
1624 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1625 if (context->inhibit_notes_p)
1627 va_end (ap);
1628 return;
1630 char *saved_prefix = pp_take_prefix (context->printer);
1631 pp_set_prefix (context->printer,
1632 diagnostic_build_prefix (context, &diagnostic));
1633 pp_format (context->printer, &diagnostic.message);
1634 pp_output_formatted_text (context->printer);
1635 pp_destroy_prefix (context->printer);
1636 pp_set_prefix (context->printer, saved_prefix);
1637 pp_newline (context->printer);
1638 diagnostic_show_locus (context, &richloc, DK_NOTE);
1639 va_end (ap);
1642 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1643 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1644 and internal_error_no_backtrace, as documented and defined below. */
1645 static bool
1646 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1647 int opt, const char *gmsgid,
1648 va_list *ap, diagnostic_t kind)
1650 diagnostic_info diagnostic;
1651 if (kind == DK_PERMERROR)
1653 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1654 permissive_error_kind (global_dc));
1655 diagnostic.option_index = permissive_error_option (global_dc);
1657 else
1659 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1660 if (kind == DK_WARNING || kind == DK_PEDWARN)
1661 diagnostic.option_index = opt;
1663 diagnostic.metadata = metadata;
1664 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1667 /* Implement inform_n, warning_n, and error_n, as documented and
1668 defined below. */
1669 static bool
1670 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1671 int opt, unsigned HOST_WIDE_INT n,
1672 const char *singular_gmsgid,
1673 const char *plural_gmsgid,
1674 va_list *ap, diagnostic_t kind)
1676 diagnostic_info diagnostic;
1677 unsigned long gtn;
1679 if (sizeof n <= sizeof gtn)
1680 gtn = n;
1681 else
1682 /* Use the largest number ngettext can handle, otherwise
1683 preserve the six least significant decimal digits for
1684 languages where the plural form depends on them. */
1685 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1687 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1688 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1689 if (kind == DK_WARNING)
1690 diagnostic.option_index = opt;
1691 diagnostic.metadata = metadata;
1692 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1695 /* Wrapper around diagnostic_impl taking a variable argument list. */
1697 bool
1698 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1699 const char *gmsgid, ...)
1701 auto_diagnostic_group d;
1702 va_list ap;
1703 va_start (ap, gmsgid);
1704 rich_location richloc (line_table, location);
1705 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1706 va_end (ap);
1707 return ret;
1710 /* As above, but for rich_location *. */
1712 bool
1713 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1714 const char *gmsgid, ...)
1716 auto_diagnostic_group d;
1717 va_list ap;
1718 va_start (ap, gmsgid);
1719 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1720 va_end (ap);
1721 return ret;
1724 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1726 bool
1727 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1728 const char *gmsgid, va_list *ap)
1730 rich_location richloc (line_table, location);
1731 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1734 /* An informative note at LOCATION. Use this for additional details on an error
1735 message. */
1736 void
1737 inform (location_t location, const char *gmsgid, ...)
1739 auto_diagnostic_group d;
1740 va_list ap;
1741 va_start (ap, gmsgid);
1742 rich_location richloc (line_table, location);
1743 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1744 va_end (ap);
1747 /* Same as "inform" above, but at RICHLOC. */
1748 void
1749 inform (rich_location *richloc, const char *gmsgid, ...)
1751 gcc_assert (richloc);
1753 auto_diagnostic_group d;
1754 va_list ap;
1755 va_start (ap, gmsgid);
1756 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1757 va_end (ap);
1760 /* An informative note at LOCATION. Use this for additional details on an
1761 error message. */
1762 void
1763 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1764 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1766 va_list ap;
1767 va_start (ap, plural_gmsgid);
1768 auto_diagnostic_group d;
1769 rich_location richloc (line_table, location);
1770 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1771 &ap, DK_NOTE);
1772 va_end (ap);
1775 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1776 to the relevant language specification but is likely to be buggy anyway.
1777 Returns true if the warning was printed, false if it was inhibited. */
1778 bool
1779 warning (int opt, const char *gmsgid, ...)
1781 auto_diagnostic_group d;
1782 va_list ap;
1783 va_start (ap, gmsgid);
1784 rich_location richloc (line_table, input_location);
1785 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1786 va_end (ap);
1787 return ret;
1790 /* A warning at LOCATION. Use this for code which is correct according to the
1791 relevant language specification but is likely to be buggy anyway.
1792 Returns true if the warning was printed, false if it was inhibited. */
1794 bool
1795 warning_at (location_t location, int opt, const char *gmsgid, ...)
1797 auto_diagnostic_group d;
1798 va_list ap;
1799 va_start (ap, gmsgid);
1800 rich_location richloc (line_table, location);
1801 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1802 va_end (ap);
1803 return ret;
1806 /* Same as "warning at" above, but using RICHLOC. */
1808 bool
1809 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1811 gcc_assert (richloc);
1813 auto_diagnostic_group d;
1814 va_list ap;
1815 va_start (ap, gmsgid);
1816 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1817 va_end (ap);
1818 return ret;
1821 /* Same as "warning at" above, but using METADATA. */
1823 bool
1824 warning_meta (rich_location *richloc,
1825 const diagnostic_metadata &metadata,
1826 int opt, const char *gmsgid, ...)
1828 gcc_assert (richloc);
1830 auto_diagnostic_group d;
1831 va_list ap;
1832 va_start (ap, gmsgid);
1833 bool ret
1834 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1835 DK_WARNING);
1836 va_end (ap);
1837 return ret;
1840 /* Same as warning_n plural variant below, but using RICHLOC. */
1842 bool
1843 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1844 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1846 gcc_assert (richloc);
1848 auto_diagnostic_group d;
1849 va_list ap;
1850 va_start (ap, plural_gmsgid);
1851 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1852 singular_gmsgid, plural_gmsgid,
1853 &ap, DK_WARNING);
1854 va_end (ap);
1855 return ret;
1858 /* A warning at LOCATION. Use this for code which is correct according to the
1859 relevant language specification but is likely to be buggy anyway.
1860 Returns true if the warning was printed, false if it was inhibited. */
1862 bool
1863 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1864 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1866 auto_diagnostic_group d;
1867 va_list ap;
1868 va_start (ap, plural_gmsgid);
1869 rich_location richloc (line_table, location);
1870 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1871 singular_gmsgid, plural_gmsgid,
1872 &ap, DK_WARNING);
1873 va_end (ap);
1874 return ret;
1877 /* A "pedantic" warning at LOCATION: issues a warning unless
1878 -pedantic-errors was given on the command line, in which case it
1879 issues an error. Use this for diagnostics required by the relevant
1880 language standard, if you have chosen not to make them errors.
1882 Note that these diagnostics are issued independent of the setting
1883 of the -Wpedantic command-line switch. To get a warning enabled
1884 only with that switch, use either "if (pedantic) pedwarn
1885 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1886 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1888 Returns true if the warning was printed, false if it was inhibited. */
1890 bool
1891 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1893 auto_diagnostic_group d;
1894 va_list ap;
1895 va_start (ap, gmsgid);
1896 rich_location richloc (line_table, location);
1897 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1898 va_end (ap);
1899 return ret;
1902 /* Same as pedwarn above, but using RICHLOC. */
1904 bool
1905 pedwarn (rich_location *richloc, 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 = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1913 va_end (ap);
1914 return ret;
1917 /* A "permissive" error at LOCATION: issues an error unless
1918 -fpermissive was given on the command line, in which case it issues
1919 a warning. Use this for things that really should be errors but we
1920 want to support legacy code.
1922 Returns true if the warning was printed, false if it was inhibited. */
1924 bool
1925 permerror (location_t location, const char *gmsgid, ...)
1927 auto_diagnostic_group d;
1928 va_list ap;
1929 va_start (ap, gmsgid);
1930 rich_location richloc (line_table, location);
1931 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1932 va_end (ap);
1933 return ret;
1936 /* Same as "permerror" above, but at RICHLOC. */
1938 bool
1939 permerror (rich_location *richloc, const char *gmsgid, ...)
1941 gcc_assert (richloc);
1943 auto_diagnostic_group d;
1944 va_list ap;
1945 va_start (ap, gmsgid);
1946 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1947 va_end (ap);
1948 return ret;
1951 /* A hard error: the code is definitely ill-formed, and an object file
1952 will not be produced. */
1953 void
1954 error (const char *gmsgid, ...)
1956 auto_diagnostic_group d;
1957 va_list ap;
1958 va_start (ap, gmsgid);
1959 rich_location richloc (line_table, input_location);
1960 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1961 va_end (ap);
1964 /* A hard error: the code is definitely ill-formed, and an object file
1965 will not be produced. */
1966 void
1967 error_n (location_t location, unsigned HOST_WIDE_INT n,
1968 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1970 auto_diagnostic_group d;
1971 va_list ap;
1972 va_start (ap, plural_gmsgid);
1973 rich_location richloc (line_table, location);
1974 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1975 &ap, DK_ERROR);
1976 va_end (ap);
1979 /* Same as above, but use location LOC instead of input_location. */
1980 void
1981 error_at (location_t loc, const char *gmsgid, ...)
1983 auto_diagnostic_group d;
1984 va_list ap;
1985 va_start (ap, gmsgid);
1986 rich_location richloc (line_table, loc);
1987 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1988 va_end (ap);
1991 /* Same as above, but use RICH_LOC. */
1993 void
1994 error_at (rich_location *richloc, const char *gmsgid, ...)
1996 gcc_assert (richloc);
1998 auto_diagnostic_group d;
1999 va_list ap;
2000 va_start (ap, gmsgid);
2001 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
2002 va_end (ap);
2005 /* "Sorry, not implemented." Use for a language feature which is
2006 required by the relevant specification but not implemented by GCC.
2007 An object file will not be produced. */
2008 void
2009 sorry (const char *gmsgid, ...)
2011 auto_diagnostic_group d;
2012 va_list ap;
2013 va_start (ap, gmsgid);
2014 rich_location richloc (line_table, input_location);
2015 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2016 va_end (ap);
2019 /* Same as above, but use location LOC instead of input_location. */
2020 void
2021 sorry_at (location_t loc, const char *gmsgid, ...)
2023 auto_diagnostic_group d;
2024 va_list ap;
2025 va_start (ap, gmsgid);
2026 rich_location richloc (line_table, loc);
2027 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
2028 va_end (ap);
2031 /* Return true if an error or a "sorry" has been seen. Various
2032 processing is disabled after errors. */
2033 bool
2034 seen_error (void)
2036 return errorcount || sorrycount;
2039 /* An error which is severe enough that we make no attempt to
2040 continue. Do not use this for internal consistency checks; that's
2041 internal_error. Use of this function should be rare. */
2042 void
2043 fatal_error (location_t loc, const char *gmsgid, ...)
2045 auto_diagnostic_group d;
2046 va_list ap;
2047 va_start (ap, gmsgid);
2048 rich_location richloc (line_table, loc);
2049 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
2050 va_end (ap);
2052 gcc_unreachable ();
2055 /* An internal consistency check has failed. We make no attempt to
2056 continue. */
2057 void
2058 internal_error (const char *gmsgid, ...)
2060 auto_diagnostic_group d;
2061 va_list ap;
2062 va_start (ap, gmsgid);
2063 rich_location richloc (line_table, input_location);
2064 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
2065 va_end (ap);
2067 gcc_unreachable ();
2070 /* Like internal_error, but no backtrace will be printed. Used when
2071 the internal error does not happen at the current location, but happened
2072 somewhere else. */
2073 void
2074 internal_error_no_backtrace (const char *gmsgid, ...)
2076 auto_diagnostic_group d;
2077 va_list ap;
2078 va_start (ap, gmsgid);
2079 rich_location richloc (line_table, input_location);
2080 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
2081 va_end (ap);
2083 gcc_unreachable ();
2086 /* Special case error functions. Most are implemented in terms of the
2087 above, or should be. */
2089 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2090 runs its second argument through gettext. */
2091 void
2092 fnotice (FILE *file, const char *cmsgid, ...)
2094 va_list ap;
2096 va_start (ap, cmsgid);
2097 vfprintf (file, _(cmsgid), ap);
2098 va_end (ap);
2101 /* Inform the user that an error occurred while trying to report some
2102 other error. This indicates catastrophic internal inconsistencies,
2103 so give up now. But do try to flush out the previous error.
2104 This mustn't use internal_error, that will cause infinite recursion. */
2106 static void
2107 error_recursion (diagnostic_context *context)
2109 if (context->lock < 3)
2110 pp_newline_and_flush (context->printer);
2112 fnotice (stderr,
2113 "internal compiler error: error reporting routines re-entered.\n");
2115 /* Call diagnostic_action_after_output to get the "please submit a bug
2116 report" message. */
2117 diagnostic_action_after_output (context, DK_ICE);
2119 /* Do not use gcc_unreachable here; that goes through internal_error
2120 and therefore would cause infinite recursion. */
2121 real_abort ();
2124 /* Report an internal compiler error in a friendly manner. This is
2125 the function that gets called upon use of abort() in the source
2126 code generally, thanks to a special macro. */
2128 void
2129 fancy_abort (const char *file, int line, const char *function)
2131 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2132 internal_error will crash internally in a way that prevents a
2133 useful message reaching the user.
2134 This can happen with libgccjit in the case of gcc_assert failures
2135 that occur outside of the libgccjit mutex that guards the rest of
2136 gcc's state, including global_dc (when global_dc may not be
2137 initialized yet, or might be in use by another thread).
2138 Handle such cases as gracefully as possible by falling back to a
2139 minimal abort handler that only relies on i18n. */
2140 if (global_dc->printer == NULL)
2142 /* Print the error message. */
2143 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2144 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2145 fputc ('\n', stderr);
2147 /* Attempt to print a backtrace. */
2148 struct backtrace_state *state
2149 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2150 int count = 0;
2151 if (state != NULL)
2152 backtrace_full (state, 2, bt_callback, bt_err_callback,
2153 (void *) &count);
2155 /* We can't call warn_if_plugins or emergency_dump_function as these
2156 rely on GCC state that might not be initialized, or might be in
2157 use by another thread. */
2159 /* Abort the process. */
2160 real_abort ();
2163 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2166 /* class auto_diagnostic_group. */
2168 /* Constructor: "push" this group into global_dc. */
2170 auto_diagnostic_group::auto_diagnostic_group ()
2172 global_dc->diagnostic_group_nesting_depth++;
2175 /* Destructor: "pop" this group from global_dc. */
2177 auto_diagnostic_group::~auto_diagnostic_group ()
2179 if (--global_dc->diagnostic_group_nesting_depth == 0)
2181 /* Handle the case where we've popped the final diagnostic group.
2182 If any diagnostics were emitted, give the context a chance
2183 to do something. */
2184 if (global_dc->diagnostic_group_emission_count > 0)
2186 if (global_dc->end_group_cb)
2187 global_dc->end_group_cb (global_dc);
2189 global_dc->diagnostic_group_emission_count = 0;
2193 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2194 file-based output formats. */
2196 void
2197 diagnostic_output_format_init (diagnostic_context *context,
2198 const char *base_file_name,
2199 enum diagnostics_output_format format)
2201 switch (format)
2203 default:
2204 gcc_unreachable ();
2205 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2206 /* The default; do nothing. */
2207 break;
2209 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2210 diagnostic_output_format_init_json_stderr (context);
2211 break;
2213 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2214 diagnostic_output_format_init_json_file (context, base_file_name);
2215 break;
2217 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2218 diagnostic_output_format_init_sarif_stderr (context);
2219 break;
2221 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2222 diagnostic_output_format_init_sarif_file (context, base_file_name);
2223 break;
2227 /* Implementation of diagnostic_path::num_events vfunc for
2228 simple_diagnostic_path: simply get the number of events in the vec. */
2230 unsigned
2231 simple_diagnostic_path::num_events () const
2233 return m_events.length ();
2236 /* Implementation of diagnostic_path::get_event vfunc for
2237 simple_diagnostic_path: simply return the event in the vec. */
2239 const diagnostic_event &
2240 simple_diagnostic_path::get_event (int idx) const
2242 return *m_events[idx];
2245 /* Add an event to this path at LOC within function FNDECL at
2246 stack depth DEPTH.
2248 Use m_context's printer to format FMT, as the text of the new
2249 event.
2251 Return the id of the new event. */
2253 diagnostic_event_id_t
2254 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2255 const char *fmt, ...)
2257 pretty_printer *pp = m_event_pp;
2258 pp_clear_output_area (pp);
2260 text_info ti;
2261 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2263 va_list ap;
2265 va_start (ap, fmt);
2267 ti.format_spec = _(fmt);
2268 ti.args_ptr = &ap;
2269 ti.err_no = 0;
2270 ti.x_data = NULL;
2271 ti.m_richloc = &rich_loc;
2273 pp_format (pp, &ti);
2274 pp_output_formatted_text (pp);
2276 va_end (ap);
2278 simple_diagnostic_event *new_event
2279 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2280 m_events.safe_push (new_event);
2282 pp_clear_output_area (pp);
2284 return diagnostic_event_id_t (m_events.length () - 1);
2287 /* struct simple_diagnostic_event. */
2289 /* simple_diagnostic_event's ctor. */
2291 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2292 tree fndecl,
2293 int depth,
2294 const char *desc)
2295 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2299 /* simple_diagnostic_event's dtor. */
2301 simple_diagnostic_event::~simple_diagnostic_event ()
2303 free (m_desc);
2306 /* Print PATH by emitting a dummy "note" associated with it. */
2308 DEBUG_FUNCTION
2309 void debug (diagnostic_path *path)
2311 rich_location richloc (line_table, UNKNOWN_LOCATION);
2312 richloc.set_path (path);
2313 inform (&richloc, "debug path");
2316 /* Really call the system 'abort'. This has to go right at the end of
2317 this file, so that there are no functions after it that call abort
2318 and get the system abort instead of our macro. */
2319 #undef abort
2320 static void
2321 real_abort (void)
2323 abort ();
2326 #if CHECKING_P
2328 namespace selftest {
2330 /* Helper function for test_print_escaped_string. */
2332 static void
2333 assert_print_escaped_string (const location &loc, const char *expected_output,
2334 const char *input)
2336 pretty_printer pp;
2337 print_escaped_string (&pp, input);
2338 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2341 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2342 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2344 /* Tests of print_escaped_string. */
2346 static void
2347 test_print_escaped_string ()
2349 /* Empty string. */
2350 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2352 /* Non-empty string. */
2353 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2355 /* Various things that need to be escaped: */
2356 /* Backslash. */
2357 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2358 "before\\after");
2359 /* Tab. */
2360 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2361 "before\tafter");
2362 /* Newline. */
2363 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2364 "before\nafter");
2365 /* Double quote. */
2366 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2367 "before\"after");
2369 /* Non-printable characters: BEL: '\a': 0x07 */
2370 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2371 "before\aafter");
2372 /* Non-printable characters: vertical tab: '\v': 0x0b */
2373 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2374 "before\vafter");
2377 /* Tests of print_parseable_fixits. */
2379 /* Verify that print_parseable_fixits emits the empty string if there
2380 are no fixits. */
2382 static void
2383 test_print_parseable_fixits_none ()
2385 pretty_printer pp;
2386 rich_location richloc (line_table, UNKNOWN_LOCATION);
2388 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2389 ASSERT_STREQ ("", pp_formatted_text (&pp));
2392 /* Verify that print_parseable_fixits does the right thing if there
2393 is an insertion fixit hint. */
2395 static void
2396 test_print_parseable_fixits_insert ()
2398 pretty_printer pp;
2399 rich_location richloc (line_table, UNKNOWN_LOCATION);
2401 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2402 linemap_line_start (line_table, 5, 100);
2403 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2404 location_t where = linemap_position_for_column (line_table, 10);
2405 richloc.add_fixit_insert_before (where, "added content");
2407 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2408 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2409 pp_formatted_text (&pp));
2412 /* Verify that print_parseable_fixits does the right thing if there
2413 is an removal fixit hint. */
2415 static void
2416 test_print_parseable_fixits_remove ()
2418 pretty_printer pp;
2419 rich_location richloc (line_table, UNKNOWN_LOCATION);
2421 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2422 linemap_line_start (line_table, 5, 100);
2423 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2424 source_range where;
2425 where.m_start = linemap_position_for_column (line_table, 10);
2426 where.m_finish = linemap_position_for_column (line_table, 20);
2427 richloc.add_fixit_remove (where);
2429 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2430 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2431 pp_formatted_text (&pp));
2434 /* Verify that print_parseable_fixits does the right thing if there
2435 is an replacement fixit hint. */
2437 static void
2438 test_print_parseable_fixits_replace ()
2440 pretty_printer pp;
2441 rich_location richloc (line_table, UNKNOWN_LOCATION);
2443 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2444 linemap_line_start (line_table, 5, 100);
2445 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2446 source_range where;
2447 where.m_start = linemap_position_for_column (line_table, 10);
2448 where.m_finish = linemap_position_for_column (line_table, 20);
2449 richloc.add_fixit_replace (where, "replacement");
2451 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2452 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2453 pp_formatted_text (&pp));
2456 /* Verify that print_parseable_fixits correctly handles
2457 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2459 static void
2460 test_print_parseable_fixits_bytes_vs_display_columns ()
2462 line_table_test ltt;
2463 rich_location richloc (line_table, UNKNOWN_LOCATION);
2465 /* 1-based byte offsets: 12345677778888999900001234567. */
2466 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2467 /* 1-based display cols: 123456[......7-8.....]9012345. */
2468 const int tabstop = 8;
2470 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2471 const char *const fname = tmp.get_filename ();
2473 linemap_add (line_table, LC_ENTER, false, fname, 0);
2474 linemap_line_start (line_table, 1, 100);
2475 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2476 source_range where;
2477 where.m_start = linemap_position_for_column (line_table, 12);
2478 where.m_finish = linemap_position_for_column (line_table, 17);
2479 richloc.add_fixit_replace (where, "color");
2481 /* Escape fname. */
2482 pretty_printer tmp_pp;
2483 print_escaped_string (&tmp_pp, fname);
2484 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2486 const int buf_len = strlen (escaped_fname) + 100;
2487 char *const expected = XNEWVEC (char, buf_len);
2490 pretty_printer pp;
2491 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2492 tabstop);
2493 snprintf (expected, buf_len,
2494 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2495 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2498 pretty_printer pp;
2499 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2500 tabstop);
2501 snprintf (expected, buf_len,
2502 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2503 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2506 XDELETEVEC (expected);
2507 free (escaped_fname);
2510 /* Verify that
2511 diagnostic_get_location_text (..., SHOW_COLUMN)
2512 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2513 colorization disabled. */
2515 static void
2516 assert_location_text (const char *expected_loc_text,
2517 const char *filename, int line, int column,
2518 bool show_column,
2519 int origin = 1,
2520 enum diagnostics_column_unit column_unit
2521 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2523 test_diagnostic_context dc;
2524 dc.show_column = show_column;
2525 dc.column_unit = column_unit;
2526 dc.column_origin = origin;
2528 expanded_location xloc;
2529 xloc.file = filename;
2530 xloc.line = line;
2531 xloc.column = column;
2532 xloc.data = NULL;
2533 xloc.sysp = false;
2535 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2536 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2537 free (actual_loc_text);
2540 /* Verify that diagnostic_get_location_text works as expected. */
2542 static void
2543 test_diagnostic_get_location_text ()
2545 const char *old_progname = progname;
2546 progname = "PROGNAME";
2547 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2548 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2549 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2550 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2551 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2552 for (int origin = 0; origin != 2; ++origin)
2553 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2554 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2555 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2556 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2558 maybe_line_and_column (INT_MAX, INT_MAX);
2559 maybe_line_and_column (INT_MIN, INT_MIN);
2562 /* In order to test display columns vs byte columns, we need to create a
2563 file for location_get_source_line() to read. */
2565 const char *const content = "smile \xf0\x9f\x98\x82\n";
2566 const int line_bytes = strlen (content) - 1;
2567 const int def_tabstop = 8;
2568 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2569 const int display_width = cpp_display_width (content, line_bytes, policy);
2570 ASSERT_EQ (line_bytes - 2, display_width);
2571 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2572 const char *const fname = tmp.get_filename ();
2573 const int buf_len = strlen (fname) + 16;
2574 char *const expected = XNEWVEC (char, buf_len);
2576 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2577 assert_location_text (expected, fname, 1, line_bytes, true,
2578 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2580 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2581 assert_location_text (expected, fname, 1, line_bytes, true,
2582 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2584 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2585 assert_location_text (expected, fname, 1, line_bytes, true,
2586 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2588 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2589 assert_location_text (expected, fname, 1, line_bytes, true,
2590 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2592 XDELETEVEC (expected);
2596 progname = old_progname;
2599 /* Selftest for num_digits. */
2601 static void
2602 test_num_digits ()
2604 ASSERT_EQ (1, num_digits (0));
2605 ASSERT_EQ (1, num_digits (9));
2606 ASSERT_EQ (2, num_digits (10));
2607 ASSERT_EQ (2, num_digits (99));
2608 ASSERT_EQ (3, num_digits (100));
2609 ASSERT_EQ (3, num_digits (999));
2610 ASSERT_EQ (4, num_digits (1000));
2611 ASSERT_EQ (4, num_digits (9999));
2612 ASSERT_EQ (5, num_digits (10000));
2613 ASSERT_EQ (5, num_digits (99999));
2614 ASSERT_EQ (6, num_digits (100000));
2615 ASSERT_EQ (6, num_digits (999999));
2616 ASSERT_EQ (7, num_digits (1000000));
2617 ASSERT_EQ (7, num_digits (9999999));
2618 ASSERT_EQ (8, num_digits (10000000));
2619 ASSERT_EQ (8, num_digits (99999999));
2622 /* Run all of the selftests within this file. */
2624 void
2625 c_diagnostic_cc_tests ()
2627 test_print_escaped_string ();
2628 test_print_parseable_fixits_none ();
2629 test_print_parseable_fixits_insert ();
2630 test_print_parseable_fixits_remove ();
2631 test_print_parseable_fixits_replace ();
2632 test_print_parseable_fixits_bytes_vs_display_columns ();
2633 test_diagnostic_get_location_text ();
2634 test_num_digits ();
2638 } // namespace selftest
2640 #endif /* #if CHECKING_P */
2642 #if __GNUC__ >= 10
2643 # pragma GCC diagnostic pop
2644 #endif