Daily bump.
[official-gcc.git] / gcc / diagnostic.c
blob4ded1760705057b6adb106926c55debc71d4754d
1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2021 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 "edit-context.h"
38 #include "selftest.h"
39 #include "selftest-diagnostic.h"
40 #include "opts.h"
41 #include "cpplib.h"
43 #ifdef HAVE_TERMIOS_H
44 # include <termios.h>
45 #endif
47 #ifdef GWINSZ_IN_SYS_IOCTL
48 # include <sys/ioctl.h>
49 #endif
51 /* Disable warnings about quoting issues in the pp_xxx calls below
52 that (intentionally) don't follow GCC diagnostic conventions. */
53 #if __GNUC__ >= 10
54 # pragma GCC diagnostic push
55 # pragma GCC diagnostic ignored "-Wformat-diag"
56 #endif
58 #define pedantic_warning_kind(DC) \
59 ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
60 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
61 #define permissive_error_option(DC) ((DC)->opt_permissive)
63 /* Prototypes. */
64 static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
65 int, const char *,
66 va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
67 static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
68 int, unsigned HOST_WIDE_INT,
69 const char *, const char *, va_list *,
70 diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
72 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
73 static void real_abort (void) ATTRIBUTE_NORETURN;
75 /* Name of program invoked, sans directories. */
77 const char *progname;
79 /* A diagnostic_context surrogate for stderr. */
80 static diagnostic_context global_diagnostic_context;
81 diagnostic_context *global_dc = &global_diagnostic_context;
83 /* Return a malloc'd string containing MSG formatted a la printf. The
84 caller is responsible for freeing the memory. */
85 char *
86 build_message_string (const char *msg, ...)
88 char *str;
89 va_list ap;
91 va_start (ap, msg);
92 str = xvasprintf (msg, ap);
93 va_end (ap);
95 return str;
98 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
99 char *
100 file_name_as_prefix (diagnostic_context *context, const char *f)
102 const char *locus_cs
103 = colorize_start (pp_show_color (context->printer), "locus");
104 const char *locus_ce = colorize_stop (pp_show_color (context->printer));
105 return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
110 /* Return the value of the getenv("COLUMNS") as an integer. If the
111 value is not set to a positive integer, use ioctl to get the
112 terminal width. If it fails, return INT_MAX. */
114 get_terminal_width (void)
116 const char * s = getenv ("COLUMNS");
117 if (s != NULL) {
118 int n = atoi (s);
119 if (n > 0)
120 return n;
123 #ifdef TIOCGWINSZ
124 struct winsize w;
125 w.ws_col = 0;
126 if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
127 return w.ws_col;
128 #endif
130 return INT_MAX;
133 /* Set caret_max_width to value. */
134 void
135 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
137 /* One minus to account for the leading empty space. */
138 value = value ? value - 1
139 : (isatty (fileno (pp_buffer (context->printer)->stream))
140 ? get_terminal_width () - 1: INT_MAX);
142 if (value <= 0)
143 value = INT_MAX;
145 context->caret_max_width = value;
148 /* Default implementation of final_cb. */
150 static void
151 default_diagnostic_final_cb (diagnostic_context *context)
153 /* Some of the errors may actually have been warnings. */
154 if (diagnostic_kind_count (context, DK_WERROR))
156 /* -Werror was given. */
157 if (context->warning_as_error_requested)
158 pp_verbatim (context->printer,
159 _("%s: all warnings being treated as errors"),
160 progname);
161 /* At least one -Werror= was given. */
162 else
163 pp_verbatim (context->printer,
164 _("%s: some warnings being treated as errors"),
165 progname);
166 pp_newline_and_flush (context->printer);
170 /* Initialize the diagnostic message outputting machinery. */
171 void
172 diagnostic_initialize (diagnostic_context *context, int n_opts)
174 int i;
176 /* Allocate a basic pretty-printer. Clients will replace this a
177 much more elaborated pretty-printer if they wish. */
178 context->printer = XNEW (pretty_printer);
179 new (context->printer) pretty_printer ();
181 memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
182 context->warning_as_error_requested = false;
183 context->n_opts = n_opts;
184 context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
185 for (i = 0; i < n_opts; i++)
186 context->classify_diagnostic[i] = DK_UNSPECIFIED;
187 context->show_caret = false;
188 diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
189 for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
190 context->caret_chars[i] = '^';
191 context->show_cwe = false;
192 context->path_format = DPF_NONE;
193 context->show_path_depths = false;
194 context->show_option_requested = false;
195 context->abort_on_error = false;
196 context->show_column = false;
197 context->pedantic_errors = false;
198 context->permissive = false;
199 context->opt_permissive = 0;
200 context->fatal_errors = false;
201 context->dc_inhibit_warnings = false;
202 context->dc_warn_system_headers = false;
203 context->max_errors = 0;
204 context->internal_error = NULL;
205 diagnostic_starter (context) = default_diagnostic_starter;
206 context->start_span = default_diagnostic_start_span_fn;
207 diagnostic_finalizer (context) = default_diagnostic_finalizer;
208 context->option_enabled = NULL;
209 context->option_state = NULL;
210 context->option_name = NULL;
211 context->get_option_url = NULL;
212 context->last_location = UNKNOWN_LOCATION;
213 context->last_module = 0;
214 context->x_data = NULL;
215 context->lock = 0;
216 context->inhibit_notes_p = false;
217 context->colorize_source_p = false;
218 context->show_labels_p = false;
219 context->show_line_numbers_p = false;
220 context->min_margin_width = 0;
221 context->show_ruler_p = false;
222 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
224 if (!strcmp (var, "fixits-v1"))
225 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
226 else if (!strcmp (var, "fixits-v2"))
227 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
228 /* Silently ignore unrecognized values. */
230 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
231 context->column_origin = 1;
232 context->tabstop = 8;
233 context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
234 context->edit_context_ptr = NULL;
235 context->diagnostic_group_nesting_depth = 0;
236 context->diagnostic_group_emission_count = 0;
237 context->begin_group_cb = NULL;
238 context->end_group_cb = NULL;
239 context->final_cb = default_diagnostic_final_cb;
242 /* Maybe initialize the color support. We require clients to do this
243 explicitly, since most clients don't want color. When called
244 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
246 void
247 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
249 /* value == -1 is the default value. */
250 if (value < 0)
252 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
253 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
254 otherwise default to -fdiagnostics-color=never, for other
255 values default to that
256 -fdiagnostics-color={never,auto,always}. */
257 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
259 if (!getenv ("GCC_COLORS"))
260 return;
261 value = DIAGNOSTICS_COLOR_AUTO;
263 else
264 value = DIAGNOSTICS_COLOR_DEFAULT;
266 pp_show_color (context->printer)
267 = colorize_init ((diagnostic_color_rule_t) value);
270 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
272 void
273 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
275 /* value == -1 is the default value. */
276 if (value < 0)
278 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
279 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
280 environment, otherwise default to -fdiagnostics-urls=never,
281 for other values default to that
282 -fdiagnostics-urls={never,auto,always}. */
283 if (DIAGNOSTICS_URLS_DEFAULT == -1)
285 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
286 return;
287 value = DIAGNOSTICS_URL_AUTO;
289 else
290 value = DIAGNOSTICS_URLS_DEFAULT;
293 context->printer->url_format
294 = determine_url_format ((diagnostic_url_rule_t) value);
297 /* Create the file_cache, if not already created, and tell it how to
298 translate files on input. */
299 void diagnostic_initialize_input_context (diagnostic_context *context,
300 diagnostic_input_charset_callback ccb,
301 bool should_skip_bom)
303 if (!context->m_file_cache)
304 context->m_file_cache = new file_cache;
305 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
308 /* Do any cleaning up required after the last diagnostic is emitted. */
310 void
311 diagnostic_finish (diagnostic_context *context)
313 if (context->final_cb)
314 context->final_cb (context);
316 diagnostic_file_cache_fini ();
318 XDELETEVEC (context->classify_diagnostic);
319 context->classify_diagnostic = NULL;
321 /* diagnostic_initialize allocates context->printer using XNEW
322 and placement-new. */
323 context->printer->~pretty_printer ();
324 XDELETE (context->printer);
325 context->printer = NULL;
327 if (context->edit_context_ptr)
329 delete context->edit_context_ptr;
330 context->edit_context_ptr = NULL;
334 /* Initialize DIAGNOSTIC, where the message MSG has already been
335 translated. */
336 void
337 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
338 va_list *args, rich_location *richloc,
339 diagnostic_t kind)
341 gcc_assert (richloc);
342 diagnostic->message.err_no = errno;
343 diagnostic->message.args_ptr = args;
344 diagnostic->message.format_spec = msg;
345 diagnostic->message.m_richloc = richloc;
346 diagnostic->richloc = richloc;
347 diagnostic->metadata = NULL;
348 diagnostic->kind = kind;
349 diagnostic->option_index = 0;
352 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
353 translated. */
354 void
355 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
356 va_list *args, rich_location *richloc,
357 diagnostic_t kind)
359 gcc_assert (richloc);
360 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
363 static const char *const diagnostic_kind_color[] = {
364 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
365 #include "diagnostic.def"
366 #undef DEFINE_DIAGNOSTIC_KIND
367 NULL
370 /* Get a color name for diagnostics of type KIND
371 Result could be NULL. */
373 const char *
374 diagnostic_get_color_for_kind (diagnostic_t kind)
376 return diagnostic_kind_color[kind];
379 /* Given an expanded_location, convert the column (which is in 1-based bytes)
380 to the requested units, without converting the origin.
381 Return -1 if the column is invalid (<= 0). */
383 static int
384 convert_column_unit (enum diagnostics_column_unit column_unit,
385 int tabstop,
386 expanded_location s)
388 if (s.column <= 0)
389 return -1;
391 switch (column_unit)
393 default:
394 gcc_unreachable ();
396 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
398 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
399 return location_compute_display_column (s, policy);
402 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
403 return s.column;
407 /* Given an expanded_location, convert the column (which is in 1-based bytes)
408 to the requested units and origin. Return -1 if the column is
409 invalid (<= 0). */
411 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
413 int one_based_col
414 = convert_column_unit (context->column_unit, context->tabstop, s);
415 if (one_based_col <= 0)
416 return -1;
417 return one_based_col + (context->column_origin - 1);
420 /* Return a formatted line and column ':%line:%column'. Elided if
421 line == 0 or col < 0. (A column of 0 may be valid due to the
422 -fdiagnostics-column-origin option.)
423 The result is a statically allocated buffer. */
425 static const char *
426 maybe_line_and_column (int line, int col)
428 static char result[32];
430 if (line)
432 size_t l
433 = snprintf (result, sizeof (result),
434 col >= 0 ? ":%d:%d" : ":%d", line, col);
435 gcc_checking_assert (l < sizeof (result));
437 else
438 result[0] = 0;
439 return result;
442 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
443 The caller is responsible for freeing the memory. */
445 static char *
446 diagnostic_get_location_text (diagnostic_context *context,
447 expanded_location s)
449 pretty_printer *pp = context->printer;
450 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
451 const char *locus_ce = colorize_stop (pp_show_color (pp));
452 const char *file = s.file ? s.file : progname;
453 int line = 0;
454 int col = -1;
455 if (strcmp (file, N_("<built-in>")))
457 line = s.line;
458 if (context->show_column)
459 col = diagnostic_converted_column (context, s);
462 const char *line_col = maybe_line_and_column (line, col);
463 return build_message_string ("%s%s%s:%s", locus_cs, file,
464 line_col, locus_ce);
467 static const char *const diagnostic_kind_text[] = {
468 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
469 #include "diagnostic.def"
470 #undef DEFINE_DIAGNOSTIC_KIND
471 "must-not-happen"
474 /* Return a malloc'd string describing a location and the severity of the
475 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
476 freeing the memory. */
477 char *
478 diagnostic_build_prefix (diagnostic_context *context,
479 const diagnostic_info *diagnostic)
481 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
483 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
484 const char *text_cs = "", *text_ce = "";
485 pretty_printer *pp = context->printer;
487 if (diagnostic_kind_color[diagnostic->kind])
489 text_cs = colorize_start (pp_show_color (pp),
490 diagnostic_kind_color[diagnostic->kind]);
491 text_ce = colorize_stop (pp_show_color (pp));
494 expanded_location s = diagnostic_expand_location (diagnostic);
495 char *location_text = diagnostic_get_location_text (context, s);
497 char *result = build_message_string ("%s %s%s%s", location_text,
498 text_cs, text, text_ce);
499 free (location_text);
500 return result;
503 /* Functions at which to stop the backtrace print. It's not
504 particularly helpful to print the callers of these functions. */
506 static const char * const bt_stop[] =
508 "main",
509 "toplev::main",
510 "execute_one_pass",
511 "compile_file",
514 /* A callback function passed to the backtrace_full function. */
516 static int
517 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
518 const char *function)
520 int *pcount = (int *) data;
522 /* If we don't have any useful information, don't print
523 anything. */
524 if (filename == NULL && function == NULL)
525 return 0;
527 /* Skip functions in diagnostic.c. */
528 if (*pcount == 0
529 && filename != NULL
530 && strcmp (lbasename (filename), "diagnostic.c") == 0)
531 return 0;
533 /* Print up to 20 functions. We could make this a --param, but
534 since this is only for debugging just use a constant for now. */
535 if (*pcount >= 20)
537 /* Returning a non-zero value stops the backtrace. */
538 return 1;
540 ++*pcount;
542 char *alc = NULL;
543 if (function != NULL)
545 char *str = cplus_demangle_v3 (function,
546 (DMGL_VERBOSE | DMGL_ANSI
547 | DMGL_GNU_V3 | DMGL_PARAMS));
548 if (str != NULL)
550 alc = str;
551 function = str;
554 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
556 size_t len = strlen (bt_stop[i]);
557 if (strncmp (function, bt_stop[i], len) == 0
558 && (function[len] == '\0' || function[len] == '('))
560 if (alc != NULL)
561 free (alc);
562 /* Returning a non-zero value stops the backtrace. */
563 return 1;
568 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
569 (unsigned long) pc,
570 function == NULL ? "???" : function,
571 filename == NULL ? "???" : filename,
572 lineno);
574 if (alc != NULL)
575 free (alc);
577 return 0;
580 /* A callback function passed to the backtrace_full function. This is
581 called if backtrace_full has an error. */
583 static void
584 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
586 if (errnum < 0)
588 /* This means that no debug info was available. Just quietly
589 skip printing backtrace info. */
590 return;
592 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
593 errnum == 0 ? "" : xstrerror (errnum));
596 /* Check if we've met the maximum error limit, and if so fatally exit
597 with a message. CONTEXT is the context to check, and FLUSH
598 indicates whether a diagnostic_finish call is needed. */
600 void
601 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
603 if (!context->max_errors)
604 return;
606 int count = (diagnostic_kind_count (context, DK_ERROR)
607 + diagnostic_kind_count (context, DK_SORRY)
608 + diagnostic_kind_count (context, DK_WERROR));
610 if (count >= context->max_errors)
612 fnotice (stderr,
613 "compilation terminated due to -fmax-errors=%u.\n",
614 context->max_errors);
615 if (flush)
616 diagnostic_finish (context);
617 exit (FATAL_EXIT_CODE);
621 /* Take any action which is expected to happen after the diagnostic
622 is written out. This function does not always return. */
623 void
624 diagnostic_action_after_output (diagnostic_context *context,
625 diagnostic_t diag_kind)
627 switch (diag_kind)
629 case DK_DEBUG:
630 case DK_NOTE:
631 case DK_ANACHRONISM:
632 case DK_WARNING:
633 break;
635 case DK_ERROR:
636 case DK_SORRY:
637 if (context->abort_on_error)
638 real_abort ();
639 if (context->fatal_errors)
641 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
642 diagnostic_finish (context);
643 exit (FATAL_EXIT_CODE);
645 break;
647 case DK_ICE:
648 case DK_ICE_NOBT:
650 struct backtrace_state *state = NULL;
651 if (diag_kind == DK_ICE)
652 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
653 int count = 0;
654 if (state != NULL)
655 backtrace_full (state, 2, bt_callback, bt_err_callback,
656 (void *) &count);
658 if (context->abort_on_error)
659 real_abort ();
661 fnotice (stderr, "Please submit a full bug report,\n"
662 "with preprocessed source if appropriate.\n");
663 if (count > 0)
664 fnotice (stderr,
665 ("Please include the complete backtrace "
666 "with any bug report.\n"));
667 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
669 exit (ICE_EXIT_CODE);
672 case DK_FATAL:
673 if (context->abort_on_error)
674 real_abort ();
675 diagnostic_finish (context);
676 fnotice (stderr, "compilation terminated.\n");
677 exit (FATAL_EXIT_CODE);
679 default:
680 gcc_unreachable ();
684 /* True if the last module or file in which a diagnostic was reported is
685 different from the current one. */
687 static bool
688 last_module_changed_p (diagnostic_context *context,
689 const line_map_ordinary *map)
691 return context->last_module != map;
694 /* Remember the current module or file as being the last one in which we
695 report a diagnostic. */
697 static void
698 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
700 context->last_module = map;
703 void
704 diagnostic_report_current_module (diagnostic_context *context, location_t where)
706 const line_map_ordinary *map = NULL;
708 if (pp_needs_newline (context->printer))
710 pp_newline (context->printer);
711 pp_needs_newline (context->printer) = false;
714 if (where <= BUILTINS_LOCATION)
715 return;
717 linemap_resolve_location (line_table, where,
718 LRK_MACRO_DEFINITION_LOCATION,
719 &map);
721 if (map && last_module_changed_p (context, map))
723 set_last_module (context, map);
724 if (! MAIN_FILE_P (map))
726 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
727 expanded_location s = {};
730 where = linemap_included_from (map);
731 map = linemap_included_from_linemap (line_table, map);
732 bool is_module = MAP_MODULE_P (map);
733 s.file = LINEMAP_FILE (map);
734 s.line = SOURCE_LINE (map, where);
735 int col = -1;
736 if (first && context->show_column)
738 s.column = SOURCE_COLUMN (map, where);
739 col = diagnostic_converted_column (context, s);
741 const char *line_col = maybe_line_and_column (s.line, col);
742 static const char *const msgs[] =
744 NULL,
745 N_(" from"),
746 N_("In file included from"), /* 2 */
747 N_(" included from"),
748 N_("In module"), /* 4 */
749 N_("of module"),
750 N_("In module imported at"), /* 6 */
751 N_("imported at"),
754 unsigned index = (was_module ? 6 : is_module ? 4
755 : need_inc ? 2 : 0) + !first;
757 pp_verbatim (context->printer, "%s%s %r%s%s%R",
758 first ? "" : was_module ? ", " : ",\n",
759 _(msgs[index]),
760 "locus", s.file, line_col);
761 first = false, need_inc = was_module, was_module = is_module;
763 while (! MAIN_FILE_P (map));
764 pp_verbatim (context->printer, ":");
765 pp_newline (context->printer);
770 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
771 print the path. */
773 void
774 diagnostic_show_any_path (diagnostic_context *context,
775 diagnostic_info *diagnostic)
777 const diagnostic_path *path = diagnostic->richloc->get_path ();
778 if (!path)
779 return;
781 if (context->print_path)
782 context->print_path (context, path);
785 /* Return true if the events in this path involve more than one
786 function, or false if it is purely intraprocedural. */
788 bool
789 diagnostic_path::interprocedural_p () const
791 const unsigned num = num_events ();
792 for (unsigned i = 0; i < num; i++)
794 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
795 return true;
796 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
797 return true;
799 return false;
802 void
803 default_diagnostic_starter (diagnostic_context *context,
804 diagnostic_info *diagnostic)
806 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
807 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
808 diagnostic));
811 void
812 default_diagnostic_start_span_fn (diagnostic_context *context,
813 expanded_location exploc)
815 char *text = diagnostic_get_location_text (context, exploc);
816 pp_string (context->printer, text);
817 free (text);
818 pp_newline (context->printer);
821 void
822 default_diagnostic_finalizer (diagnostic_context *context,
823 diagnostic_info *diagnostic,
824 diagnostic_t)
826 char *saved_prefix = pp_take_prefix (context->printer);
827 pp_set_prefix (context->printer, NULL);
828 pp_newline (context->printer);
829 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
830 pp_set_prefix (context->printer, saved_prefix);
831 pp_flush (context->printer);
834 /* Interface to specify diagnostic kind overrides. Returns the
835 previous setting, or DK_UNSPECIFIED if the parameters are out of
836 range. If OPTION_INDEX is zero, the new setting is for all the
837 diagnostics. */
838 diagnostic_t
839 diagnostic_classify_diagnostic (diagnostic_context *context,
840 int option_index,
841 diagnostic_t new_kind,
842 location_t where)
844 diagnostic_t old_kind;
846 if (option_index < 0
847 || option_index >= context->n_opts
848 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
849 return DK_UNSPECIFIED;
851 old_kind = context->classify_diagnostic[option_index];
853 /* Handle pragmas separately, since we need to keep track of *where*
854 the pragmas were. */
855 if (where != UNKNOWN_LOCATION)
857 int i;
859 /* Record the command-line status, so we can reset it back on DK_POP. */
860 if (old_kind == DK_UNSPECIFIED)
862 old_kind = !context->option_enabled (option_index,
863 context->lang_mask,
864 context->option_state)
865 ? DK_IGNORED : (context->warning_as_error_requested
866 ? DK_ERROR : DK_WARNING);
867 context->classify_diagnostic[option_index] = old_kind;
870 for (i = context->n_classification_history - 1; i >= 0; i --)
871 if (context->classification_history[i].option == option_index)
873 old_kind = context->classification_history[i].kind;
874 break;
877 i = context->n_classification_history;
878 context->classification_history =
879 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
880 * sizeof (diagnostic_classification_change_t));
881 context->classification_history[i].location = where;
882 context->classification_history[i].option = option_index;
883 context->classification_history[i].kind = new_kind;
884 context->n_classification_history ++;
886 else
887 context->classify_diagnostic[option_index] = new_kind;
889 return old_kind;
892 /* Save all diagnostic classifications in a stack. */
893 void
894 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
896 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
897 context->push_list[context->n_push ++] = context->n_classification_history;
900 /* Restore the topmost classification set off the stack. If the stack
901 is empty, revert to the state based on command line parameters. */
902 void
903 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
905 int jump_to;
906 int i;
908 if (context->n_push)
909 jump_to = context->push_list [-- context->n_push];
910 else
911 jump_to = 0;
913 i = context->n_classification_history;
914 context->classification_history =
915 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
916 * sizeof (diagnostic_classification_change_t));
917 context->classification_history[i].location = where;
918 context->classification_history[i].option = jump_to;
919 context->classification_history[i].kind = DK_POP;
920 context->n_classification_history ++;
923 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
924 escaping rules for -fdiagnostics-parseable-fixits. */
926 static void
927 print_escaped_string (pretty_printer *pp, const char *text)
929 gcc_assert (pp);
930 gcc_assert (text);
932 pp_character (pp, '"');
933 for (const char *ch = text; *ch; ch++)
935 switch (*ch)
937 case '\\':
938 /* Escape backslash as two backslashes. */
939 pp_string (pp, "\\\\");
940 break;
941 case '\t':
942 /* Escape tab as "\t". */
943 pp_string (pp, "\\t");
944 break;
945 case '\n':
946 /* Escape newline as "\n". */
947 pp_string (pp, "\\n");
948 break;
949 case '"':
950 /* Escape doublequotes as \". */
951 pp_string (pp, "\\\"");
952 break;
953 default:
954 if (ISPRINT (*ch))
955 pp_character (pp, *ch);
956 else
957 /* Use octal for non-printable chars. */
959 unsigned char c = (*ch & 0xff);
960 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
962 break;
965 pp_character (pp, '"');
968 /* Implementation of -fdiagnostics-parseable-fixits and
969 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
970 Print a machine-parseable version of all fixits in RICHLOC to PP,
971 using COLUMN_UNIT to express columns.
972 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
974 static void
975 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
976 enum diagnostics_column_unit column_unit,
977 int tabstop)
979 gcc_assert (pp);
980 gcc_assert (richloc);
982 char *saved_prefix = pp_take_prefix (pp);
983 pp_set_prefix (pp, NULL);
985 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
987 const fixit_hint *hint = richloc->get_fixit_hint (i);
988 location_t start_loc = hint->get_start_loc ();
989 expanded_location start_exploc = expand_location (start_loc);
990 pp_string (pp, "fix-it:");
991 print_escaped_string (pp, start_exploc.file);
992 /* For compatibility with clang, print as a half-open range. */
993 location_t next_loc = hint->get_next_loc ();
994 expanded_location next_exploc = expand_location (next_loc);
995 int start_col
996 = convert_column_unit (column_unit, tabstop, start_exploc);
997 int next_col
998 = convert_column_unit (column_unit, tabstop, next_exploc);
999 pp_printf (pp, ":{%i:%i-%i:%i}:",
1000 start_exploc.line, start_col,
1001 next_exploc.line, next_col);
1002 print_escaped_string (pp, hint->get_string ());
1003 pp_newline (pp);
1006 pp_set_prefix (pp, saved_prefix);
1009 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1011 static void
1012 get_any_inlining_info (diagnostic_context *context,
1013 diagnostic_info *diagnostic)
1015 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1017 if (context->set_locations_cb)
1018 /* Retrieve the locations into which the expression about to be
1019 diagnosed has been inlined, including those of all the callers
1020 all the way down the inlining stack. */
1021 context->set_locations_cb (context, diagnostic);
1022 else
1024 /* When there's no callback use just the one location provided
1025 by the caller of the diagnostic function. */
1026 location_t loc = diagnostic_location (diagnostic);
1027 ilocs.safe_push (loc);
1028 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1032 /* Update the kind of DIAGNOSTIC based on its location(s), including
1033 any of those in its inlining stack, relative to any
1034 #pragma GCC diagnostic
1035 directives recorded within CONTEXT.
1037 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1038 otherwise. */
1040 static diagnostic_t
1041 update_effective_level_from_pragmas (diagnostic_context *context,
1042 diagnostic_info *diagnostic)
1044 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1046 /* Ignore the diagnostic if all the inlined locations are
1047 in system headers and -Wno-system-headers is in effect. */
1048 diagnostic->kind = DK_IGNORED;
1049 return DK_IGNORED;
1052 if (context->n_classification_history <= 0)
1053 return DK_UNSPECIFIED;
1055 /* Iterate over the locations, checking the diagnostic disposition
1056 for the diagnostic at each. If it's explicitly set as opposed
1057 to unspecified, update the disposition for this instance of
1058 the diagnostic and return it. */
1059 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1061 /* FIXME: Stupid search. Optimize later. */
1062 for (int i = context->n_classification_history - 1; i >= 0; i --)
1064 const diagnostic_classification_change_t &hist
1065 = context->classification_history[i];
1067 location_t pragloc = hist.location;
1068 if (!linemap_location_before_p (line_table, pragloc, loc))
1069 continue;
1071 if (hist.kind == (int) DK_POP)
1073 /* Move on to the next region. */
1074 i = hist.option;
1075 continue;
1078 int option = hist.option;
1079 /* The option 0 is for all the diagnostics. */
1080 if (option == 0 || option == diagnostic->option_index)
1082 diagnostic_t kind = hist.kind;
1083 if (kind != DK_UNSPECIFIED)
1084 diagnostic->kind = kind;
1085 return kind;
1090 return DK_UNSPECIFIED;
1093 /* Generate a URL string describing CWE. The caller is responsible for
1094 freeing the string. */
1096 static char *
1097 get_cwe_url (int cwe)
1099 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1102 /* If DIAGNOSTIC has a CWE identifier, print it.
1104 For example, if the diagnostic metadata associates it with CWE-119,
1105 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1106 description of the security issue. */
1108 static void
1109 print_any_cwe (diagnostic_context *context,
1110 const diagnostic_info *diagnostic)
1112 if (diagnostic->metadata == NULL)
1113 return;
1115 int cwe = diagnostic->metadata->get_cwe ();
1116 if (cwe)
1118 pretty_printer *pp = context->printer;
1119 char *saved_prefix = pp_take_prefix (context->printer);
1120 pp_string (pp, " [");
1121 pp_string (pp, colorize_start (pp_show_color (pp),
1122 diagnostic_kind_color[diagnostic->kind]));
1123 if (pp->url_format != URL_FORMAT_NONE)
1125 char *cwe_url = get_cwe_url (cwe);
1126 pp_begin_url (pp, cwe_url);
1127 free (cwe_url);
1129 pp_printf (pp, "CWE-%i", cwe);
1130 pp_set_prefix (context->printer, saved_prefix);
1131 if (pp->url_format != URL_FORMAT_NONE)
1132 pp_end_url (pp);
1133 pp_string (pp, colorize_stop (pp_show_color (pp)));
1134 pp_character (pp, ']');
1138 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1139 printer, e.g. " [-Werror=uninitialized]".
1140 Subroutine of diagnostic_report_diagnostic. */
1142 static void
1143 print_option_information (diagnostic_context *context,
1144 const diagnostic_info *diagnostic,
1145 diagnostic_t orig_diag_kind)
1147 char *option_text;
1149 option_text = context->option_name (context, diagnostic->option_index,
1150 orig_diag_kind, diagnostic->kind);
1152 if (option_text)
1154 char *option_url = NULL;
1155 if (context->get_option_url
1156 && context->printer->url_format != URL_FORMAT_NONE)
1157 option_url = context->get_option_url (context,
1158 diagnostic->option_index);
1159 pretty_printer *pp = context->printer;
1160 pp_string (pp, " [");
1161 pp_string (pp, colorize_start (pp_show_color (pp),
1162 diagnostic_kind_color[diagnostic->kind]));
1163 if (option_url)
1164 pp_begin_url (pp, option_url);
1165 pp_string (pp, option_text);
1166 if (option_url)
1168 pp_end_url (pp);
1169 free (option_url);
1171 pp_string (pp, colorize_stop (pp_show_color (pp)));
1172 pp_character (pp, ']');
1173 free (option_text);
1177 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1178 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1180 static bool
1181 diagnostic_enabled (diagnostic_context *context,
1182 diagnostic_info *diagnostic)
1184 /* Update the inlining stack for this diagnostic. */
1185 get_any_inlining_info (context, diagnostic);
1187 /* Diagnostics with no option or -fpermissive are always enabled. */
1188 if (!diagnostic->option_index
1189 || diagnostic->option_index == permissive_error_option (context))
1190 return true;
1192 /* This tests if the user provided the appropriate -Wfoo or
1193 -Wno-foo option. */
1194 if (! context->option_enabled (diagnostic->option_index,
1195 context->lang_mask,
1196 context->option_state))
1197 return false;
1199 /* This tests for #pragma diagnostic changes. */
1200 diagnostic_t diag_class
1201 = update_effective_level_from_pragmas (context, diagnostic);
1203 /* This tests if the user provided the appropriate -Werror=foo
1204 option. */
1205 if (diag_class == DK_UNSPECIFIED
1206 && (context->classify_diagnostic[diagnostic->option_index]
1207 != DK_UNSPECIFIED))
1208 diagnostic->kind
1209 = context->classify_diagnostic[diagnostic->option_index];
1211 /* This allows for future extensions, like temporarily disabling
1212 warnings for ranges of source code. */
1213 if (diagnostic->kind == DK_IGNORED)
1214 return false;
1216 return true;
1219 /* Returns whether warning OPT is enabled at LOC. */
1221 bool
1222 warning_enabled_at (location_t loc, int opt)
1224 if (!diagnostic_report_warnings_p (global_dc, loc))
1225 return false;
1227 rich_location richloc (line_table, loc);
1228 diagnostic_info diagnostic = {};
1229 diagnostic.option_index = opt;
1230 diagnostic.richloc = &richloc;
1231 diagnostic.message.m_richloc = &richloc;
1232 diagnostic.kind = DK_WARNING;
1233 return diagnostic_enabled (global_dc, &diagnostic);
1236 /* Report a diagnostic message (an error or a warning) as specified by
1237 DC. This function is *the* subroutine in terms of which front-ends
1238 should implement their specific diagnostic handling modules. The
1239 front-end independent format specifiers are exactly those described
1240 in the documentation of output_format.
1241 Return true if a diagnostic was printed, false otherwise. */
1243 bool
1244 diagnostic_report_diagnostic (diagnostic_context *context,
1245 diagnostic_info *diagnostic)
1247 location_t location = diagnostic_location (diagnostic);
1248 diagnostic_t orig_diag_kind = diagnostic->kind;
1250 /* Give preference to being able to inhibit warnings, before they
1251 get reclassified to something else. */
1252 bool report_warning_p = true;
1253 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1255 if (context->dc_inhibit_warnings)
1256 return false;
1257 /* Remember the result of the overall system header warning setting
1258 but proceed to also check the inlining context. */
1259 report_warning_p = diagnostic_report_warnings_p (context, location);
1260 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1261 return false;
1264 if (diagnostic->kind == DK_PEDWARN)
1266 diagnostic->kind = pedantic_warning_kind (context);
1267 /* We do this to avoid giving the message for -pedantic-errors. */
1268 orig_diag_kind = diagnostic->kind;
1271 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1272 return false;
1274 if (context->lock > 0)
1276 /* If we're reporting an ICE in the middle of some other error,
1277 try to flush out the previous error, then let this one
1278 through. Don't do this more than once. */
1279 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1280 && context->lock == 1)
1281 pp_newline_and_flush (context->printer);
1282 else
1283 error_recursion (context);
1286 /* If the user requested that warnings be treated as errors, so be
1287 it. Note that we do this before the next block so that
1288 individual warnings can be overridden back to warnings with
1289 -Wno-error=*. */
1290 if (context->warning_as_error_requested
1291 && diagnostic->kind == DK_WARNING)
1292 diagnostic->kind = DK_ERROR;
1294 diagnostic->message.x_data = &diagnostic->x_data;
1296 /* Check to see if the diagnostic is enabled at the location and
1297 not disabled by #pragma GCC diagnostic anywhere along the inlining
1298 stack. . */
1299 if (!diagnostic_enabled (context, diagnostic))
1300 return false;
1302 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1303 /* Bail if the warning is not to be reported because all locations
1304 in the inlining stack (if there is one) are in system headers. */
1305 return false;
1307 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1308 diagnostic_check_max_errors (context);
1310 context->lock++;
1312 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1314 /* When not checking, ICEs are converted to fatal errors when an
1315 error has already occurred. This is counteracted by
1316 abort_on_error. */
1317 if (!CHECKING_P
1318 && (diagnostic_kind_count (context, DK_ERROR) > 0
1319 || diagnostic_kind_count (context, DK_SORRY) > 0)
1320 && !context->abort_on_error)
1322 expanded_location s
1323 = expand_location (diagnostic_location (diagnostic));
1324 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1325 s.file, s.line);
1326 exit (ICE_EXIT_CODE);
1328 if (context->internal_error)
1329 (*context->internal_error) (context,
1330 diagnostic->message.format_spec,
1331 diagnostic->message.args_ptr);
1333 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1334 ++diagnostic_kind_count (context, DK_WERROR);
1335 else
1336 ++diagnostic_kind_count (context, diagnostic->kind);
1338 /* Is this the initial diagnostic within the stack of groups? */
1339 if (context->diagnostic_group_emission_count == 0)
1341 if (context->begin_group_cb)
1342 context->begin_group_cb (context);
1344 context->diagnostic_group_emission_count++;
1346 pp_format (context->printer, &diagnostic->message);
1347 (*diagnostic_starter (context)) (context, diagnostic);
1348 pp_output_formatted_text (context->printer);
1349 if (context->show_cwe)
1350 print_any_cwe (context, diagnostic);
1351 if (context->show_option_requested)
1352 print_option_information (context, diagnostic, orig_diag_kind);
1353 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1354 switch (context->extra_output_kind)
1356 default:
1357 break;
1358 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1359 print_parseable_fixits (context->printer, diagnostic->richloc,
1360 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1361 context->tabstop);
1362 pp_flush (context->printer);
1363 break;
1364 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1365 print_parseable_fixits (context->printer, diagnostic->richloc,
1366 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1367 context->tabstop);
1368 pp_flush (context->printer);
1369 break;
1371 diagnostic_action_after_output (context, diagnostic->kind);
1372 diagnostic->x_data = NULL;
1374 if (context->edit_context_ptr)
1375 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1376 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1378 context->lock--;
1380 diagnostic_show_any_path (context, diagnostic);
1382 return true;
1385 /* Get the number of digits in the decimal representation of VALUE. */
1388 num_digits (int value)
1390 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1391 using floating point. */
1392 gcc_assert (value >= 0);
1394 if (value == 0)
1395 return 1;
1397 int digits = 0;
1398 while (value > 0)
1400 digits++;
1401 value /= 10;
1403 return digits;
1406 /* Given a partial pathname as input, return another pathname that
1407 shares no directory elements with the pathname of __FILE__. This
1408 is used by fancy_abort() to print `Internal compiler error in expr.c'
1409 instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
1411 const char *
1412 trim_filename (const char *name)
1414 static const char this_file[] = __FILE__;
1415 const char *p = name, *q = this_file;
1417 /* First skip any "../" in each filename. This allows us to give a proper
1418 reference to a file in a subdirectory. */
1419 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1420 p += 3;
1422 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1423 q += 3;
1425 /* Now skip any parts the two filenames have in common. */
1426 while (*p == *q && *p != 0 && *q != 0)
1427 p++, q++;
1429 /* Now go backwards until the previous directory separator. */
1430 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1431 p--;
1433 return p;
1436 /* Standard error reporting routines in increasing order of severity.
1437 All of these take arguments like printf. */
1439 /* Text to be emitted verbatim to the error message stream; this
1440 produces no prefix and disables line-wrapping. Use rarely. */
1441 void
1442 verbatim (const char *gmsgid, ...)
1444 text_info text;
1445 va_list ap;
1447 va_start (ap, gmsgid);
1448 text.err_no = errno;
1449 text.args_ptr = &ap;
1450 text.format_spec = _(gmsgid);
1451 text.x_data = NULL;
1452 pp_format_verbatim (global_dc->printer, &text);
1453 pp_newline_and_flush (global_dc->printer);
1454 va_end (ap);
1457 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1458 void
1459 diagnostic_append_note (diagnostic_context *context,
1460 location_t location,
1461 const char * gmsgid, ...)
1463 diagnostic_info diagnostic;
1464 va_list ap;
1465 rich_location richloc (line_table, location);
1467 va_start (ap, gmsgid);
1468 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1469 if (context->inhibit_notes_p)
1471 va_end (ap);
1472 return;
1474 char *saved_prefix = pp_take_prefix (context->printer);
1475 pp_set_prefix (context->printer,
1476 diagnostic_build_prefix (context, &diagnostic));
1477 pp_format (context->printer, &diagnostic.message);
1478 pp_output_formatted_text (context->printer);
1479 pp_destroy_prefix (context->printer);
1480 pp_set_prefix (context->printer, saved_prefix);
1481 pp_newline (context->printer);
1482 diagnostic_show_locus (context, &richloc, DK_NOTE);
1483 va_end (ap);
1486 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1487 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1488 and internal_error_no_backtrace, as documented and defined below. */
1489 static bool
1490 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1491 int opt, const char *gmsgid,
1492 va_list *ap, diagnostic_t kind)
1494 diagnostic_info diagnostic;
1495 if (kind == DK_PERMERROR)
1497 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1498 permissive_error_kind (global_dc));
1499 diagnostic.option_index = permissive_error_option (global_dc);
1501 else
1503 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1504 if (kind == DK_WARNING || kind == DK_PEDWARN)
1505 diagnostic.option_index = opt;
1507 diagnostic.metadata = metadata;
1508 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1511 /* Implement inform_n, warning_n, and error_n, as documented and
1512 defined below. */
1513 static bool
1514 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1515 int opt, unsigned HOST_WIDE_INT n,
1516 const char *singular_gmsgid,
1517 const char *plural_gmsgid,
1518 va_list *ap, diagnostic_t kind)
1520 diagnostic_info diagnostic;
1521 unsigned long gtn;
1523 if (sizeof n <= sizeof gtn)
1524 gtn = n;
1525 else
1526 /* Use the largest number ngettext can handle, otherwise
1527 preserve the six least significant decimal digits for
1528 languages where the plural form depends on them. */
1529 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1531 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1532 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1533 if (kind == DK_WARNING)
1534 diagnostic.option_index = opt;
1535 diagnostic.metadata = metadata;
1536 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1539 /* Wrapper around diagnostic_impl taking a variable argument list. */
1541 bool
1542 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1543 const char *gmsgid, ...)
1545 auto_diagnostic_group d;
1546 va_list ap;
1547 va_start (ap, gmsgid);
1548 rich_location richloc (line_table, location);
1549 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1550 va_end (ap);
1551 return ret;
1554 /* As above, but for rich_location *. */
1556 bool
1557 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1558 const char *gmsgid, ...)
1560 auto_diagnostic_group d;
1561 va_list ap;
1562 va_start (ap, gmsgid);
1563 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1564 va_end (ap);
1565 return ret;
1568 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1570 bool
1571 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1572 const char *gmsgid, va_list *ap)
1574 rich_location richloc (line_table, location);
1575 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1578 /* An informative note at LOCATION. Use this for additional details on an error
1579 message. */
1580 void
1581 inform (location_t location, const char *gmsgid, ...)
1583 auto_diagnostic_group d;
1584 va_list ap;
1585 va_start (ap, gmsgid);
1586 rich_location richloc (line_table, location);
1587 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1588 va_end (ap);
1591 /* Same as "inform" above, but at RICHLOC. */
1592 void
1593 inform (rich_location *richloc, const char *gmsgid, ...)
1595 gcc_assert (richloc);
1597 auto_diagnostic_group d;
1598 va_list ap;
1599 va_start (ap, gmsgid);
1600 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1601 va_end (ap);
1604 /* An informative note at LOCATION. Use this for additional details on an
1605 error message. */
1606 void
1607 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1608 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1610 va_list ap;
1611 va_start (ap, plural_gmsgid);
1612 auto_diagnostic_group d;
1613 rich_location richloc (line_table, location);
1614 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1615 &ap, DK_NOTE);
1616 va_end (ap);
1619 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1620 to the relevant language specification but is likely to be buggy anyway.
1621 Returns true if the warning was printed, false if it was inhibited. */
1622 bool
1623 warning (int opt, const char *gmsgid, ...)
1625 auto_diagnostic_group d;
1626 va_list ap;
1627 va_start (ap, gmsgid);
1628 rich_location richloc (line_table, input_location);
1629 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1630 va_end (ap);
1631 return ret;
1634 /* A warning at LOCATION. Use this for code which is correct according to the
1635 relevant language specification but is likely to be buggy anyway.
1636 Returns true if the warning was printed, false if it was inhibited. */
1638 bool
1639 warning_at (location_t location, int opt, const char *gmsgid, ...)
1641 auto_diagnostic_group d;
1642 va_list ap;
1643 va_start (ap, gmsgid);
1644 rich_location richloc (line_table, location);
1645 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1646 va_end (ap);
1647 return ret;
1650 /* Same as "warning at" above, but using RICHLOC. */
1652 bool
1653 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1655 gcc_assert (richloc);
1657 auto_diagnostic_group d;
1658 va_list ap;
1659 va_start (ap, gmsgid);
1660 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1661 va_end (ap);
1662 return ret;
1665 /* Same as "warning at" above, but using METADATA. */
1667 bool
1668 warning_meta (rich_location *richloc,
1669 const diagnostic_metadata &metadata,
1670 int opt, const char *gmsgid, ...)
1672 gcc_assert (richloc);
1674 auto_diagnostic_group d;
1675 va_list ap;
1676 va_start (ap, gmsgid);
1677 bool ret
1678 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1679 DK_WARNING);
1680 va_end (ap);
1681 return ret;
1684 /* Same as warning_n plural variant below, but using RICHLOC. */
1686 bool
1687 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1688 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1690 gcc_assert (richloc);
1692 auto_diagnostic_group d;
1693 va_list ap;
1694 va_start (ap, plural_gmsgid);
1695 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1696 singular_gmsgid, plural_gmsgid,
1697 &ap, DK_WARNING);
1698 va_end (ap);
1699 return ret;
1702 /* A warning at LOCATION. Use this for code which is correct according to the
1703 relevant language specification but is likely to be buggy anyway.
1704 Returns true if the warning was printed, false if it was inhibited. */
1706 bool
1707 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1708 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1710 auto_diagnostic_group d;
1711 va_list ap;
1712 va_start (ap, plural_gmsgid);
1713 rich_location richloc (line_table, location);
1714 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1715 singular_gmsgid, plural_gmsgid,
1716 &ap, DK_WARNING);
1717 va_end (ap);
1718 return ret;
1721 /* A "pedantic" warning at LOCATION: issues a warning unless
1722 -pedantic-errors was given on the command line, in which case it
1723 issues an error. Use this for diagnostics required by the relevant
1724 language standard, if you have chosen not to make them errors.
1726 Note that these diagnostics are issued independent of the setting
1727 of the -Wpedantic command-line switch. To get a warning enabled
1728 only with that switch, use either "if (pedantic) pedwarn
1729 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1730 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1732 Returns true if the warning was printed, false if it was inhibited. */
1734 bool
1735 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1737 auto_diagnostic_group d;
1738 va_list ap;
1739 va_start (ap, gmsgid);
1740 rich_location richloc (line_table, location);
1741 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1742 va_end (ap);
1743 return ret;
1746 /* Same as pedwarn above, but using RICHLOC. */
1748 bool
1749 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1751 gcc_assert (richloc);
1753 auto_diagnostic_group d;
1754 va_list ap;
1755 va_start (ap, gmsgid);
1756 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1757 va_end (ap);
1758 return ret;
1761 /* A "permissive" error at LOCATION: issues an error unless
1762 -fpermissive was given on the command line, in which case it issues
1763 a warning. Use this for things that really should be errors but we
1764 want to support legacy code.
1766 Returns true if the warning was printed, false if it was inhibited. */
1768 bool
1769 permerror (location_t location, const char *gmsgid, ...)
1771 auto_diagnostic_group d;
1772 va_list ap;
1773 va_start (ap, gmsgid);
1774 rich_location richloc (line_table, location);
1775 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1776 va_end (ap);
1777 return ret;
1780 /* Same as "permerror" above, but at RICHLOC. */
1782 bool
1783 permerror (rich_location *richloc, const char *gmsgid, ...)
1785 gcc_assert (richloc);
1787 auto_diagnostic_group d;
1788 va_list ap;
1789 va_start (ap, gmsgid);
1790 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1791 va_end (ap);
1792 return ret;
1795 /* A hard error: the code is definitely ill-formed, and an object file
1796 will not be produced. */
1797 void
1798 error (const char *gmsgid, ...)
1800 auto_diagnostic_group d;
1801 va_list ap;
1802 va_start (ap, gmsgid);
1803 rich_location richloc (line_table, input_location);
1804 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1805 va_end (ap);
1808 /* A hard error: the code is definitely ill-formed, and an object file
1809 will not be produced. */
1810 void
1811 error_n (location_t location, unsigned HOST_WIDE_INT n,
1812 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1814 auto_diagnostic_group d;
1815 va_list ap;
1816 va_start (ap, plural_gmsgid);
1817 rich_location richloc (line_table, location);
1818 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1819 &ap, DK_ERROR);
1820 va_end (ap);
1823 /* Same as above, but use location LOC instead of input_location. */
1824 void
1825 error_at (location_t loc, const char *gmsgid, ...)
1827 auto_diagnostic_group d;
1828 va_list ap;
1829 va_start (ap, gmsgid);
1830 rich_location richloc (line_table, loc);
1831 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1832 va_end (ap);
1835 /* Same as above, but use RICH_LOC. */
1837 void
1838 error_at (rich_location *richloc, const char *gmsgid, ...)
1840 gcc_assert (richloc);
1842 auto_diagnostic_group d;
1843 va_list ap;
1844 va_start (ap, gmsgid);
1845 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1846 va_end (ap);
1849 /* "Sorry, not implemented." Use for a language feature which is
1850 required by the relevant specification but not implemented by GCC.
1851 An object file will not be produced. */
1852 void
1853 sorry (const char *gmsgid, ...)
1855 auto_diagnostic_group d;
1856 va_list ap;
1857 va_start (ap, gmsgid);
1858 rich_location richloc (line_table, input_location);
1859 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1860 va_end (ap);
1863 /* Same as above, but use location LOC instead of input_location. */
1864 void
1865 sorry_at (location_t loc, const char *gmsgid, ...)
1867 auto_diagnostic_group d;
1868 va_list ap;
1869 va_start (ap, gmsgid);
1870 rich_location richloc (line_table, loc);
1871 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1872 va_end (ap);
1875 /* Return true if an error or a "sorry" has been seen. Various
1876 processing is disabled after errors. */
1877 bool
1878 seen_error (void)
1880 return errorcount || sorrycount;
1883 /* An error which is severe enough that we make no attempt to
1884 continue. Do not use this for internal consistency checks; that's
1885 internal_error. Use of this function should be rare. */
1886 void
1887 fatal_error (location_t loc, const char *gmsgid, ...)
1889 auto_diagnostic_group d;
1890 va_list ap;
1891 va_start (ap, gmsgid);
1892 rich_location richloc (line_table, loc);
1893 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1894 va_end (ap);
1896 gcc_unreachable ();
1899 /* An internal consistency check has failed. We make no attempt to
1900 continue. Note that unless there is debugging value to be had from
1901 a more specific message, or some other good reason, you should use
1902 abort () instead of calling this function directly. */
1903 void
1904 internal_error (const char *gmsgid, ...)
1906 auto_diagnostic_group d;
1907 va_list ap;
1908 va_start (ap, gmsgid);
1909 rich_location richloc (line_table, input_location);
1910 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
1911 va_end (ap);
1913 gcc_unreachable ();
1916 /* Like internal_error, but no backtrace will be printed. Used when
1917 the internal error does not happen at the current location, but happened
1918 somewhere else. */
1919 void
1920 internal_error_no_backtrace (const char *gmsgid, ...)
1922 auto_diagnostic_group d;
1923 va_list ap;
1924 va_start (ap, gmsgid);
1925 rich_location richloc (line_table, input_location);
1926 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1927 va_end (ap);
1929 gcc_unreachable ();
1932 /* Special case error functions. Most are implemented in terms of the
1933 above, or should be. */
1935 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1936 runs its second argument through gettext. */
1937 void
1938 fnotice (FILE *file, const char *cmsgid, ...)
1940 va_list ap;
1942 va_start (ap, cmsgid);
1943 vfprintf (file, _(cmsgid), ap);
1944 va_end (ap);
1947 /* Inform the user that an error occurred while trying to report some
1948 other error. This indicates catastrophic internal inconsistencies,
1949 so give up now. But do try to flush out the previous error.
1950 This mustn't use internal_error, that will cause infinite recursion. */
1952 static void
1953 error_recursion (diagnostic_context *context)
1955 if (context->lock < 3)
1956 pp_newline_and_flush (context->printer);
1958 fnotice (stderr,
1959 "Internal compiler error: Error reporting routines re-entered.\n");
1961 /* Call diagnostic_action_after_output to get the "please submit a bug
1962 report" message. */
1963 diagnostic_action_after_output (context, DK_ICE);
1965 /* Do not use gcc_unreachable here; that goes through internal_error
1966 and therefore would cause infinite recursion. */
1967 real_abort ();
1970 /* Report an internal compiler error in a friendly manner. This is
1971 the function that gets called upon use of abort() in the source
1972 code generally, thanks to a special macro. */
1974 void
1975 fancy_abort (const char *file, int line, const char *function)
1977 /* If fancy_abort is called before the diagnostic subsystem is initialized,
1978 internal_error will crash internally in a way that prevents a
1979 useful message reaching the user.
1980 This can happen with libgccjit in the case of gcc_assert failures
1981 that occur outside of the libgccjit mutex that guards the rest of
1982 gcc's state, including global_dc (when global_dc may not be
1983 initialized yet, or might be in use by another thread).
1984 Handle such cases as gracefully as possible by falling back to a
1985 minimal abort handler that only relies on i18n. */
1986 if (global_dc->printer == NULL)
1988 /* Print the error message. */
1989 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
1990 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
1991 fputc ('\n', stderr);
1993 /* Attempt to print a backtrace. */
1994 struct backtrace_state *state
1995 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
1996 int count = 0;
1997 if (state != NULL)
1998 backtrace_full (state, 2, bt_callback, bt_err_callback,
1999 (void *) &count);
2001 /* We can't call warn_if_plugins or emergency_dump_function as these
2002 rely on GCC state that might not be initialized, or might be in
2003 use by another thread. */
2005 /* Abort the process. */
2006 real_abort ();
2009 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2012 /* class auto_diagnostic_group. */
2014 /* Constructor: "push" this group into global_dc. */
2016 auto_diagnostic_group::auto_diagnostic_group ()
2018 global_dc->diagnostic_group_nesting_depth++;
2021 /* Destructor: "pop" this group from global_dc. */
2023 auto_diagnostic_group::~auto_diagnostic_group ()
2025 if (--global_dc->diagnostic_group_nesting_depth == 0)
2027 /* Handle the case where we've popped the final diagnostic group.
2028 If any diagnostics were emitted, give the context a chance
2029 to do something. */
2030 if (global_dc->diagnostic_group_emission_count > 0)
2032 if (global_dc->end_group_cb)
2033 global_dc->end_group_cb (global_dc);
2035 global_dc->diagnostic_group_emission_count = 0;
2039 /* Implementation of diagnostic_path::num_events vfunc for
2040 simple_diagnostic_path: simply get the number of events in the vec. */
2042 unsigned
2043 simple_diagnostic_path::num_events () const
2045 return m_events.length ();
2048 /* Implementation of diagnostic_path::get_event vfunc for
2049 simple_diagnostic_path: simply return the event in the vec. */
2051 const diagnostic_event &
2052 simple_diagnostic_path::get_event (int idx) const
2054 return *m_events[idx];
2057 /* Add an event to this path at LOC within function FNDECL at
2058 stack depth DEPTH.
2060 Use m_context's printer to format FMT, as the text of the new
2061 event.
2063 Return the id of the new event. */
2065 diagnostic_event_id_t
2066 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2067 const char *fmt, ...)
2069 pretty_printer *pp = m_event_pp;
2070 pp_clear_output_area (pp);
2072 text_info ti;
2073 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2075 va_list ap;
2077 va_start (ap, fmt);
2079 ti.format_spec = _(fmt);
2080 ti.args_ptr = &ap;
2081 ti.err_no = 0;
2082 ti.x_data = NULL;
2083 ti.m_richloc = &rich_loc;
2085 pp_format (pp, &ti);
2086 pp_output_formatted_text (pp);
2088 va_end (ap);
2090 simple_diagnostic_event *new_event
2091 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2092 m_events.safe_push (new_event);
2094 pp_clear_output_area (pp);
2096 return diagnostic_event_id_t (m_events.length () - 1);
2099 /* struct simple_diagnostic_event. */
2101 /* simple_diagnostic_event's ctor. */
2103 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2104 tree fndecl,
2105 int depth,
2106 const char *desc)
2107 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2111 /* simple_diagnostic_event's dtor. */
2113 simple_diagnostic_event::~simple_diagnostic_event ()
2115 free (m_desc);
2118 /* Print PATH by emitting a dummy "note" associated with it. */
2120 DEBUG_FUNCTION
2121 void debug (diagnostic_path *path)
2123 rich_location richloc (line_table, UNKNOWN_LOCATION);
2124 richloc.set_path (path);
2125 inform (&richloc, "debug path");
2128 /* Really call the system 'abort'. This has to go right at the end of
2129 this file, so that there are no functions after it that call abort
2130 and get the system abort instead of our macro. */
2131 #undef abort
2132 static void
2133 real_abort (void)
2135 abort ();
2138 #if CHECKING_P
2140 namespace selftest {
2142 /* Helper function for test_print_escaped_string. */
2144 static void
2145 assert_print_escaped_string (const location &loc, const char *expected_output,
2146 const char *input)
2148 pretty_printer pp;
2149 print_escaped_string (&pp, input);
2150 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2153 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2154 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2156 /* Tests of print_escaped_string. */
2158 static void
2159 test_print_escaped_string ()
2161 /* Empty string. */
2162 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2164 /* Non-empty string. */
2165 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2167 /* Various things that need to be escaped: */
2168 /* Backslash. */
2169 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2170 "before\\after");
2171 /* Tab. */
2172 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2173 "before\tafter");
2174 /* Newline. */
2175 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2176 "before\nafter");
2177 /* Double quote. */
2178 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2179 "before\"after");
2181 /* Non-printable characters: BEL: '\a': 0x07 */
2182 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2183 "before\aafter");
2184 /* Non-printable characters: vertical tab: '\v': 0x0b */
2185 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2186 "before\vafter");
2189 /* Tests of print_parseable_fixits. */
2191 /* Verify that print_parseable_fixits emits the empty string if there
2192 are no fixits. */
2194 static void
2195 test_print_parseable_fixits_none ()
2197 pretty_printer pp;
2198 rich_location richloc (line_table, UNKNOWN_LOCATION);
2200 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2201 ASSERT_STREQ ("", pp_formatted_text (&pp));
2204 /* Verify that print_parseable_fixits does the right thing if there
2205 is an insertion fixit hint. */
2207 static void
2208 test_print_parseable_fixits_insert ()
2210 pretty_printer pp;
2211 rich_location richloc (line_table, UNKNOWN_LOCATION);
2213 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2214 linemap_line_start (line_table, 5, 100);
2215 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2216 location_t where = linemap_position_for_column (line_table, 10);
2217 richloc.add_fixit_insert_before (where, "added content");
2219 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2220 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2221 pp_formatted_text (&pp));
2224 /* Verify that print_parseable_fixits does the right thing if there
2225 is an removal fixit hint. */
2227 static void
2228 test_print_parseable_fixits_remove ()
2230 pretty_printer pp;
2231 rich_location richloc (line_table, UNKNOWN_LOCATION);
2233 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2234 linemap_line_start (line_table, 5, 100);
2235 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2236 source_range where;
2237 where.m_start = linemap_position_for_column (line_table, 10);
2238 where.m_finish = linemap_position_for_column (line_table, 20);
2239 richloc.add_fixit_remove (where);
2241 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2242 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2243 pp_formatted_text (&pp));
2246 /* Verify that print_parseable_fixits does the right thing if there
2247 is an replacement fixit hint. */
2249 static void
2250 test_print_parseable_fixits_replace ()
2252 pretty_printer pp;
2253 rich_location richloc (line_table, UNKNOWN_LOCATION);
2255 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2256 linemap_line_start (line_table, 5, 100);
2257 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2258 source_range where;
2259 where.m_start = linemap_position_for_column (line_table, 10);
2260 where.m_finish = linemap_position_for_column (line_table, 20);
2261 richloc.add_fixit_replace (where, "replacement");
2263 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2264 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2265 pp_formatted_text (&pp));
2268 /* Verify that print_parseable_fixits correctly handles
2269 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2271 static void
2272 test_print_parseable_fixits_bytes_vs_display_columns ()
2274 line_table_test ltt;
2275 rich_location richloc (line_table, UNKNOWN_LOCATION);
2277 /* 1-based byte offsets: 12345677778888999900001234567. */
2278 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2279 /* 1-based display cols: 123456[......7-8.....]9012345. */
2280 const int tabstop = 8;
2282 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2283 const char *const fname = tmp.get_filename ();
2285 linemap_add (line_table, LC_ENTER, false, fname, 0);
2286 linemap_line_start (line_table, 1, 100);
2287 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2288 source_range where;
2289 where.m_start = linemap_position_for_column (line_table, 12);
2290 where.m_finish = linemap_position_for_column (line_table, 17);
2291 richloc.add_fixit_replace (where, "color");
2293 /* Escape fname. */
2294 pretty_printer tmp_pp;
2295 print_escaped_string (&tmp_pp, fname);
2296 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2298 const int buf_len = strlen (escaped_fname) + 100;
2299 char *const expected = XNEWVEC (char, buf_len);
2302 pretty_printer pp;
2303 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2304 tabstop);
2305 snprintf (expected, buf_len,
2306 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2307 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2310 pretty_printer pp;
2311 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2312 tabstop);
2313 snprintf (expected, buf_len,
2314 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2315 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2318 XDELETEVEC (expected);
2319 free (escaped_fname);
2322 /* Verify that
2323 diagnostic_get_location_text (..., SHOW_COLUMN)
2324 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2325 colorization disabled. */
2327 static void
2328 assert_location_text (const char *expected_loc_text,
2329 const char *filename, int line, int column,
2330 bool show_column,
2331 int origin = 1,
2332 enum diagnostics_column_unit column_unit
2333 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2335 test_diagnostic_context dc;
2336 dc.show_column = show_column;
2337 dc.column_unit = column_unit;
2338 dc.column_origin = origin;
2340 expanded_location xloc;
2341 xloc.file = filename;
2342 xloc.line = line;
2343 xloc.column = column;
2344 xloc.data = NULL;
2345 xloc.sysp = false;
2347 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2348 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2349 free (actual_loc_text);
2352 /* Verify that diagnostic_get_location_text works as expected. */
2354 static void
2355 test_diagnostic_get_location_text ()
2357 const char *old_progname = progname;
2358 progname = "PROGNAME";
2359 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2360 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2361 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2362 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2363 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2364 for (int origin = 0; origin != 2; ++origin)
2365 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2366 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2367 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2368 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2370 maybe_line_and_column (INT_MAX, INT_MAX);
2371 maybe_line_and_column (INT_MIN, INT_MIN);
2374 /* In order to test display columns vs byte columns, we need to create a
2375 file for location_get_source_line() to read. */
2377 const char *const content = "smile \xf0\x9f\x98\x82\n";
2378 const int line_bytes = strlen (content) - 1;
2379 const int def_tabstop = 8;
2380 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2381 const int display_width = cpp_display_width (content, line_bytes, policy);
2382 ASSERT_EQ (line_bytes - 2, display_width);
2383 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2384 const char *const fname = tmp.get_filename ();
2385 const int buf_len = strlen (fname) + 16;
2386 char *const expected = XNEWVEC (char, buf_len);
2388 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2389 assert_location_text (expected, fname, 1, line_bytes, true,
2390 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2392 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2393 assert_location_text (expected, fname, 1, line_bytes, true,
2394 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2396 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2397 assert_location_text (expected, fname, 1, line_bytes, true,
2398 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2400 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2401 assert_location_text (expected, fname, 1, line_bytes, true,
2402 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2404 XDELETEVEC (expected);
2408 progname = old_progname;
2411 /* Selftest for num_digits. */
2413 static void
2414 test_num_digits ()
2416 ASSERT_EQ (1, num_digits (0));
2417 ASSERT_EQ (1, num_digits (9));
2418 ASSERT_EQ (2, num_digits (10));
2419 ASSERT_EQ (2, num_digits (99));
2420 ASSERT_EQ (3, num_digits (100));
2421 ASSERT_EQ (3, num_digits (999));
2422 ASSERT_EQ (4, num_digits (1000));
2423 ASSERT_EQ (4, num_digits (9999));
2424 ASSERT_EQ (5, num_digits (10000));
2425 ASSERT_EQ (5, num_digits (99999));
2426 ASSERT_EQ (6, num_digits (100000));
2427 ASSERT_EQ (6, num_digits (999999));
2428 ASSERT_EQ (7, num_digits (1000000));
2429 ASSERT_EQ (7, num_digits (9999999));
2430 ASSERT_EQ (8, num_digits (10000000));
2431 ASSERT_EQ (8, num_digits (99999999));
2434 /* Run all of the selftests within this file. */
2436 void
2437 diagnostic_c_tests ()
2439 test_print_escaped_string ();
2440 test_print_parseable_fixits_none ();
2441 test_print_parseable_fixits_insert ();
2442 test_print_parseable_fixits_remove ();
2443 test_print_parseable_fixits_replace ();
2444 test_print_parseable_fixits_bytes_vs_display_columns ();
2445 test_diagnostic_get_location_text ();
2446 test_num_digits ();
2450 } // namespace selftest
2452 #endif /* #if CHECKING_P */
2454 #if __GNUC__ >= 10
2455 # pragma GCC diagnostic pop
2456 #endif