Revise -mdisable-fpregs option and add new -msoft-mult option
[official-gcc.git] / gcc / diagnostic.c
blobb3afbeae648844a872f5773915f6227e5a1f5725
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->edit_context_ptr = NULL;
234 context->diagnostic_group_nesting_depth = 0;
235 context->diagnostic_group_emission_count = 0;
236 context->begin_group_cb = NULL;
237 context->end_group_cb = NULL;
238 context->final_cb = default_diagnostic_final_cb;
241 /* Maybe initialize the color support. We require clients to do this
242 explicitly, since most clients don't want color. When called
243 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
245 void
246 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
248 /* value == -1 is the default value. */
249 if (value < 0)
251 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
252 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
253 otherwise default to -fdiagnostics-color=never, for other
254 values default to that
255 -fdiagnostics-color={never,auto,always}. */
256 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
258 if (!getenv ("GCC_COLORS"))
259 return;
260 value = DIAGNOSTICS_COLOR_AUTO;
262 else
263 value = DIAGNOSTICS_COLOR_DEFAULT;
265 pp_show_color (context->printer)
266 = colorize_init ((diagnostic_color_rule_t) value);
269 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
271 void
272 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
274 /* value == -1 is the default value. */
275 if (value < 0)
277 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
278 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
279 environment, otherwise default to -fdiagnostics-urls=never,
280 for other values default to that
281 -fdiagnostics-urls={never,auto,always}. */
282 if (DIAGNOSTICS_URLS_DEFAULT == -1)
284 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
285 return;
286 value = DIAGNOSTICS_URL_AUTO;
288 else
289 value = DIAGNOSTICS_URLS_DEFAULT;
292 context->printer->url_format
293 = determine_url_format ((diagnostic_url_rule_t) value);
296 /* Create the file_cache, if not already created, and tell it how to
297 translate files on input. */
298 void diagnostic_initialize_input_context (diagnostic_context *context,
299 diagnostic_input_charset_callback ccb,
300 bool should_skip_bom)
302 if (!context->m_file_cache)
303 context->m_file_cache = new file_cache;
304 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
307 /* Do any cleaning up required after the last diagnostic is emitted. */
309 void
310 diagnostic_finish (diagnostic_context *context)
312 if (context->final_cb)
313 context->final_cb (context);
315 diagnostic_file_cache_fini ();
317 XDELETEVEC (context->classify_diagnostic);
318 context->classify_diagnostic = NULL;
320 /* diagnostic_initialize allocates context->printer using XNEW
321 and placement-new. */
322 context->printer->~pretty_printer ();
323 XDELETE (context->printer);
324 context->printer = NULL;
326 if (context->edit_context_ptr)
328 delete context->edit_context_ptr;
329 context->edit_context_ptr = NULL;
333 /* Initialize DIAGNOSTIC, where the message MSG has already been
334 translated. */
335 void
336 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
337 va_list *args, rich_location *richloc,
338 diagnostic_t kind)
340 gcc_assert (richloc);
341 diagnostic->message.err_no = errno;
342 diagnostic->message.args_ptr = args;
343 diagnostic->message.format_spec = msg;
344 diagnostic->message.m_richloc = richloc;
345 diagnostic->richloc = richloc;
346 diagnostic->metadata = NULL;
347 diagnostic->kind = kind;
348 diagnostic->option_index = 0;
351 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
352 translated. */
353 void
354 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
355 va_list *args, rich_location *richloc,
356 diagnostic_t kind)
358 gcc_assert (richloc);
359 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
362 static const char *const diagnostic_kind_color[] = {
363 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
364 #include "diagnostic.def"
365 #undef DEFINE_DIAGNOSTIC_KIND
366 NULL
369 /* Get a color name for diagnostics of type KIND
370 Result could be NULL. */
372 const char *
373 diagnostic_get_color_for_kind (diagnostic_t kind)
375 return diagnostic_kind_color[kind];
378 /* Given an expanded_location, convert the column (which is in 1-based bytes)
379 to the requested units, without converting the origin.
380 Return -1 if the column is invalid (<= 0). */
382 static int
383 convert_column_unit (enum diagnostics_column_unit column_unit,
384 int tabstop,
385 expanded_location s)
387 if (s.column <= 0)
388 return -1;
390 switch (column_unit)
392 default:
393 gcc_unreachable ();
395 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
396 return location_compute_display_column (s, tabstop);
398 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
399 return s.column;
403 /* Given an expanded_location, convert the column (which is in 1-based bytes)
404 to the requested units and origin. Return -1 if the column is
405 invalid (<= 0). */
407 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
409 int one_based_col
410 = convert_column_unit (context->column_unit, context->tabstop, s);
411 if (one_based_col <= 0)
412 return -1;
413 return one_based_col + (context->column_origin - 1);
416 /* Return a formatted line and column ':%line:%column'. Elided if
417 line == 0 or col < 0. (A column of 0 may be valid due to the
418 -fdiagnostics-column-origin option.)
419 The result is a statically allocated buffer. */
421 static const char *
422 maybe_line_and_column (int line, int col)
424 static char result[32];
426 if (line)
428 size_t l
429 = snprintf (result, sizeof (result),
430 col >= 0 ? ":%d:%d" : ":%d", line, col);
431 gcc_checking_assert (l < sizeof (result));
433 else
434 result[0] = 0;
435 return result;
438 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
439 The caller is responsible for freeing the memory. */
441 static char *
442 diagnostic_get_location_text (diagnostic_context *context,
443 expanded_location s)
445 pretty_printer *pp = context->printer;
446 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
447 const char *locus_ce = colorize_stop (pp_show_color (pp));
448 const char *file = s.file ? s.file : progname;
449 int line = 0;
450 int col = -1;
451 if (strcmp (file, N_("<built-in>")))
453 line = s.line;
454 if (context->show_column)
455 col = diagnostic_converted_column (context, s);
458 const char *line_col = maybe_line_and_column (line, col);
459 return build_message_string ("%s%s%s:%s", locus_cs, file,
460 line_col, locus_ce);
463 static const char *const diagnostic_kind_text[] = {
464 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
465 #include "diagnostic.def"
466 #undef DEFINE_DIAGNOSTIC_KIND
467 "must-not-happen"
470 /* Return a malloc'd string describing a location and the severity of the
471 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
472 freeing the memory. */
473 char *
474 diagnostic_build_prefix (diagnostic_context *context,
475 const diagnostic_info *diagnostic)
477 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
479 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
480 const char *text_cs = "", *text_ce = "";
481 pretty_printer *pp = context->printer;
483 if (diagnostic_kind_color[diagnostic->kind])
485 text_cs = colorize_start (pp_show_color (pp),
486 diagnostic_kind_color[diagnostic->kind]);
487 text_ce = colorize_stop (pp_show_color (pp));
490 expanded_location s = diagnostic_expand_location (diagnostic);
491 char *location_text = diagnostic_get_location_text (context, s);
493 char *result = build_message_string ("%s %s%s%s", location_text,
494 text_cs, text, text_ce);
495 free (location_text);
496 return result;
499 /* Functions at which to stop the backtrace print. It's not
500 particularly helpful to print the callers of these functions. */
502 static const char * const bt_stop[] =
504 "main",
505 "toplev::main",
506 "execute_one_pass",
507 "compile_file",
510 /* A callback function passed to the backtrace_full function. */
512 static int
513 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
514 const char *function)
516 int *pcount = (int *) data;
518 /* If we don't have any useful information, don't print
519 anything. */
520 if (filename == NULL && function == NULL)
521 return 0;
523 /* Skip functions in diagnostic.c. */
524 if (*pcount == 0
525 && filename != NULL
526 && strcmp (lbasename (filename), "diagnostic.c") == 0)
527 return 0;
529 /* Print up to 20 functions. We could make this a --param, but
530 since this is only for debugging just use a constant for now. */
531 if (*pcount >= 20)
533 /* Returning a non-zero value stops the backtrace. */
534 return 1;
536 ++*pcount;
538 char *alc = NULL;
539 if (function != NULL)
541 char *str = cplus_demangle_v3 (function,
542 (DMGL_VERBOSE | DMGL_ANSI
543 | DMGL_GNU_V3 | DMGL_PARAMS));
544 if (str != NULL)
546 alc = str;
547 function = str;
550 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
552 size_t len = strlen (bt_stop[i]);
553 if (strncmp (function, bt_stop[i], len) == 0
554 && (function[len] == '\0' || function[len] == '('))
556 if (alc != NULL)
557 free (alc);
558 /* Returning a non-zero value stops the backtrace. */
559 return 1;
564 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
565 (unsigned long) pc,
566 function == NULL ? "???" : function,
567 filename == NULL ? "???" : filename,
568 lineno);
570 if (alc != NULL)
571 free (alc);
573 return 0;
576 /* A callback function passed to the backtrace_full function. This is
577 called if backtrace_full has an error. */
579 static void
580 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
582 if (errnum < 0)
584 /* This means that no debug info was available. Just quietly
585 skip printing backtrace info. */
586 return;
588 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
589 errnum == 0 ? "" : xstrerror (errnum));
592 /* Check if we've met the maximum error limit, and if so fatally exit
593 with a message. CONTEXT is the context to check, and FLUSH
594 indicates whether a diagnostic_finish call is needed. */
596 void
597 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
599 if (!context->max_errors)
600 return;
602 int count = (diagnostic_kind_count (context, DK_ERROR)
603 + diagnostic_kind_count (context, DK_SORRY)
604 + diagnostic_kind_count (context, DK_WERROR));
606 if (count >= context->max_errors)
608 fnotice (stderr,
609 "compilation terminated due to -fmax-errors=%u.\n",
610 context->max_errors);
611 if (flush)
612 diagnostic_finish (context);
613 exit (FATAL_EXIT_CODE);
617 /* Take any action which is expected to happen after the diagnostic
618 is written out. This function does not always return. */
619 void
620 diagnostic_action_after_output (diagnostic_context *context,
621 diagnostic_t diag_kind)
623 switch (diag_kind)
625 case DK_DEBUG:
626 case DK_NOTE:
627 case DK_ANACHRONISM:
628 case DK_WARNING:
629 break;
631 case DK_ERROR:
632 case DK_SORRY:
633 if (context->abort_on_error)
634 real_abort ();
635 if (context->fatal_errors)
637 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
638 diagnostic_finish (context);
639 exit (FATAL_EXIT_CODE);
641 break;
643 case DK_ICE:
644 case DK_ICE_NOBT:
646 struct backtrace_state *state = NULL;
647 if (diag_kind == DK_ICE)
648 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
649 int count = 0;
650 if (state != NULL)
651 backtrace_full (state, 2, bt_callback, bt_err_callback,
652 (void *) &count);
654 if (context->abort_on_error)
655 real_abort ();
657 fnotice (stderr, "Please submit a full bug report,\n"
658 "with preprocessed source if appropriate.\n");
659 if (count > 0)
660 fnotice (stderr,
661 ("Please include the complete backtrace "
662 "with any bug report.\n"));
663 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
665 exit (ICE_EXIT_CODE);
668 case DK_FATAL:
669 if (context->abort_on_error)
670 real_abort ();
671 diagnostic_finish (context);
672 fnotice (stderr, "compilation terminated.\n");
673 exit (FATAL_EXIT_CODE);
675 default:
676 gcc_unreachable ();
680 /* True if the last module or file in which a diagnostic was reported is
681 different from the current one. */
683 static bool
684 last_module_changed_p (diagnostic_context *context,
685 const line_map_ordinary *map)
687 return context->last_module != map;
690 /* Remember the current module or file as being the last one in which we
691 report a diagnostic. */
693 static void
694 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
696 context->last_module = map;
699 void
700 diagnostic_report_current_module (diagnostic_context *context, location_t where)
702 const line_map_ordinary *map = NULL;
704 if (pp_needs_newline (context->printer))
706 pp_newline (context->printer);
707 pp_needs_newline (context->printer) = false;
710 if (where <= BUILTINS_LOCATION)
711 return;
713 linemap_resolve_location (line_table, where,
714 LRK_MACRO_DEFINITION_LOCATION,
715 &map);
717 if (map && last_module_changed_p (context, map))
719 set_last_module (context, map);
720 if (! MAIN_FILE_P (map))
722 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
723 expanded_location s = {};
726 where = linemap_included_from (map);
727 map = linemap_included_from_linemap (line_table, map);
728 bool is_module = MAP_MODULE_P (map);
729 s.file = LINEMAP_FILE (map);
730 s.line = SOURCE_LINE (map, where);
731 int col = -1;
732 if (first && context->show_column)
734 s.column = SOURCE_COLUMN (map, where);
735 col = diagnostic_converted_column (context, s);
737 const char *line_col = maybe_line_and_column (s.line, col);
738 static const char *const msgs[] =
740 NULL,
741 N_(" from"),
742 N_("In file included from"), /* 2 */
743 N_(" included from"),
744 N_("In module"), /* 4 */
745 N_("of module"),
746 N_("In module imported at"), /* 6 */
747 N_("imported at"),
750 unsigned index = (was_module ? 6 : is_module ? 4
751 : need_inc ? 2 : 0) + !first;
753 pp_verbatim (context->printer, "%s%s %r%s%s%R",
754 first ? "" : was_module ? ", " : ",\n",
755 _(msgs[index]),
756 "locus", s.file, line_col);
757 first = false, need_inc = was_module, was_module = is_module;
759 while (! MAIN_FILE_P (map));
760 pp_verbatim (context->printer, ":");
761 pp_newline (context->printer);
766 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
767 print the path. */
769 void
770 diagnostic_show_any_path (diagnostic_context *context,
771 diagnostic_info *diagnostic)
773 const diagnostic_path *path = diagnostic->richloc->get_path ();
774 if (!path)
775 return;
777 if (context->print_path)
778 context->print_path (context, path);
781 /* Return true if the events in this path involve more than one
782 function, or false if it is purely intraprocedural. */
784 bool
785 diagnostic_path::interprocedural_p () const
787 const unsigned num = num_events ();
788 for (unsigned i = 0; i < num; i++)
790 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
791 return true;
792 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
793 return true;
795 return false;
798 void
799 default_diagnostic_starter (diagnostic_context *context,
800 diagnostic_info *diagnostic)
802 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
803 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
804 diagnostic));
807 void
808 default_diagnostic_start_span_fn (diagnostic_context *context,
809 expanded_location exploc)
811 char *text = diagnostic_get_location_text (context, exploc);
812 pp_string (context->printer, text);
813 free (text);
814 pp_newline (context->printer);
817 void
818 default_diagnostic_finalizer (diagnostic_context *context,
819 diagnostic_info *diagnostic,
820 diagnostic_t)
822 char *saved_prefix = pp_take_prefix (context->printer);
823 pp_set_prefix (context->printer, NULL);
824 pp_newline (context->printer);
825 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
826 pp_set_prefix (context->printer, saved_prefix);
827 pp_flush (context->printer);
830 /* Interface to specify diagnostic kind overrides. Returns the
831 previous setting, or DK_UNSPECIFIED if the parameters are out of
832 range. If OPTION_INDEX is zero, the new setting is for all the
833 diagnostics. */
834 diagnostic_t
835 diagnostic_classify_diagnostic (diagnostic_context *context,
836 int option_index,
837 diagnostic_t new_kind,
838 location_t where)
840 diagnostic_t old_kind;
842 if (option_index < 0
843 || option_index >= context->n_opts
844 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
845 return DK_UNSPECIFIED;
847 old_kind = context->classify_diagnostic[option_index];
849 /* Handle pragmas separately, since we need to keep track of *where*
850 the pragmas were. */
851 if (where != UNKNOWN_LOCATION)
853 int i;
855 /* Record the command-line status, so we can reset it back on DK_POP. */
856 if (old_kind == DK_UNSPECIFIED)
858 old_kind = !context->option_enabled (option_index,
859 context->lang_mask,
860 context->option_state)
861 ? DK_IGNORED : (context->warning_as_error_requested
862 ? DK_ERROR : DK_WARNING);
863 context->classify_diagnostic[option_index] = old_kind;
866 for (i = context->n_classification_history - 1; i >= 0; i --)
867 if (context->classification_history[i].option == option_index)
869 old_kind = context->classification_history[i].kind;
870 break;
873 i = context->n_classification_history;
874 context->classification_history =
875 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
876 * sizeof (diagnostic_classification_change_t));
877 context->classification_history[i].location = where;
878 context->classification_history[i].option = option_index;
879 context->classification_history[i].kind = new_kind;
880 context->n_classification_history ++;
882 else
883 context->classify_diagnostic[option_index] = new_kind;
885 return old_kind;
888 /* Save all diagnostic classifications in a stack. */
889 void
890 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
892 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
893 context->push_list[context->n_push ++] = context->n_classification_history;
896 /* Restore the topmost classification set off the stack. If the stack
897 is empty, revert to the state based on command line parameters. */
898 void
899 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
901 int jump_to;
902 int i;
904 if (context->n_push)
905 jump_to = context->push_list [-- context->n_push];
906 else
907 jump_to = 0;
909 i = context->n_classification_history;
910 context->classification_history =
911 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
912 * sizeof (diagnostic_classification_change_t));
913 context->classification_history[i].location = where;
914 context->classification_history[i].option = jump_to;
915 context->classification_history[i].kind = DK_POP;
916 context->n_classification_history ++;
919 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
920 escaping rules for -fdiagnostics-parseable-fixits. */
922 static void
923 print_escaped_string (pretty_printer *pp, const char *text)
925 gcc_assert (pp);
926 gcc_assert (text);
928 pp_character (pp, '"');
929 for (const char *ch = text; *ch; ch++)
931 switch (*ch)
933 case '\\':
934 /* Escape backslash as two backslashes. */
935 pp_string (pp, "\\\\");
936 break;
937 case '\t':
938 /* Escape tab as "\t". */
939 pp_string (pp, "\\t");
940 break;
941 case '\n':
942 /* Escape newline as "\n". */
943 pp_string (pp, "\\n");
944 break;
945 case '"':
946 /* Escape doublequotes as \". */
947 pp_string (pp, "\\\"");
948 break;
949 default:
950 if (ISPRINT (*ch))
951 pp_character (pp, *ch);
952 else
953 /* Use octal for non-printable chars. */
955 unsigned char c = (*ch & 0xff);
956 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
958 break;
961 pp_character (pp, '"');
964 /* Implementation of -fdiagnostics-parseable-fixits and
965 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
966 Print a machine-parseable version of all fixits in RICHLOC to PP,
967 using COLUMN_UNIT to express columns.
968 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
970 static void
971 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
972 enum diagnostics_column_unit column_unit,
973 int tabstop)
975 gcc_assert (pp);
976 gcc_assert (richloc);
978 char *saved_prefix = pp_take_prefix (pp);
979 pp_set_prefix (pp, NULL);
981 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
983 const fixit_hint *hint = richloc->get_fixit_hint (i);
984 location_t start_loc = hint->get_start_loc ();
985 expanded_location start_exploc = expand_location (start_loc);
986 pp_string (pp, "fix-it:");
987 print_escaped_string (pp, start_exploc.file);
988 /* For compatibility with clang, print as a half-open range. */
989 location_t next_loc = hint->get_next_loc ();
990 expanded_location next_exploc = expand_location (next_loc);
991 int start_col
992 = convert_column_unit (column_unit, tabstop, start_exploc);
993 int next_col
994 = convert_column_unit (column_unit, tabstop, next_exploc);
995 pp_printf (pp, ":{%i:%i-%i:%i}:",
996 start_exploc.line, start_col,
997 next_exploc.line, next_col);
998 print_escaped_string (pp, hint->get_string ());
999 pp_newline (pp);
1002 pp_set_prefix (pp, saved_prefix);
1005 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1007 static void
1008 get_any_inlining_info (diagnostic_context *context,
1009 diagnostic_info *diagnostic)
1011 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1013 if (context->set_locations_cb)
1014 /* Retrieve the locations into which the expression about to be
1015 diagnosed has been inlined, including those of all the callers
1016 all the way down the inlining stack. */
1017 context->set_locations_cb (context, diagnostic);
1018 else
1020 /* When there's no callback use just the one location provided
1021 by the caller of the diagnostic function. */
1022 location_t loc = diagnostic_location (diagnostic);
1023 ilocs.safe_push (loc);
1024 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1028 /* Update the kind of DIAGNOSTIC based on its location(s), including
1029 any of those in its inlining stack, relative to any
1030 #pragma GCC diagnostic
1031 directives recorded within CONTEXT.
1033 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1034 otherwise. */
1036 static diagnostic_t
1037 update_effective_level_from_pragmas (diagnostic_context *context,
1038 diagnostic_info *diagnostic)
1040 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1042 /* Ignore the diagnostic if all the inlined locations are
1043 in system headers and -Wno-system-headers is in effect. */
1044 diagnostic->kind = DK_IGNORED;
1045 return DK_IGNORED;
1048 if (context->n_classification_history <= 0)
1049 return DK_UNSPECIFIED;
1051 /* Iterate over the locations, checking the diagnostic disposition
1052 for the diagnostic at each. If it's explicitly set as opposed
1053 to unspecified, update the disposition for this instance of
1054 the diagnostic and return it. */
1055 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1057 /* FIXME: Stupid search. Optimize later. */
1058 for (int i = context->n_classification_history - 1; i >= 0; i --)
1060 const diagnostic_classification_change_t &hist
1061 = context->classification_history[i];
1063 location_t pragloc = hist.location;
1064 if (!linemap_location_before_p (line_table, pragloc, loc))
1065 continue;
1067 if (hist.kind == (int) DK_POP)
1069 /* Move on to the next region. */
1070 i = hist.option;
1071 continue;
1074 int option = hist.option;
1075 /* The option 0 is for all the diagnostics. */
1076 if (option == 0 || option == diagnostic->option_index)
1078 diagnostic_t kind = hist.kind;
1079 if (kind != DK_UNSPECIFIED)
1080 diagnostic->kind = kind;
1081 return kind;
1086 return DK_UNSPECIFIED;
1089 /* Generate a URL string describing CWE. The caller is responsible for
1090 freeing the string. */
1092 static char *
1093 get_cwe_url (int cwe)
1095 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1098 /* If DIAGNOSTIC has a CWE identifier, print it.
1100 For example, if the diagnostic metadata associates it with CWE-119,
1101 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1102 description of the security issue. */
1104 static void
1105 print_any_cwe (diagnostic_context *context,
1106 const diagnostic_info *diagnostic)
1108 if (diagnostic->metadata == NULL)
1109 return;
1111 int cwe = diagnostic->metadata->get_cwe ();
1112 if (cwe)
1114 pretty_printer *pp = context->printer;
1115 char *saved_prefix = pp_take_prefix (context->printer);
1116 pp_string (pp, " [");
1117 pp_string (pp, colorize_start (pp_show_color (pp),
1118 diagnostic_kind_color[diagnostic->kind]));
1119 if (pp->url_format != URL_FORMAT_NONE)
1121 char *cwe_url = get_cwe_url (cwe);
1122 pp_begin_url (pp, cwe_url);
1123 free (cwe_url);
1125 pp_printf (pp, "CWE-%i", cwe);
1126 pp_set_prefix (context->printer, saved_prefix);
1127 if (pp->url_format != URL_FORMAT_NONE)
1128 pp_end_url (pp);
1129 pp_string (pp, colorize_stop (pp_show_color (pp)));
1130 pp_character (pp, ']');
1134 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1135 printer, e.g. " [-Werror=uninitialized]".
1136 Subroutine of diagnostic_report_diagnostic. */
1138 static void
1139 print_option_information (diagnostic_context *context,
1140 const diagnostic_info *diagnostic,
1141 diagnostic_t orig_diag_kind)
1143 char *option_text;
1145 option_text = context->option_name (context, diagnostic->option_index,
1146 orig_diag_kind, diagnostic->kind);
1148 if (option_text)
1150 char *option_url = NULL;
1151 if (context->get_option_url
1152 && context->printer->url_format != URL_FORMAT_NONE)
1153 option_url = context->get_option_url (context,
1154 diagnostic->option_index);
1155 pretty_printer *pp = context->printer;
1156 pp_string (pp, " [");
1157 pp_string (pp, colorize_start (pp_show_color (pp),
1158 diagnostic_kind_color[diagnostic->kind]));
1159 if (option_url)
1160 pp_begin_url (pp, option_url);
1161 pp_string (pp, option_text);
1162 if (option_url)
1164 pp_end_url (pp);
1165 free (option_url);
1167 pp_string (pp, colorize_stop (pp_show_color (pp)));
1168 pp_character (pp, ']');
1169 free (option_text);
1173 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1174 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1176 static bool
1177 diagnostic_enabled (diagnostic_context *context,
1178 diagnostic_info *diagnostic)
1180 /* Update the inlining stack for this diagnostic. */
1181 get_any_inlining_info (context, diagnostic);
1183 /* Diagnostics with no option or -fpermissive are always enabled. */
1184 if (!diagnostic->option_index
1185 || diagnostic->option_index == permissive_error_option (context))
1186 return true;
1188 /* This tests if the user provided the appropriate -Wfoo or
1189 -Wno-foo option. */
1190 if (! context->option_enabled (diagnostic->option_index,
1191 context->lang_mask,
1192 context->option_state))
1193 return false;
1195 /* This tests for #pragma diagnostic changes. */
1196 diagnostic_t diag_class
1197 = update_effective_level_from_pragmas (context, diagnostic);
1199 /* This tests if the user provided the appropriate -Werror=foo
1200 option. */
1201 if (diag_class == DK_UNSPECIFIED
1202 && (context->classify_diagnostic[diagnostic->option_index]
1203 != DK_UNSPECIFIED))
1204 diagnostic->kind
1205 = context->classify_diagnostic[diagnostic->option_index];
1207 /* This allows for future extensions, like temporarily disabling
1208 warnings for ranges of source code. */
1209 if (diagnostic->kind == DK_IGNORED)
1210 return false;
1212 return true;
1215 /* Returns whether warning OPT is enabled at LOC. */
1217 bool
1218 warning_enabled_at (location_t loc, int opt)
1220 if (!diagnostic_report_warnings_p (global_dc, loc))
1221 return false;
1223 rich_location richloc (line_table, loc);
1224 diagnostic_info diagnostic = {};
1225 diagnostic.option_index = opt;
1226 diagnostic.richloc = &richloc;
1227 diagnostic.message.m_richloc = &richloc;
1228 diagnostic.kind = DK_WARNING;
1229 return diagnostic_enabled (global_dc, &diagnostic);
1232 /* Report a diagnostic message (an error or a warning) as specified by
1233 DC. This function is *the* subroutine in terms of which front-ends
1234 should implement their specific diagnostic handling modules. The
1235 front-end independent format specifiers are exactly those described
1236 in the documentation of output_format.
1237 Return true if a diagnostic was printed, false otherwise. */
1239 bool
1240 diagnostic_report_diagnostic (diagnostic_context *context,
1241 diagnostic_info *diagnostic)
1243 location_t location = diagnostic_location (diagnostic);
1244 diagnostic_t orig_diag_kind = diagnostic->kind;
1246 /* Give preference to being able to inhibit warnings, before they
1247 get reclassified to something else. */
1248 bool report_warning_p = true;
1249 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1251 if (context->dc_inhibit_warnings)
1252 return false;
1253 /* Remember the result of the overall system header warning setting
1254 but proceed to also check the inlining context. */
1255 report_warning_p = diagnostic_report_warnings_p (context, location);
1256 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1257 return false;
1260 if (diagnostic->kind == DK_PEDWARN)
1262 diagnostic->kind = pedantic_warning_kind (context);
1263 /* We do this to avoid giving the message for -pedantic-errors. */
1264 orig_diag_kind = diagnostic->kind;
1267 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1268 return false;
1270 if (context->lock > 0)
1272 /* If we're reporting an ICE in the middle of some other error,
1273 try to flush out the previous error, then let this one
1274 through. Don't do this more than once. */
1275 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1276 && context->lock == 1)
1277 pp_newline_and_flush (context->printer);
1278 else
1279 error_recursion (context);
1282 /* If the user requested that warnings be treated as errors, so be
1283 it. Note that we do this before the next block so that
1284 individual warnings can be overridden back to warnings with
1285 -Wno-error=*. */
1286 if (context->warning_as_error_requested
1287 && diagnostic->kind == DK_WARNING)
1288 diagnostic->kind = DK_ERROR;
1290 diagnostic->message.x_data = &diagnostic->x_data;
1292 /* Check to see if the diagnostic is enabled at the location and
1293 not disabled by #pragma GCC diagnostic anywhere along the inlining
1294 stack. . */
1295 if (!diagnostic_enabled (context, diagnostic))
1296 return false;
1298 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1299 /* Bail if the warning is not to be reported because all locations
1300 in the inlining stack (if there is one) are in system headers. */
1301 return false;
1303 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1304 diagnostic_check_max_errors (context);
1306 context->lock++;
1308 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1310 /* When not checking, ICEs are converted to fatal errors when an
1311 error has already occurred. This is counteracted by
1312 abort_on_error. */
1313 if (!CHECKING_P
1314 && (diagnostic_kind_count (context, DK_ERROR) > 0
1315 || diagnostic_kind_count (context, DK_SORRY) > 0)
1316 && !context->abort_on_error)
1318 expanded_location s
1319 = expand_location (diagnostic_location (diagnostic));
1320 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1321 s.file, s.line);
1322 exit (ICE_EXIT_CODE);
1324 if (context->internal_error)
1325 (*context->internal_error) (context,
1326 diagnostic->message.format_spec,
1327 diagnostic->message.args_ptr);
1329 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1330 ++diagnostic_kind_count (context, DK_WERROR);
1331 else
1332 ++diagnostic_kind_count (context, diagnostic->kind);
1334 /* Is this the initial diagnostic within the stack of groups? */
1335 if (context->diagnostic_group_emission_count == 0)
1337 if (context->begin_group_cb)
1338 context->begin_group_cb (context);
1340 context->diagnostic_group_emission_count++;
1342 pp_format (context->printer, &diagnostic->message);
1343 (*diagnostic_starter (context)) (context, diagnostic);
1344 pp_output_formatted_text (context->printer);
1345 if (context->show_cwe)
1346 print_any_cwe (context, diagnostic);
1347 if (context->show_option_requested)
1348 print_option_information (context, diagnostic, orig_diag_kind);
1349 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1350 switch (context->extra_output_kind)
1352 default:
1353 break;
1354 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1355 print_parseable_fixits (context->printer, diagnostic->richloc,
1356 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1357 context->tabstop);
1358 pp_flush (context->printer);
1359 break;
1360 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1361 print_parseable_fixits (context->printer, diagnostic->richloc,
1362 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1363 context->tabstop);
1364 pp_flush (context->printer);
1365 break;
1367 diagnostic_action_after_output (context, diagnostic->kind);
1368 diagnostic->x_data = NULL;
1370 if (context->edit_context_ptr)
1371 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1372 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1374 context->lock--;
1376 diagnostic_show_any_path (context, diagnostic);
1378 return true;
1381 /* Get the number of digits in the decimal representation of VALUE. */
1384 num_digits (int value)
1386 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1387 using floating point. */
1388 gcc_assert (value >= 0);
1390 if (value == 0)
1391 return 1;
1393 int digits = 0;
1394 while (value > 0)
1396 digits++;
1397 value /= 10;
1399 return digits;
1402 /* Given a partial pathname as input, return another pathname that
1403 shares no directory elements with the pathname of __FILE__. This
1404 is used by fancy_abort() to print `Internal compiler error in expr.c'
1405 instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
1407 const char *
1408 trim_filename (const char *name)
1410 static const char this_file[] = __FILE__;
1411 const char *p = name, *q = this_file;
1413 /* First skip any "../" in each filename. This allows us to give a proper
1414 reference to a file in a subdirectory. */
1415 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1416 p += 3;
1418 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1419 q += 3;
1421 /* Now skip any parts the two filenames have in common. */
1422 while (*p == *q && *p != 0 && *q != 0)
1423 p++, q++;
1425 /* Now go backwards until the previous directory separator. */
1426 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1427 p--;
1429 return p;
1432 /* Standard error reporting routines in increasing order of severity.
1433 All of these take arguments like printf. */
1435 /* Text to be emitted verbatim to the error message stream; this
1436 produces no prefix and disables line-wrapping. Use rarely. */
1437 void
1438 verbatim (const char *gmsgid, ...)
1440 text_info text;
1441 va_list ap;
1443 va_start (ap, gmsgid);
1444 text.err_no = errno;
1445 text.args_ptr = &ap;
1446 text.format_spec = _(gmsgid);
1447 text.x_data = NULL;
1448 pp_format_verbatim (global_dc->printer, &text);
1449 pp_newline_and_flush (global_dc->printer);
1450 va_end (ap);
1453 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1454 void
1455 diagnostic_append_note (diagnostic_context *context,
1456 location_t location,
1457 const char * gmsgid, ...)
1459 diagnostic_info diagnostic;
1460 va_list ap;
1461 rich_location richloc (line_table, location);
1463 va_start (ap, gmsgid);
1464 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1465 if (context->inhibit_notes_p)
1467 va_end (ap);
1468 return;
1470 char *saved_prefix = pp_take_prefix (context->printer);
1471 pp_set_prefix (context->printer,
1472 diagnostic_build_prefix (context, &diagnostic));
1473 pp_format (context->printer, &diagnostic.message);
1474 pp_output_formatted_text (context->printer);
1475 pp_destroy_prefix (context->printer);
1476 pp_set_prefix (context->printer, saved_prefix);
1477 pp_newline (context->printer);
1478 diagnostic_show_locus (context, &richloc, DK_NOTE);
1479 va_end (ap);
1482 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1483 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1484 and internal_error_no_backtrace, as documented and defined below. */
1485 static bool
1486 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1487 int opt, const char *gmsgid,
1488 va_list *ap, diagnostic_t kind)
1490 diagnostic_info diagnostic;
1491 if (kind == DK_PERMERROR)
1493 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1494 permissive_error_kind (global_dc));
1495 diagnostic.option_index = permissive_error_option (global_dc);
1497 else
1499 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1500 if (kind == DK_WARNING || kind == DK_PEDWARN)
1501 diagnostic.option_index = opt;
1503 diagnostic.metadata = metadata;
1504 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1507 /* Implement inform_n, warning_n, and error_n, as documented and
1508 defined below. */
1509 static bool
1510 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1511 int opt, unsigned HOST_WIDE_INT n,
1512 const char *singular_gmsgid,
1513 const char *plural_gmsgid,
1514 va_list *ap, diagnostic_t kind)
1516 diagnostic_info diagnostic;
1517 unsigned long gtn;
1519 if (sizeof n <= sizeof gtn)
1520 gtn = n;
1521 else
1522 /* Use the largest number ngettext can handle, otherwise
1523 preserve the six least significant decimal digits for
1524 languages where the plural form depends on them. */
1525 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1527 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1528 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1529 if (kind == DK_WARNING)
1530 diagnostic.option_index = opt;
1531 diagnostic.metadata = metadata;
1532 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1535 /* Wrapper around diagnostic_impl taking a variable argument list. */
1537 bool
1538 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1539 const char *gmsgid, ...)
1541 auto_diagnostic_group d;
1542 va_list ap;
1543 va_start (ap, gmsgid);
1544 rich_location richloc (line_table, location);
1545 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1546 va_end (ap);
1547 return ret;
1550 /* As above, but for rich_location *. */
1552 bool
1553 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1554 const char *gmsgid, ...)
1556 auto_diagnostic_group d;
1557 va_list ap;
1558 va_start (ap, gmsgid);
1559 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1560 va_end (ap);
1561 return ret;
1564 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1566 bool
1567 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1568 const char *gmsgid, va_list *ap)
1570 rich_location richloc (line_table, location);
1571 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1574 /* An informative note at LOCATION. Use this for additional details on an error
1575 message. */
1576 void
1577 inform (location_t location, const char *gmsgid, ...)
1579 auto_diagnostic_group d;
1580 va_list ap;
1581 va_start (ap, gmsgid);
1582 rich_location richloc (line_table, location);
1583 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1584 va_end (ap);
1587 /* Same as "inform" above, but at RICHLOC. */
1588 void
1589 inform (rich_location *richloc, const char *gmsgid, ...)
1591 gcc_assert (richloc);
1593 auto_diagnostic_group d;
1594 va_list ap;
1595 va_start (ap, gmsgid);
1596 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1597 va_end (ap);
1600 /* An informative note at LOCATION. Use this for additional details on an
1601 error message. */
1602 void
1603 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1604 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1606 va_list ap;
1607 va_start (ap, plural_gmsgid);
1608 auto_diagnostic_group d;
1609 rich_location richloc (line_table, location);
1610 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1611 &ap, DK_NOTE);
1612 va_end (ap);
1615 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1616 to the relevant language specification but is likely to be buggy anyway.
1617 Returns true if the warning was printed, false if it was inhibited. */
1618 bool
1619 warning (int opt, const char *gmsgid, ...)
1621 auto_diagnostic_group d;
1622 va_list ap;
1623 va_start (ap, gmsgid);
1624 rich_location richloc (line_table, input_location);
1625 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1626 va_end (ap);
1627 return ret;
1630 /* A warning at LOCATION. Use this for code which is correct according to the
1631 relevant language specification but is likely to be buggy anyway.
1632 Returns true if the warning was printed, false if it was inhibited. */
1634 bool
1635 warning_at (location_t location, int opt, const char *gmsgid, ...)
1637 auto_diagnostic_group d;
1638 va_list ap;
1639 va_start (ap, gmsgid);
1640 rich_location richloc (line_table, location);
1641 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1642 va_end (ap);
1643 return ret;
1646 /* Same as "warning at" above, but using RICHLOC. */
1648 bool
1649 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1651 gcc_assert (richloc);
1653 auto_diagnostic_group d;
1654 va_list ap;
1655 va_start (ap, gmsgid);
1656 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1657 va_end (ap);
1658 return ret;
1661 /* Same as "warning at" above, but using METADATA. */
1663 bool
1664 warning_meta (rich_location *richloc,
1665 const diagnostic_metadata &metadata,
1666 int opt, const char *gmsgid, ...)
1668 gcc_assert (richloc);
1670 auto_diagnostic_group d;
1671 va_list ap;
1672 va_start (ap, gmsgid);
1673 bool ret
1674 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1675 DK_WARNING);
1676 va_end (ap);
1677 return ret;
1680 /* Same as warning_n plural variant below, but using RICHLOC. */
1682 bool
1683 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1684 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1686 gcc_assert (richloc);
1688 auto_diagnostic_group d;
1689 va_list ap;
1690 va_start (ap, plural_gmsgid);
1691 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1692 singular_gmsgid, plural_gmsgid,
1693 &ap, DK_WARNING);
1694 va_end (ap);
1695 return ret;
1698 /* A warning at LOCATION. Use this for code which is correct according to the
1699 relevant language specification but is likely to be buggy anyway.
1700 Returns true if the warning was printed, false if it was inhibited. */
1702 bool
1703 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1704 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1706 auto_diagnostic_group d;
1707 va_list ap;
1708 va_start (ap, plural_gmsgid);
1709 rich_location richloc (line_table, location);
1710 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1711 singular_gmsgid, plural_gmsgid,
1712 &ap, DK_WARNING);
1713 va_end (ap);
1714 return ret;
1717 /* A "pedantic" warning at LOCATION: issues a warning unless
1718 -pedantic-errors was given on the command line, in which case it
1719 issues an error. Use this for diagnostics required by the relevant
1720 language standard, if you have chosen not to make them errors.
1722 Note that these diagnostics are issued independent of the setting
1723 of the -Wpedantic command-line switch. To get a warning enabled
1724 only with that switch, use either "if (pedantic) pedwarn
1725 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1726 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1728 Returns true if the warning was printed, false if it was inhibited. */
1730 bool
1731 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1733 auto_diagnostic_group d;
1734 va_list ap;
1735 va_start (ap, gmsgid);
1736 rich_location richloc (line_table, location);
1737 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1738 va_end (ap);
1739 return ret;
1742 /* Same as pedwarn above, but using RICHLOC. */
1744 bool
1745 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1747 gcc_assert (richloc);
1749 auto_diagnostic_group d;
1750 va_list ap;
1751 va_start (ap, gmsgid);
1752 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1753 va_end (ap);
1754 return ret;
1757 /* A "permissive" error at LOCATION: issues an error unless
1758 -fpermissive was given on the command line, in which case it issues
1759 a warning. Use this for things that really should be errors but we
1760 want to support legacy code.
1762 Returns true if the warning was printed, false if it was inhibited. */
1764 bool
1765 permerror (location_t location, const char *gmsgid, ...)
1767 auto_diagnostic_group d;
1768 va_list ap;
1769 va_start (ap, gmsgid);
1770 rich_location richloc (line_table, location);
1771 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1772 va_end (ap);
1773 return ret;
1776 /* Same as "permerror" above, but at RICHLOC. */
1778 bool
1779 permerror (rich_location *richloc, const char *gmsgid, ...)
1781 gcc_assert (richloc);
1783 auto_diagnostic_group d;
1784 va_list ap;
1785 va_start (ap, gmsgid);
1786 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1787 va_end (ap);
1788 return ret;
1791 /* A hard error: the code is definitely ill-formed, and an object file
1792 will not be produced. */
1793 void
1794 error (const char *gmsgid, ...)
1796 auto_diagnostic_group d;
1797 va_list ap;
1798 va_start (ap, gmsgid);
1799 rich_location richloc (line_table, input_location);
1800 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1801 va_end (ap);
1804 /* A hard error: the code is definitely ill-formed, and an object file
1805 will not be produced. */
1806 void
1807 error_n (location_t location, unsigned HOST_WIDE_INT n,
1808 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1810 auto_diagnostic_group d;
1811 va_list ap;
1812 va_start (ap, plural_gmsgid);
1813 rich_location richloc (line_table, location);
1814 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1815 &ap, DK_ERROR);
1816 va_end (ap);
1819 /* Same as above, but use location LOC instead of input_location. */
1820 void
1821 error_at (location_t loc, const char *gmsgid, ...)
1823 auto_diagnostic_group d;
1824 va_list ap;
1825 va_start (ap, gmsgid);
1826 rich_location richloc (line_table, loc);
1827 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1828 va_end (ap);
1831 /* Same as above, but use RICH_LOC. */
1833 void
1834 error_at (rich_location *richloc, const char *gmsgid, ...)
1836 gcc_assert (richloc);
1838 auto_diagnostic_group d;
1839 va_list ap;
1840 va_start (ap, gmsgid);
1841 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1842 va_end (ap);
1845 /* "Sorry, not implemented." Use for a language feature which is
1846 required by the relevant specification but not implemented by GCC.
1847 An object file will not be produced. */
1848 void
1849 sorry (const char *gmsgid, ...)
1851 auto_diagnostic_group d;
1852 va_list ap;
1853 va_start (ap, gmsgid);
1854 rich_location richloc (line_table, input_location);
1855 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1856 va_end (ap);
1859 /* Same as above, but use location LOC instead of input_location. */
1860 void
1861 sorry_at (location_t loc, const char *gmsgid, ...)
1863 auto_diagnostic_group d;
1864 va_list ap;
1865 va_start (ap, gmsgid);
1866 rich_location richloc (line_table, loc);
1867 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1868 va_end (ap);
1871 /* Return true if an error or a "sorry" has been seen. Various
1872 processing is disabled after errors. */
1873 bool
1874 seen_error (void)
1876 return errorcount || sorrycount;
1879 /* An error which is severe enough that we make no attempt to
1880 continue. Do not use this for internal consistency checks; that's
1881 internal_error. Use of this function should be rare. */
1882 void
1883 fatal_error (location_t loc, const char *gmsgid, ...)
1885 auto_diagnostic_group d;
1886 va_list ap;
1887 va_start (ap, gmsgid);
1888 rich_location richloc (line_table, loc);
1889 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1890 va_end (ap);
1892 gcc_unreachable ();
1895 /* An internal consistency check has failed. We make no attempt to
1896 continue. Note that unless there is debugging value to be had from
1897 a more specific message, or some other good reason, you should use
1898 abort () instead of calling this function directly. */
1899 void
1900 internal_error (const char *gmsgid, ...)
1902 auto_diagnostic_group d;
1903 va_list ap;
1904 va_start (ap, gmsgid);
1905 rich_location richloc (line_table, input_location);
1906 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
1907 va_end (ap);
1909 gcc_unreachable ();
1912 /* Like internal_error, but no backtrace will be printed. Used when
1913 the internal error does not happen at the current location, but happened
1914 somewhere else. */
1915 void
1916 internal_error_no_backtrace (const char *gmsgid, ...)
1918 auto_diagnostic_group d;
1919 va_list ap;
1920 va_start (ap, gmsgid);
1921 rich_location richloc (line_table, input_location);
1922 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1923 va_end (ap);
1925 gcc_unreachable ();
1928 /* Special case error functions. Most are implemented in terms of the
1929 above, or should be. */
1931 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1932 runs its second argument through gettext. */
1933 void
1934 fnotice (FILE *file, const char *cmsgid, ...)
1936 va_list ap;
1938 va_start (ap, cmsgid);
1939 vfprintf (file, _(cmsgid), ap);
1940 va_end (ap);
1943 /* Inform the user that an error occurred while trying to report some
1944 other error. This indicates catastrophic internal inconsistencies,
1945 so give up now. But do try to flush out the previous error.
1946 This mustn't use internal_error, that will cause infinite recursion. */
1948 static void
1949 error_recursion (diagnostic_context *context)
1951 if (context->lock < 3)
1952 pp_newline_and_flush (context->printer);
1954 fnotice (stderr,
1955 "Internal compiler error: Error reporting routines re-entered.\n");
1957 /* Call diagnostic_action_after_output to get the "please submit a bug
1958 report" message. */
1959 diagnostic_action_after_output (context, DK_ICE);
1961 /* Do not use gcc_unreachable here; that goes through internal_error
1962 and therefore would cause infinite recursion. */
1963 real_abort ();
1966 /* Report an internal compiler error in a friendly manner. This is
1967 the function that gets called upon use of abort() in the source
1968 code generally, thanks to a special macro. */
1970 void
1971 fancy_abort (const char *file, int line, const char *function)
1973 /* If fancy_abort is called before the diagnostic subsystem is initialized,
1974 internal_error will crash internally in a way that prevents a
1975 useful message reaching the user.
1976 This can happen with libgccjit in the case of gcc_assert failures
1977 that occur outside of the libgccjit mutex that guards the rest of
1978 gcc's state, including global_dc (when global_dc may not be
1979 initialized yet, or might be in use by another thread).
1980 Handle such cases as gracefully as possible by falling back to a
1981 minimal abort handler that only relies on i18n. */
1982 if (global_dc->printer == NULL)
1984 /* Print the error message. */
1985 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
1986 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
1987 fputc ('\n', stderr);
1989 /* Attempt to print a backtrace. */
1990 struct backtrace_state *state
1991 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
1992 int count = 0;
1993 if (state != NULL)
1994 backtrace_full (state, 2, bt_callback, bt_err_callback,
1995 (void *) &count);
1997 /* We can't call warn_if_plugins or emergency_dump_function as these
1998 rely on GCC state that might not be initialized, or might be in
1999 use by another thread. */
2001 /* Abort the process. */
2002 real_abort ();
2005 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2008 /* class auto_diagnostic_group. */
2010 /* Constructor: "push" this group into global_dc. */
2012 auto_diagnostic_group::auto_diagnostic_group ()
2014 global_dc->diagnostic_group_nesting_depth++;
2017 /* Destructor: "pop" this group from global_dc. */
2019 auto_diagnostic_group::~auto_diagnostic_group ()
2021 if (--global_dc->diagnostic_group_nesting_depth == 0)
2023 /* Handle the case where we've popped the final diagnostic group.
2024 If any diagnostics were emitted, give the context a chance
2025 to do something. */
2026 if (global_dc->diagnostic_group_emission_count > 0)
2028 if (global_dc->end_group_cb)
2029 global_dc->end_group_cb (global_dc);
2031 global_dc->diagnostic_group_emission_count = 0;
2035 /* Implementation of diagnostic_path::num_events vfunc for
2036 simple_diagnostic_path: simply get the number of events in the vec. */
2038 unsigned
2039 simple_diagnostic_path::num_events () const
2041 return m_events.length ();
2044 /* Implementation of diagnostic_path::get_event vfunc for
2045 simple_diagnostic_path: simply return the event in the vec. */
2047 const diagnostic_event &
2048 simple_diagnostic_path::get_event (int idx) const
2050 return *m_events[idx];
2053 /* Add an event to this path at LOC within function FNDECL at
2054 stack depth DEPTH.
2056 Use m_context's printer to format FMT, as the text of the new
2057 event.
2059 Return the id of the new event. */
2061 diagnostic_event_id_t
2062 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2063 const char *fmt, ...)
2065 pretty_printer *pp = m_event_pp;
2066 pp_clear_output_area (pp);
2068 text_info ti;
2069 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2071 va_list ap;
2073 va_start (ap, fmt);
2075 ti.format_spec = _(fmt);
2076 ti.args_ptr = &ap;
2077 ti.err_no = 0;
2078 ti.x_data = NULL;
2079 ti.m_richloc = &rich_loc;
2081 pp_format (pp, &ti);
2082 pp_output_formatted_text (pp);
2084 va_end (ap);
2086 simple_diagnostic_event *new_event
2087 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2088 m_events.safe_push (new_event);
2090 pp_clear_output_area (pp);
2092 return diagnostic_event_id_t (m_events.length () - 1);
2095 /* struct simple_diagnostic_event. */
2097 /* simple_diagnostic_event's ctor. */
2099 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2100 tree fndecl,
2101 int depth,
2102 const char *desc)
2103 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2107 /* simple_diagnostic_event's dtor. */
2109 simple_diagnostic_event::~simple_diagnostic_event ()
2111 free (m_desc);
2114 /* Print PATH by emitting a dummy "note" associated with it. */
2116 DEBUG_FUNCTION
2117 void debug (diagnostic_path *path)
2119 rich_location richloc (line_table, UNKNOWN_LOCATION);
2120 richloc.set_path (path);
2121 inform (&richloc, "debug path");
2124 /* Really call the system 'abort'. This has to go right at the end of
2125 this file, so that there are no functions after it that call abort
2126 and get the system abort instead of our macro. */
2127 #undef abort
2128 static void
2129 real_abort (void)
2131 abort ();
2134 #if CHECKING_P
2136 namespace selftest {
2138 /* Helper function for test_print_escaped_string. */
2140 static void
2141 assert_print_escaped_string (const location &loc, const char *expected_output,
2142 const char *input)
2144 pretty_printer pp;
2145 print_escaped_string (&pp, input);
2146 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2149 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2150 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2152 /* Tests of print_escaped_string. */
2154 static void
2155 test_print_escaped_string ()
2157 /* Empty string. */
2158 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2160 /* Non-empty string. */
2161 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2163 /* Various things that need to be escaped: */
2164 /* Backslash. */
2165 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2166 "before\\after");
2167 /* Tab. */
2168 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2169 "before\tafter");
2170 /* Newline. */
2171 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2172 "before\nafter");
2173 /* Double quote. */
2174 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2175 "before\"after");
2177 /* Non-printable characters: BEL: '\a': 0x07 */
2178 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2179 "before\aafter");
2180 /* Non-printable characters: vertical tab: '\v': 0x0b */
2181 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2182 "before\vafter");
2185 /* Tests of print_parseable_fixits. */
2187 /* Verify that print_parseable_fixits emits the empty string if there
2188 are no fixits. */
2190 static void
2191 test_print_parseable_fixits_none ()
2193 pretty_printer pp;
2194 rich_location richloc (line_table, UNKNOWN_LOCATION);
2196 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2197 ASSERT_STREQ ("", pp_formatted_text (&pp));
2200 /* Verify that print_parseable_fixits does the right thing if there
2201 is an insertion fixit hint. */
2203 static void
2204 test_print_parseable_fixits_insert ()
2206 pretty_printer pp;
2207 rich_location richloc (line_table, UNKNOWN_LOCATION);
2209 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2210 linemap_line_start (line_table, 5, 100);
2211 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2212 location_t where = linemap_position_for_column (line_table, 10);
2213 richloc.add_fixit_insert_before (where, "added content");
2215 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2216 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2217 pp_formatted_text (&pp));
2220 /* Verify that print_parseable_fixits does the right thing if there
2221 is an removal fixit hint. */
2223 static void
2224 test_print_parseable_fixits_remove ()
2226 pretty_printer pp;
2227 rich_location richloc (line_table, UNKNOWN_LOCATION);
2229 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2230 linemap_line_start (line_table, 5, 100);
2231 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2232 source_range where;
2233 where.m_start = linemap_position_for_column (line_table, 10);
2234 where.m_finish = linemap_position_for_column (line_table, 20);
2235 richloc.add_fixit_remove (where);
2237 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2238 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2239 pp_formatted_text (&pp));
2242 /* Verify that print_parseable_fixits does the right thing if there
2243 is an replacement fixit hint. */
2245 static void
2246 test_print_parseable_fixits_replace ()
2248 pretty_printer pp;
2249 rich_location richloc (line_table, UNKNOWN_LOCATION);
2251 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2252 linemap_line_start (line_table, 5, 100);
2253 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2254 source_range where;
2255 where.m_start = linemap_position_for_column (line_table, 10);
2256 where.m_finish = linemap_position_for_column (line_table, 20);
2257 richloc.add_fixit_replace (where, "replacement");
2259 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2260 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2261 pp_formatted_text (&pp));
2264 /* Verify that print_parseable_fixits correctly handles
2265 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2267 static void
2268 test_print_parseable_fixits_bytes_vs_display_columns ()
2270 line_table_test ltt;
2271 rich_location richloc (line_table, UNKNOWN_LOCATION);
2273 /* 1-based byte offsets: 12345677778888999900001234567. */
2274 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2275 /* 1-based display cols: 123456[......7-8.....]9012345. */
2276 const int tabstop = 8;
2278 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2279 const char *const fname = tmp.get_filename ();
2281 linemap_add (line_table, LC_ENTER, false, fname, 0);
2282 linemap_line_start (line_table, 1, 100);
2283 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2284 source_range where;
2285 where.m_start = linemap_position_for_column (line_table, 12);
2286 where.m_finish = linemap_position_for_column (line_table, 17);
2287 richloc.add_fixit_replace (where, "color");
2289 /* Escape fname. */
2290 pretty_printer tmp_pp;
2291 print_escaped_string (&tmp_pp, fname);
2292 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2294 const int buf_len = strlen (escaped_fname) + 100;
2295 char *const expected = XNEWVEC (char, buf_len);
2298 pretty_printer pp;
2299 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2300 tabstop);
2301 snprintf (expected, buf_len,
2302 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2303 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2306 pretty_printer pp;
2307 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2308 tabstop);
2309 snprintf (expected, buf_len,
2310 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2311 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2314 XDELETEVEC (expected);
2315 free (escaped_fname);
2318 /* Verify that
2319 diagnostic_get_location_text (..., SHOW_COLUMN)
2320 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2321 colorization disabled. */
2323 static void
2324 assert_location_text (const char *expected_loc_text,
2325 const char *filename, int line, int column,
2326 bool show_column,
2327 int origin = 1,
2328 enum diagnostics_column_unit column_unit
2329 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2331 test_diagnostic_context dc;
2332 dc.show_column = show_column;
2333 dc.column_unit = column_unit;
2334 dc.column_origin = origin;
2336 expanded_location xloc;
2337 xloc.file = filename;
2338 xloc.line = line;
2339 xloc.column = column;
2340 xloc.data = NULL;
2341 xloc.sysp = false;
2343 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2344 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2345 free (actual_loc_text);
2348 /* Verify that diagnostic_get_location_text works as expected. */
2350 static void
2351 test_diagnostic_get_location_text ()
2353 const char *old_progname = progname;
2354 progname = "PROGNAME";
2355 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2356 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2357 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2358 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2359 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2360 for (int origin = 0; origin != 2; ++origin)
2361 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2362 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2363 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2364 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2366 maybe_line_and_column (INT_MAX, INT_MAX);
2367 maybe_line_and_column (INT_MIN, INT_MIN);
2370 /* In order to test display columns vs byte columns, we need to create a
2371 file for location_get_source_line() to read. */
2373 const char *const content = "smile \xf0\x9f\x98\x82\n";
2374 const int line_bytes = strlen (content) - 1;
2375 const int def_tabstop = 8;
2376 const int display_width = cpp_display_width (content, line_bytes,
2377 def_tabstop);
2378 ASSERT_EQ (line_bytes - 2, display_width);
2379 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2380 const char *const fname = tmp.get_filename ();
2381 const int buf_len = strlen (fname) + 16;
2382 char *const expected = XNEWVEC (char, buf_len);
2384 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2385 assert_location_text (expected, fname, 1, line_bytes, true,
2386 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2388 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2389 assert_location_text (expected, fname, 1, line_bytes, true,
2390 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2392 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2393 assert_location_text (expected, fname, 1, line_bytes, true,
2394 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2396 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2397 assert_location_text (expected, fname, 1, line_bytes, true,
2398 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2400 XDELETEVEC (expected);
2404 progname = old_progname;
2407 /* Selftest for num_digits. */
2409 static void
2410 test_num_digits ()
2412 ASSERT_EQ (1, num_digits (0));
2413 ASSERT_EQ (1, num_digits (9));
2414 ASSERT_EQ (2, num_digits (10));
2415 ASSERT_EQ (2, num_digits (99));
2416 ASSERT_EQ (3, num_digits (100));
2417 ASSERT_EQ (3, num_digits (999));
2418 ASSERT_EQ (4, num_digits (1000));
2419 ASSERT_EQ (4, num_digits (9999));
2420 ASSERT_EQ (5, num_digits (10000));
2421 ASSERT_EQ (5, num_digits (99999));
2422 ASSERT_EQ (6, num_digits (100000));
2423 ASSERT_EQ (6, num_digits (999999));
2424 ASSERT_EQ (7, num_digits (1000000));
2425 ASSERT_EQ (7, num_digits (9999999));
2426 ASSERT_EQ (8, num_digits (10000000));
2427 ASSERT_EQ (8, num_digits (99999999));
2430 /* Run all of the selftests within this file. */
2432 void
2433 diagnostic_c_tests ()
2435 test_print_escaped_string ();
2436 test_print_parseable_fixits_none ();
2437 test_print_parseable_fixits_insert ();
2438 test_print_parseable_fixits_remove ();
2439 test_print_parseable_fixits_replace ();
2440 test_print_parseable_fixits_bytes_vs_display_columns ();
2441 test_diagnostic_get_location_text ();
2442 test_num_digits ();
2446 } // namespace selftest
2448 #endif /* #if CHECKING_P */
2450 #if __GNUC__ >= 10
2451 # pragma GCC diagnostic pop
2452 #endif