struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / support / cpp / gcc / diagnostic.cc
blob5ec6742bdc0153a83a0054ff59830ce34827c648
1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2022 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
22 /* This file implements the language independent aspect of diagnostic
23 message module. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "version.h"
29 #include "demangle.h"
30 #include "intl.h"
31 #include "backtrace.h"
32 #include "diagnostic.h"
33 #include "diagnostic-color.h"
34 #include "diagnostic-url.h"
35 #include "diagnostic-metadata.h"
36 #include "diagnostic-path.h"
37 #include "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);
108 /* Return the value of the getenv("COLUMNS") as an integer. If the
109 value is not set to a positive integer, use ioctl to get the
110 terminal width. If it fails, return INT_MAX. */
112 get_terminal_width (void)
114 const char * s = getenv ("COLUMNS");
115 if (s != NULL) {
116 int n = atoi (s);
117 if (n > 0)
118 return n;
121 #ifdef TIOCGWINSZ
122 struct winsize w;
123 w.ws_col = 0;
124 if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
125 return w.ws_col;
126 #endif
128 return INT_MAX;
131 /* Set caret_max_width to value. */
132 void
133 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
135 /* One minus to account for the leading empty space. */
136 value = value ? value - 1
137 : (isatty (fileno (pp_buffer (context->printer)->stream))
138 ? get_terminal_width () - 1: INT_MAX);
140 if (value <= 0)
141 value = INT_MAX;
143 context->caret_max_width = value;
146 /* Default implementation of final_cb. */
148 static void
149 default_diagnostic_final_cb (diagnostic_context *context)
151 /* Some of the errors may actually have been warnings. */
152 if (diagnostic_kind_count (context, DK_WERROR))
154 /* -Werror was given. */
155 if (context->warning_as_error_requested)
156 pp_verbatim (context->printer,
157 _("%s: all warnings being treated as errors"),
158 progname);
159 /* At least one -Werror= was given. */
160 else
161 pp_verbatim (context->printer,
162 _("%s: some warnings being treated as errors"),
163 progname);
164 pp_newline_and_flush (context->printer);
168 /* Initialize the diagnostic message outputting machinery. */
169 void
170 diagnostic_initialize (diagnostic_context *context, int n_opts)
172 int i;
174 /* Allocate a basic pretty-printer. Clients will replace this a
175 much more elaborated pretty-printer if they wish. */
176 context->printer = XNEW (pretty_printer);
177 new (context->printer) pretty_printer ();
179 memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
180 context->warning_as_error_requested = false;
181 context->n_opts = n_opts;
182 context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
183 for (i = 0; i < n_opts; i++)
184 context->classify_diagnostic[i] = DK_UNSPECIFIED;
185 context->show_caret = false;
186 diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
187 for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
188 context->caret_chars[i] = '^';
189 context->show_cwe = false;
190 context->path_format = DPF_NONE;
191 context->show_path_depths = false;
192 context->show_option_requested = false;
193 context->abort_on_error = false;
194 context->show_column = false;
195 context->pedantic_errors = false;
196 context->permissive = false;
197 context->opt_permissive = 0;
198 context->fatal_errors = false;
199 context->dc_inhibit_warnings = false;
200 context->dc_warn_system_headers = false;
201 context->max_errors = 0;
202 context->internal_error = NULL;
203 diagnostic_starter (context) = default_diagnostic_starter;
204 context->start_span = default_diagnostic_start_span_fn;
205 diagnostic_finalizer (context) = default_diagnostic_finalizer;
206 context->option_enabled = NULL;
207 context->option_state = NULL;
208 context->option_name = NULL;
209 context->get_option_url = NULL;
210 context->last_location = UNKNOWN_LOCATION;
211 context->last_module = 0;
212 context->x_data = NULL;
213 context->lock = 0;
214 context->inhibit_notes_p = false;
215 context->colorize_source_p = false;
216 context->show_labels_p = false;
217 context->show_line_numbers_p = false;
218 context->min_margin_width = 0;
219 context->show_ruler_p = false;
220 context->report_bug = 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;
240 context->includes_seen = NULL;
243 /* Maybe initialize the color support. We require clients to do this
244 explicitly, since most clients don't want color. When called
245 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
247 void
248 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
250 /* value == -1 is the default value. */
251 if (value < 0)
253 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
254 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
255 otherwise default to -fdiagnostics-color=never, for other
256 values default to that
257 -fdiagnostics-color={never,auto,always}. */
258 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
260 if (!getenv ("GCC_COLORS"))
261 return;
262 value = DIAGNOSTICS_COLOR_AUTO;
264 else
265 value = DIAGNOSTICS_COLOR_DEFAULT;
267 pp_show_color (context->printer)
268 = colorize_init ((diagnostic_color_rule_t) value);
271 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
273 void
274 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
276 /* value == -1 is the default value. */
277 if (value < 0)
279 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
280 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
281 environment, otherwise default to -fdiagnostics-urls=never,
282 for other values default to that
283 -fdiagnostics-urls={never,auto,always}. */
284 if (DIAGNOSTICS_URLS_DEFAULT == -1)
286 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
287 return;
288 value = DIAGNOSTICS_URL_AUTO;
290 else
291 value = DIAGNOSTICS_URLS_DEFAULT;
294 context->printer->url_format
295 = determine_url_format ((diagnostic_url_rule_t) value);
298 /* Create the file_cache, if not already created, and tell it how to
299 translate files on input. */
300 void diagnostic_initialize_input_context (diagnostic_context *context,
301 diagnostic_input_charset_callback ccb,
302 bool should_skip_bom)
304 if (!context->m_file_cache)
305 context->m_file_cache = new file_cache;
306 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
309 /* Do any cleaning up required after the last diagnostic is emitted. */
311 void
312 diagnostic_finish (diagnostic_context *context)
314 if (context->final_cb)
315 context->final_cb (context);
317 diagnostic_file_cache_fini ();
319 XDELETEVEC (context->classify_diagnostic);
320 context->classify_diagnostic = NULL;
322 /* diagnostic_initialize allocates context->printer using XNEW
323 and placement-new. */
324 context->printer->~pretty_printer ();
325 XDELETE (context->printer);
326 context->printer = NULL;
328 if (context->edit_context_ptr)
330 delete context->edit_context_ptr;
331 context->edit_context_ptr = NULL;
334 if (context->includes_seen)
336 delete context->includes_seen;
337 context->includes_seen = nullptr;
341 /* Initialize DIAGNOSTIC, where the message MSG has already been
342 translated. */
343 void
344 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
345 va_list *args, rich_location *richloc,
346 diagnostic_t kind)
348 gcc_assert (richloc);
349 diagnostic->message.err_no = errno;
350 diagnostic->message.args_ptr = args;
351 diagnostic->message.format_spec = msg;
352 diagnostic->message.m_richloc = richloc;
353 diagnostic->richloc = richloc;
354 diagnostic->metadata = NULL;
355 diagnostic->kind = kind;
356 diagnostic->option_index = 0;
359 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
360 translated. */
361 void
362 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
363 va_list *args, rich_location *richloc,
364 diagnostic_t kind)
366 gcc_assert (richloc);
367 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
370 static const char *const diagnostic_kind_color[] = {
371 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
372 #include "diagnostic.def"
373 #undef DEFINE_DIAGNOSTIC_KIND
374 NULL
377 /* Get a color name for diagnostics of type KIND
378 Result could be NULL. */
380 const char *
381 diagnostic_get_color_for_kind (diagnostic_t kind)
383 return diagnostic_kind_color[kind];
386 /* Given an expanded_location, convert the column (which is in 1-based bytes)
387 to the requested units, without converting the origin.
388 Return -1 if the column is invalid (<= 0). */
390 static int
391 convert_column_unit (enum diagnostics_column_unit column_unit,
392 int tabstop,
393 expanded_location s)
395 if (s.column <= 0)
396 return -1;
398 switch (column_unit)
400 default:
401 gcc_unreachable ();
403 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
405 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
406 return location_compute_display_column (s, policy);
409 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
410 return s.column;
414 /* Given an expanded_location, convert the column (which is in 1-based bytes)
415 to the requested units and origin. Return -1 if the column is
416 invalid (<= 0). */
418 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
420 int one_based_col
421 = convert_column_unit (context->column_unit, context->tabstop, s);
422 if (one_based_col <= 0)
423 return -1;
424 return one_based_col + (context->column_origin - 1);
427 /* Return a formatted line and column ':%line:%column'. Elided if
428 line == 0 or col < 0. (A column of 0 may be valid due to the
429 -fdiagnostics-column-origin option.)
430 The result is a statically allocated buffer. */
432 static const char *
433 maybe_line_and_column (int line, int col)
435 static char result[32];
437 if (line)
439 size_t l
440 = snprintf (result, sizeof (result),
441 col >= 0 ? ":%d:%d" : ":%d", line, col);
442 gcc_checking_assert (l < sizeof (result));
444 else
445 result[0] = 0;
446 return result;
449 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
450 The caller is responsible for freeing the memory. */
452 static char *
453 diagnostic_get_location_text (diagnostic_context *context,
454 expanded_location s)
456 pretty_printer *pp = context->printer;
457 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
458 const char *locus_ce = colorize_stop (pp_show_color (pp));
459 const char *file = s.file ? s.file : progname;
460 int line = 0;
461 int col = -1;
462 if (strcmp (file, N_("<built-in>")))
464 line = s.line;
465 if (context->show_column)
466 col = diagnostic_converted_column (context, s);
469 const char *line_col = maybe_line_and_column (line, col);
470 return build_message_string ("%s%s%s:%s", locus_cs, file,
471 line_col, locus_ce);
474 static const char *const diagnostic_kind_text[] = {
475 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
476 #include "diagnostic.def"
477 #undef DEFINE_DIAGNOSTIC_KIND
478 "must-not-happen"
481 /* Return a malloc'd string describing a location and the severity of the
482 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
483 freeing the memory. */
484 char *
485 diagnostic_build_prefix (diagnostic_context *context,
486 const diagnostic_info *diagnostic)
488 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
490 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
491 const char *text_cs = "", *text_ce = "";
492 pretty_printer *pp = context->printer;
494 if (diagnostic_kind_color[diagnostic->kind])
496 text_cs = colorize_start (pp_show_color (pp),
497 diagnostic_kind_color[diagnostic->kind]);
498 text_ce = colorize_stop (pp_show_color (pp));
501 expanded_location s = diagnostic_expand_location (diagnostic);
502 char *location_text = diagnostic_get_location_text (context, s);
504 char *result = build_message_string ("%s %s%s%s", location_text,
505 text_cs, text, text_ce);
506 free (location_text);
507 return result;
510 /* Functions at which to stop the backtrace print. It's not
511 particularly helpful to print the callers of these functions. */
513 static const char * const bt_stop[] =
515 "main",
516 "toplev::main",
517 "execute_one_pass",
518 "compile_file",
521 /* A callback function passed to the backtrace_full function. */
523 static int
524 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
525 const char *function)
527 int *pcount = (int *) data;
529 /* If we don't have any useful information, don't print
530 anything. */
531 if (filename == NULL && function == NULL)
532 return 0;
534 /* Skip functions in diagnostic.cc. */
535 if (*pcount == 0
536 && filename != NULL
537 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
538 return 0;
540 /* Print up to 20 functions. We could make this a --param, but
541 since this is only for debugging just use a constant for now. */
542 if (*pcount >= 20)
544 /* Returning a non-zero value stops the backtrace. */
545 return 1;
547 ++*pcount;
549 char *alc = NULL;
550 if (function != NULL)
552 char *str = cplus_demangle_v3 (function,
553 (DMGL_VERBOSE | DMGL_ANSI
554 | DMGL_GNU_V3 | DMGL_PARAMS));
555 if (str != NULL)
557 alc = str;
558 function = str;
561 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
563 size_t len = strlen (bt_stop[i]);
564 if (strncmp (function, bt_stop[i], len) == 0
565 && (function[len] == '\0' || function[len] == '('))
567 if (alc != NULL)
568 free (alc);
569 /* Returning a non-zero value stops the backtrace. */
570 return 1;
575 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
576 (unsigned long) pc,
577 function == NULL ? "???" : function,
578 filename == NULL ? "???" : filename,
579 lineno);
581 if (alc != NULL)
582 free (alc);
584 return 0;
587 /* A callback function passed to the backtrace_full function. This is
588 called if backtrace_full has an error. */
590 static void
591 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
593 if (errnum < 0)
595 /* This means that no debug info was available. Just quietly
596 skip printing backtrace info. */
597 return;
599 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
600 errnum == 0 ? "" : xstrerror (errnum));
603 /* Check if we've met the maximum error limit, and if so fatally exit
604 with a message. CONTEXT is the context to check, and FLUSH
605 indicates whether a diagnostic_finish call is needed. */
607 void
608 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
610 if (!context->max_errors)
611 return;
613 int count = (diagnostic_kind_count (context, DK_ERROR)
614 + diagnostic_kind_count (context, DK_SORRY)
615 + diagnostic_kind_count (context, DK_WERROR));
617 if (count >= context->max_errors)
619 fnotice (stderr,
620 "compilation terminated due to -fmax-errors=%u.\n",
621 context->max_errors);
622 if (flush)
623 diagnostic_finish (context);
624 exit (FATAL_EXIT_CODE);
628 /* Take any action which is expected to happen after the diagnostic
629 is written out. This function does not always return. */
630 void
631 diagnostic_action_after_output (diagnostic_context *context,
632 diagnostic_t diag_kind)
634 switch (diag_kind)
636 case DK_DEBUG:
637 case DK_NOTE:
638 case DK_ANACHRONISM:
639 case DK_WARNING:
640 break;
642 case DK_ERROR:
643 case DK_SORRY:
644 if (context->abort_on_error)
645 real_abort ();
646 if (context->fatal_errors)
648 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
649 diagnostic_finish (context);
650 exit (FATAL_EXIT_CODE);
652 break;
654 case DK_ICE:
655 case DK_ICE_NOBT:
657 struct backtrace_state *state = NULL;
658 if (diag_kind == DK_ICE)
659 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
660 int count = 0;
661 if (state != NULL)
662 backtrace_full (state, 2, bt_callback, bt_err_callback,
663 (void *) &count);
665 if (context->abort_on_error)
666 real_abort ();
668 if (context->report_bug)
669 fnotice (stderr, "Please submit a full bug report, "
670 "with preprocessed source.\n");
671 else
672 fnotice (stderr, "Please submit a full bug report, "
673 "with preprocessed source (by using -freport-bug).\n");
675 if (count > 0)
676 fnotice (stderr, "Please include the complete backtrace "
677 "with any bug report.\n");
678 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
680 exit (ICE_EXIT_CODE);
683 case DK_FATAL:
684 if (context->abort_on_error)
685 real_abort ();
686 diagnostic_finish (context);
687 fnotice (stderr, "compilation terminated.\n");
688 exit (FATAL_EXIT_CODE);
690 default:
691 gcc_unreachable ();
695 /* True if the last module or file in which a diagnostic was reported is
696 different from the current one. */
698 static bool
699 last_module_changed_p (diagnostic_context *context,
700 const line_map_ordinary *map)
702 return context->last_module != map;
705 /* Remember the current module or file as being the last one in which we
706 report a diagnostic. */
708 static void
709 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
711 context->last_module = map;
714 /* Only dump the "In file included from..." stack once for each file. */
716 static bool
717 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
719 /* No include path for main. */
720 if (MAIN_FILE_P (map))
721 return true;
723 /* Always identify C++ modules, at least for now. */
724 auto probe = map;
725 if (linemap_check_ordinary (map)->reason == LC_RENAME)
726 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
727 probe = linemap_included_from_linemap (line_table, map);
728 if (MAP_MODULE_P (probe))
729 return false;
731 if (!context->includes_seen)
732 context->includes_seen = new hash_set<location_t, false, location_hash>;
734 /* Hash the location of the #include directive to better handle files
735 that are included multiple times with different macros defined. */
736 return context->includes_seen->add (linemap_included_from (map));
739 void
740 diagnostic_report_current_module (diagnostic_context *context, location_t where)
742 const line_map_ordinary *map = NULL;
744 if (pp_needs_newline (context->printer))
746 pp_newline (context->printer);
747 pp_needs_newline (context->printer) = false;
750 if (where <= BUILTINS_LOCATION)
751 return;
753 linemap_resolve_location (line_table, where,
754 LRK_MACRO_DEFINITION_LOCATION,
755 &map);
757 if (map && last_module_changed_p (context, map))
759 set_last_module (context, map);
760 if (!includes_seen (context, map))
762 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
763 expanded_location s = {};
766 where = linemap_included_from (map);
767 map = linemap_included_from_linemap (line_table, map);
768 bool is_module = MAP_MODULE_P (map);
769 s.file = LINEMAP_FILE (map);
770 s.line = SOURCE_LINE (map, where);
771 int col = -1;
772 if (first && context->show_column)
774 s.column = SOURCE_COLUMN (map, where);
775 col = diagnostic_converted_column (context, s);
777 const char *line_col = maybe_line_and_column (s.line, col);
778 static const char *const msgs[] =
780 NULL,
781 N_(" from"),
782 N_("In file included from"), /* 2 */
783 N_(" included from"),
784 N_("In module"), /* 4 */
785 N_("of module"),
786 N_("In module imported at"), /* 6 */
787 N_("imported at"),
790 unsigned index = (was_module ? 6 : is_module ? 4
791 : need_inc ? 2 : 0) + !first;
793 pp_verbatim (context->printer, "%s%s %r%s%s%R",
794 first ? "" : was_module ? ", " : ",\n",
795 _(msgs[index]),
796 "locus", s.file, line_col);
797 first = false, need_inc = was_module, was_module = is_module;
799 while (!includes_seen (context, map));
800 pp_verbatim (context->printer, ":");
801 pp_newline (context->printer);
806 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
807 print the path. */
809 void
810 diagnostic_show_any_path (diagnostic_context *context,
811 diagnostic_info *diagnostic)
813 const diagnostic_path *path = diagnostic->richloc->get_path ();
814 if (!path)
815 return;
817 if (context->print_path)
818 context->print_path (context, path);
821 /* Return true if the events in this path involve more than one
822 function, or false if it is purely intraprocedural. */
824 bool
825 diagnostic_path::interprocedural_p () const
827 const unsigned num = num_events ();
828 for (unsigned i = 0; i < num; i++)
830 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
831 return true;
832 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
833 return true;
835 return false;
838 void
839 default_diagnostic_starter (diagnostic_context *context,
840 diagnostic_info *diagnostic)
842 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
843 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
844 diagnostic));
847 void
848 default_diagnostic_start_span_fn (diagnostic_context *context,
849 expanded_location exploc)
851 char *text = diagnostic_get_location_text (context, exploc);
852 pp_string (context->printer, text);
853 free (text);
854 pp_newline (context->printer);
857 void
858 default_diagnostic_finalizer (diagnostic_context *context,
859 diagnostic_info *diagnostic,
860 diagnostic_t)
862 char *saved_prefix = pp_take_prefix (context->printer);
863 pp_set_prefix (context->printer, NULL);
864 pp_newline (context->printer);
865 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
866 pp_set_prefix (context->printer, saved_prefix);
867 pp_flush (context->printer);
870 /* Interface to specify diagnostic kind overrides. Returns the
871 previous setting, or DK_UNSPECIFIED if the parameters are out of
872 range. If OPTION_INDEX is zero, the new setting is for all the
873 diagnostics. */
874 diagnostic_t
875 diagnostic_classify_diagnostic (diagnostic_context *context,
876 int option_index,
877 diagnostic_t new_kind,
878 location_t where)
880 diagnostic_t old_kind;
882 if (option_index < 0
883 || option_index >= context->n_opts
884 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
885 return DK_UNSPECIFIED;
887 old_kind = context->classify_diagnostic[option_index];
889 /* Handle pragmas separately, since we need to keep track of *where*
890 the pragmas were. */
891 if (where != UNKNOWN_LOCATION)
893 int i;
895 /* Record the command-line status, so we can reset it back on DK_POP. */
896 if (old_kind == DK_UNSPECIFIED)
898 old_kind = !context->option_enabled (option_index,
899 context->lang_mask,
900 context->option_state)
901 ? DK_IGNORED : (context->warning_as_error_requested
902 ? DK_ERROR : DK_WARNING);
903 context->classify_diagnostic[option_index] = old_kind;
906 for (i = context->n_classification_history - 1; i >= 0; i --)
907 if (context->classification_history[i].option == option_index)
909 old_kind = context->classification_history[i].kind;
910 break;
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 = option_index;
919 context->classification_history[i].kind = new_kind;
920 context->n_classification_history ++;
922 else
923 context->classify_diagnostic[option_index] = new_kind;
925 return old_kind;
928 /* Save all diagnostic classifications in a stack. */
929 void
930 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
932 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
933 context->push_list[context->n_push ++] = context->n_classification_history;
936 /* Restore the topmost classification set off the stack. If the stack
937 is empty, revert to the state based on command line parameters. */
938 void
939 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
941 int jump_to;
942 int i;
944 if (context->n_push)
945 jump_to = context->push_list [-- context->n_push];
946 else
947 jump_to = 0;
949 i = context->n_classification_history;
950 context->classification_history =
951 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
952 * sizeof (diagnostic_classification_change_t));
953 context->classification_history[i].location = where;
954 context->classification_history[i].option = jump_to;
955 context->classification_history[i].kind = DK_POP;
956 context->n_classification_history ++;
959 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
960 escaping rules for -fdiagnostics-parseable-fixits. */
962 static void
963 print_escaped_string (pretty_printer *pp, const char *text)
965 gcc_assert (pp);
966 gcc_assert (text);
968 pp_character (pp, '"');
969 for (const char *ch = text; *ch; ch++)
971 switch (*ch)
973 case '\\':
974 /* Escape backslash as two backslashes. */
975 pp_string (pp, "\\\\");
976 break;
977 case '\t':
978 /* Escape tab as "\t". */
979 pp_string (pp, "\\t");
980 break;
981 case '\n':
982 /* Escape newline as "\n". */
983 pp_string (pp, "\\n");
984 break;
985 case '"':
986 /* Escape doublequotes as \". */
987 pp_string (pp, "\\\"");
988 break;
989 default:
990 if (ISPRINT (*ch))
991 pp_character (pp, *ch);
992 else
993 /* Use octal for non-printable chars. */
995 unsigned char c = (*ch & 0xff);
996 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
998 break;
1001 pp_character (pp, '"');
1004 /* Implementation of -fdiagnostics-parseable-fixits and
1005 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1006 Print a machine-parseable version of all fixits in RICHLOC to PP,
1007 using COLUMN_UNIT to express columns.
1008 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1010 static void
1011 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1012 enum diagnostics_column_unit column_unit,
1013 int tabstop)
1015 gcc_assert (pp);
1016 gcc_assert (richloc);
1018 char *saved_prefix = pp_take_prefix (pp);
1019 pp_set_prefix (pp, NULL);
1021 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1023 const fixit_hint *hint = richloc->get_fixit_hint (i);
1024 location_t start_loc = hint->get_start_loc ();
1025 expanded_location start_exploc = expand_location (start_loc);
1026 pp_string (pp, "fix-it:");
1027 print_escaped_string (pp, start_exploc.file);
1028 /* For compatibility with clang, print as a half-open range. */
1029 location_t next_loc = hint->get_next_loc ();
1030 expanded_location next_exploc = expand_location (next_loc);
1031 int start_col
1032 = convert_column_unit (column_unit, tabstop, start_exploc);
1033 int next_col
1034 = convert_column_unit (column_unit, tabstop, next_exploc);
1035 pp_printf (pp, ":{%i:%i-%i:%i}:",
1036 start_exploc.line, start_col,
1037 next_exploc.line, next_col);
1038 print_escaped_string (pp, hint->get_string ());
1039 pp_newline (pp);
1042 pp_set_prefix (pp, saved_prefix);
1045 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1047 static void
1048 get_any_inlining_info (diagnostic_context *context,
1049 diagnostic_info *diagnostic)
1051 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1053 if (context->set_locations_cb)
1054 /* Retrieve the locations into which the expression about to be
1055 diagnosed has been inlined, including those of all the callers
1056 all the way down the inlining stack. */
1057 context->set_locations_cb (context, diagnostic);
1058 else
1060 /* When there's no callback use just the one location provided
1061 by the caller of the diagnostic function. */
1062 location_t loc = diagnostic_location (diagnostic);
1063 ilocs.safe_push (loc);
1064 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1068 /* Update the kind of DIAGNOSTIC based on its location(s), including
1069 any of those in its inlining stack, relative to any
1070 #pragma GCC diagnostic
1071 directives recorded within CONTEXT.
1073 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1074 otherwise. */
1076 static diagnostic_t
1077 update_effective_level_from_pragmas (diagnostic_context *context,
1078 diagnostic_info *diagnostic)
1080 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1082 /* Ignore the diagnostic if all the inlined locations are
1083 in system headers and -Wno-system-headers is in effect. */
1084 diagnostic->kind = DK_IGNORED;
1085 return DK_IGNORED;
1088 if (context->n_classification_history <= 0)
1089 return DK_UNSPECIFIED;
1091 /* Iterate over the locations, checking the diagnostic disposition
1092 for the diagnostic at each. If it's explicitly set as opposed
1093 to unspecified, update the disposition for this instance of
1094 the diagnostic and return it. */
1095 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1097 /* FIXME: Stupid search. Optimize later. */
1098 for (int i = context->n_classification_history - 1; i >= 0; i --)
1100 const diagnostic_classification_change_t &hist
1101 = context->classification_history[i];
1103 location_t pragloc = hist.location;
1104 if (!linemap_location_before_p (line_table, pragloc, loc))
1105 continue;
1107 if (hist.kind == (int) DK_POP)
1109 /* Move on to the next region. */
1110 i = hist.option;
1111 continue;
1114 int option = hist.option;
1115 /* The option 0 is for all the diagnostics. */
1116 if (option == 0 || option == diagnostic->option_index)
1118 diagnostic_t kind = hist.kind;
1119 if (kind != DK_UNSPECIFIED)
1120 diagnostic->kind = kind;
1121 return kind;
1126 return DK_UNSPECIFIED;
1129 /* Generate a URL string describing CWE. The caller is responsible for
1130 freeing the string. */
1132 static char *
1133 get_cwe_url (int cwe)
1135 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1138 /* If DIAGNOSTIC has a CWE identifier, print it.
1140 For example, if the diagnostic metadata associates it with CWE-119,
1141 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1142 description of the security issue. */
1144 static void
1145 print_any_cwe (diagnostic_context *context,
1146 const diagnostic_info *diagnostic)
1148 if (diagnostic->metadata == NULL)
1149 return;
1151 int cwe = diagnostic->metadata->get_cwe ();
1152 if (cwe)
1154 pretty_printer *pp = context->printer;
1155 char *saved_prefix = pp_take_prefix (context->printer);
1156 pp_string (pp, " [");
1157 pp_string (pp, colorize_start (pp_show_color (pp),
1158 diagnostic_kind_color[diagnostic->kind]));
1159 if (pp->url_format != URL_FORMAT_NONE)
1161 char *cwe_url = get_cwe_url (cwe);
1162 pp_begin_url (pp, cwe_url);
1163 free (cwe_url);
1165 pp_printf (pp, "CWE-%i", cwe);
1166 pp_set_prefix (context->printer, saved_prefix);
1167 if (pp->url_format != URL_FORMAT_NONE)
1168 pp_end_url (pp);
1169 pp_string (pp, colorize_stop (pp_show_color (pp)));
1170 pp_character (pp, ']');
1174 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1175 printer, e.g. " [-Werror=uninitialized]".
1176 Subroutine of diagnostic_report_diagnostic. */
1178 static void
1179 print_option_information (diagnostic_context *context,
1180 const diagnostic_info *diagnostic,
1181 diagnostic_t orig_diag_kind)
1183 char *option_text;
1185 option_text = context->option_name (context, diagnostic->option_index,
1186 orig_diag_kind, diagnostic->kind);
1188 if (option_text)
1190 char *option_url = NULL;
1191 if (context->get_option_url
1192 && context->printer->url_format != URL_FORMAT_NONE)
1193 option_url = context->get_option_url (context,
1194 diagnostic->option_index);
1195 pretty_printer *pp = context->printer;
1196 pp_string (pp, " [");
1197 pp_string (pp, colorize_start (pp_show_color (pp),
1198 diagnostic_kind_color[diagnostic->kind]));
1199 if (option_url)
1200 pp_begin_url (pp, option_url);
1201 pp_string (pp, option_text);
1202 if (option_url)
1204 pp_end_url (pp);
1205 free (option_url);
1207 pp_string (pp, colorize_stop (pp_show_color (pp)));
1208 pp_character (pp, ']');
1209 free (option_text);
1213 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1214 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1216 static bool
1217 diagnostic_enabled (diagnostic_context *context,
1218 diagnostic_info *diagnostic)
1220 /* Update the inlining stack for this diagnostic. */
1221 get_any_inlining_info (context, diagnostic);
1223 /* Diagnostics with no option or -fpermissive are always enabled. */
1224 if (!diagnostic->option_index
1225 || diagnostic->option_index == permissive_error_option (context))
1226 return true;
1228 /* This tests if the user provided the appropriate -Wfoo or
1229 -Wno-foo option. */
1230 if (! context->option_enabled (diagnostic->option_index,
1231 context->lang_mask,
1232 context->option_state))
1233 return false;
1235 /* This tests for #pragma diagnostic changes. */
1236 diagnostic_t diag_class
1237 = update_effective_level_from_pragmas (context, diagnostic);
1239 /* This tests if the user provided the appropriate -Werror=foo
1240 option. */
1241 if (diag_class == DK_UNSPECIFIED
1242 && (context->classify_diagnostic[diagnostic->option_index]
1243 != DK_UNSPECIFIED))
1244 diagnostic->kind
1245 = context->classify_diagnostic[diagnostic->option_index];
1247 /* This allows for future extensions, like temporarily disabling
1248 warnings for ranges of source code. */
1249 if (diagnostic->kind == DK_IGNORED)
1250 return false;
1252 return true;
1255 /* Returns whether warning OPT is enabled at LOC. */
1257 bool
1258 warning_enabled_at (location_t loc, int opt)
1260 if (!diagnostic_report_warnings_p (global_dc, loc))
1261 return false;
1263 rich_location richloc (line_table, loc);
1264 diagnostic_info diagnostic = {};
1265 diagnostic.option_index = opt;
1266 diagnostic.richloc = &richloc;
1267 diagnostic.message.m_richloc = &richloc;
1268 diagnostic.kind = DK_WARNING;
1269 return diagnostic_enabled (global_dc, &diagnostic);
1272 /* Report a diagnostic message (an error or a warning) as specified by
1273 DC. This function is *the* subroutine in terms of which front-ends
1274 should implement their specific diagnostic handling modules. The
1275 front-end independent format specifiers are exactly those described
1276 in the documentation of output_format.
1277 Return true if a diagnostic was printed, false otherwise. */
1279 bool
1280 diagnostic_report_diagnostic (diagnostic_context *context,
1281 diagnostic_info *diagnostic)
1283 location_t location = diagnostic_location (diagnostic);
1284 diagnostic_t orig_diag_kind = diagnostic->kind;
1286 /* Give preference to being able to inhibit warnings, before they
1287 get reclassified to something else. */
1288 bool report_warning_p = true;
1289 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1291 if (context->dc_inhibit_warnings)
1292 return false;
1293 /* Remember the result of the overall system header warning setting
1294 but proceed to also check the inlining context. */
1295 report_warning_p = diagnostic_report_warnings_p (context, location);
1296 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1297 return false;
1300 if (diagnostic->kind == DK_PEDWARN)
1302 diagnostic->kind = pedantic_warning_kind (context);
1303 /* We do this to avoid giving the message for -pedantic-errors. */
1304 orig_diag_kind = diagnostic->kind;
1307 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1308 return false;
1310 if (context->lock > 0)
1312 /* If we're reporting an ICE in the middle of some other error,
1313 try to flush out the previous error, then let this one
1314 through. Don't do this more than once. */
1315 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1316 && context->lock == 1)
1317 pp_newline_and_flush (context->printer);
1318 else
1319 error_recursion (context);
1322 /* If the user requested that warnings be treated as errors, so be
1323 it. Note that we do this before the next block so that
1324 individual warnings can be overridden back to warnings with
1325 -Wno-error=*. */
1326 if (context->warning_as_error_requested
1327 && diagnostic->kind == DK_WARNING)
1328 diagnostic->kind = DK_ERROR;
1330 diagnostic->message.x_data = &diagnostic->x_data;
1332 /* Check to see if the diagnostic is enabled at the location and
1333 not disabled by #pragma GCC diagnostic anywhere along the inlining
1334 stack. . */
1335 if (!diagnostic_enabled (context, diagnostic))
1336 return false;
1338 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1339 /* Bail if the warning is not to be reported because all locations
1340 in the inlining stack (if there is one) are in system headers. */
1341 return false;
1343 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1344 diagnostic_check_max_errors (context);
1346 context->lock++;
1348 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1350 /* When not checking, ICEs are converted to fatal errors when an
1351 error has already occurred. This is counteracted by
1352 abort_on_error. */
1353 if (!CHECKING_P
1354 && (diagnostic_kind_count (context, DK_ERROR) > 0
1355 || diagnostic_kind_count (context, DK_SORRY) > 0)
1356 && !context->abort_on_error)
1358 expanded_location s
1359 = expand_location (diagnostic_location (diagnostic));
1360 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1361 s.file, s.line);
1362 exit (ICE_EXIT_CODE);
1364 if (context->internal_error)
1365 (*context->internal_error) (context,
1366 diagnostic->message.format_spec,
1367 diagnostic->message.args_ptr);
1369 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1370 ++diagnostic_kind_count (context, DK_WERROR);
1371 else
1372 ++diagnostic_kind_count (context, diagnostic->kind);
1374 /* Is this the initial diagnostic within the stack of groups? */
1375 if (context->diagnostic_group_emission_count == 0)
1377 if (context->begin_group_cb)
1378 context->begin_group_cb (context);
1380 context->diagnostic_group_emission_count++;
1382 pp_format (context->printer, &diagnostic->message);
1383 (*diagnostic_starter (context)) (context, diagnostic);
1384 pp_output_formatted_text (context->printer);
1385 if (context->show_cwe)
1386 print_any_cwe (context, diagnostic);
1387 if (context->show_option_requested)
1388 print_option_information (context, diagnostic, orig_diag_kind);
1389 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1390 switch (context->extra_output_kind)
1392 default:
1393 break;
1394 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1395 print_parseable_fixits (context->printer, diagnostic->richloc,
1396 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1397 context->tabstop);
1398 pp_flush (context->printer);
1399 break;
1400 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1401 print_parseable_fixits (context->printer, diagnostic->richloc,
1402 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1403 context->tabstop);
1404 pp_flush (context->printer);
1405 break;
1407 diagnostic_action_after_output (context, diagnostic->kind);
1408 diagnostic->x_data = NULL;
1410 if (context->edit_context_ptr)
1411 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1412 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1414 context->lock--;
1416 diagnostic_show_any_path (context, diagnostic);
1418 return true;
1421 /* Get the number of digits in the decimal representation of VALUE. */
1424 num_digits (int value)
1426 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1427 using floating point. */
1428 gcc_assert (value >= 0);
1430 if (value == 0)
1431 return 1;
1433 int digits = 0;
1434 while (value > 0)
1436 digits++;
1437 value /= 10;
1439 return digits;
1442 /* Given a partial pathname as input, return another pathname that
1443 shares no directory elements with the pathname of __FILE__. This
1444 is used by fancy_abort() to print `internal compiler error in expr.cc'
1445 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1447 const char *
1448 trim_filename (const char *name)
1450 static const char this_file[] = __FILE__;
1451 const char *p = name, *q = this_file;
1453 /* First skip any "../" in each filename. This allows us to give a proper
1454 reference to a file in a subdirectory. */
1455 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1456 p += 3;
1458 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1459 q += 3;
1461 /* Now skip any parts the two filenames have in common. */
1462 while (*p == *q && *p != 0 && *q != 0)
1463 p++, q++;
1465 /* Now go backwards until the previous directory separator. */
1466 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1467 p--;
1469 return p;
1472 /* Standard error reporting routines in increasing order of severity.
1473 All of these take arguments like printf. */
1475 /* Text to be emitted verbatim to the error message stream; this
1476 produces no prefix and disables line-wrapping. Use rarely. */
1477 void
1478 verbatim (const char *gmsgid, ...)
1480 text_info text;
1481 va_list ap;
1483 va_start (ap, gmsgid);
1484 text.err_no = errno;
1485 text.args_ptr = &ap;
1486 text.format_spec = _(gmsgid);
1487 text.x_data = NULL;
1488 pp_format_verbatim (global_dc->printer, &text);
1489 pp_newline_and_flush (global_dc->printer);
1490 va_end (ap);
1493 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1494 void
1495 diagnostic_append_note (diagnostic_context *context,
1496 location_t location,
1497 const char * gmsgid, ...)
1499 diagnostic_info diagnostic;
1500 va_list ap;
1501 rich_location richloc (line_table, location);
1503 va_start (ap, gmsgid);
1504 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1505 if (context->inhibit_notes_p)
1507 va_end (ap);
1508 return;
1510 char *saved_prefix = pp_take_prefix (context->printer);
1511 pp_set_prefix (context->printer,
1512 diagnostic_build_prefix (context, &diagnostic));
1513 pp_format (context->printer, &diagnostic.message);
1514 pp_output_formatted_text (context->printer);
1515 pp_destroy_prefix (context->printer);
1516 pp_set_prefix (context->printer, saved_prefix);
1517 pp_newline (context->printer);
1518 diagnostic_show_locus (context, &richloc, DK_NOTE);
1519 va_end (ap);
1522 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1523 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1524 and internal_error_no_backtrace, as documented and defined below. */
1525 static bool
1526 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1527 int opt, const char *gmsgid,
1528 va_list *ap, diagnostic_t kind)
1530 diagnostic_info diagnostic;
1531 if (kind == DK_PERMERROR)
1533 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1534 permissive_error_kind (global_dc));
1535 diagnostic.option_index = permissive_error_option (global_dc);
1537 else
1539 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1540 if (kind == DK_WARNING || kind == DK_PEDWARN)
1541 diagnostic.option_index = opt;
1543 diagnostic.metadata = metadata;
1544 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1547 /* Implement inform_n, warning_n, and error_n, as documented and
1548 defined below. */
1549 static bool
1550 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1551 int opt, unsigned HOST_WIDE_INT n,
1552 const char *singular_gmsgid,
1553 const char *plural_gmsgid,
1554 va_list *ap, diagnostic_t kind)
1556 diagnostic_info diagnostic;
1557 unsigned long gtn;
1559 if (sizeof n <= sizeof gtn)
1560 gtn = n;
1561 else
1562 /* Use the largest number ngettext can handle, otherwise
1563 preserve the six least significant decimal digits for
1564 languages where the plural form depends on them. */
1565 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1567 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1568 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1569 if (kind == DK_WARNING)
1570 diagnostic.option_index = opt;
1571 diagnostic.metadata = metadata;
1572 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1575 /* Wrapper around diagnostic_impl taking a variable argument list. */
1577 bool
1578 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1579 const char *gmsgid, ...)
1581 auto_diagnostic_group d;
1582 va_list ap;
1583 va_start (ap, gmsgid);
1584 rich_location richloc (line_table, location);
1585 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1586 va_end (ap);
1587 return ret;
1590 /* As above, but for rich_location *. */
1592 bool
1593 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1594 const char *gmsgid, ...)
1596 auto_diagnostic_group d;
1597 va_list ap;
1598 va_start (ap, gmsgid);
1599 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1600 va_end (ap);
1601 return ret;
1604 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1606 bool
1607 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1608 const char *gmsgid, va_list *ap)
1610 rich_location richloc (line_table, location);
1611 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1614 /* An informative note at LOCATION. Use this for additional details on an error
1615 message. */
1616 void
1617 inform (location_t location, const char *gmsgid, ...)
1619 auto_diagnostic_group d;
1620 va_list ap;
1621 va_start (ap, gmsgid);
1622 rich_location richloc (line_table, location);
1623 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1624 va_end (ap);
1627 /* Same as "inform" above, but at RICHLOC. */
1628 void
1629 inform (rich_location *richloc, const char *gmsgid, ...)
1631 gcc_assert (richloc);
1633 auto_diagnostic_group d;
1634 va_list ap;
1635 va_start (ap, gmsgid);
1636 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1637 va_end (ap);
1640 /* An informative note at LOCATION. Use this for additional details on an
1641 error message. */
1642 void
1643 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1644 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1646 va_list ap;
1647 va_start (ap, plural_gmsgid);
1648 auto_diagnostic_group d;
1649 rich_location richloc (line_table, location);
1650 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1651 &ap, DK_NOTE);
1652 va_end (ap);
1655 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1656 to the relevant language specification but is likely to be buggy anyway.
1657 Returns true if the warning was printed, false if it was inhibited. */
1658 bool
1659 warning (int opt, const char *gmsgid, ...)
1661 auto_diagnostic_group d;
1662 va_list ap;
1663 va_start (ap, gmsgid);
1664 rich_location richloc (line_table, input_location);
1665 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1666 va_end (ap);
1667 return ret;
1670 /* A warning at LOCATION. Use this for code which is correct according to the
1671 relevant language specification but is likely to be buggy anyway.
1672 Returns true if the warning was printed, false if it was inhibited. */
1674 bool
1675 warning_at (location_t location, int opt, const char *gmsgid, ...)
1677 auto_diagnostic_group d;
1678 va_list ap;
1679 va_start (ap, gmsgid);
1680 rich_location richloc (line_table, location);
1681 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1682 va_end (ap);
1683 return ret;
1686 /* Same as "warning at" above, but using RICHLOC. */
1688 bool
1689 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1691 gcc_assert (richloc);
1693 auto_diagnostic_group d;
1694 va_list ap;
1695 va_start (ap, gmsgid);
1696 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1697 va_end (ap);
1698 return ret;
1701 /* Same as "warning at" above, but using METADATA. */
1703 bool
1704 warning_meta (rich_location *richloc,
1705 const diagnostic_metadata &metadata,
1706 int opt, const char *gmsgid, ...)
1708 gcc_assert (richloc);
1710 auto_diagnostic_group d;
1711 va_list ap;
1712 va_start (ap, gmsgid);
1713 bool ret
1714 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1715 DK_WARNING);
1716 va_end (ap);
1717 return ret;
1720 /* Same as warning_n plural variant below, but using RICHLOC. */
1722 bool
1723 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1724 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1726 gcc_assert (richloc);
1728 auto_diagnostic_group d;
1729 va_list ap;
1730 va_start (ap, plural_gmsgid);
1731 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1732 singular_gmsgid, plural_gmsgid,
1733 &ap, DK_WARNING);
1734 va_end (ap);
1735 return ret;
1738 /* A warning at LOCATION. Use this for code which is correct according to the
1739 relevant language specification but is likely to be buggy anyway.
1740 Returns true if the warning was printed, false if it was inhibited. */
1742 bool
1743 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1744 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1746 auto_diagnostic_group d;
1747 va_list ap;
1748 va_start (ap, plural_gmsgid);
1749 rich_location richloc (line_table, location);
1750 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1751 singular_gmsgid, plural_gmsgid,
1752 &ap, DK_WARNING);
1753 va_end (ap);
1754 return ret;
1757 /* A "pedantic" warning at LOCATION: issues a warning unless
1758 -pedantic-errors was given on the command line, in which case it
1759 issues an error. Use this for diagnostics required by the relevant
1760 language standard, if you have chosen not to make them errors.
1762 Note that these diagnostics are issued independent of the setting
1763 of the -Wpedantic command-line switch. To get a warning enabled
1764 only with that switch, use either "if (pedantic) pedwarn
1765 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1766 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1768 Returns true if the warning was printed, false if it was inhibited. */
1770 bool
1771 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1773 auto_diagnostic_group d;
1774 va_list ap;
1775 va_start (ap, gmsgid);
1776 rich_location richloc (line_table, location);
1777 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1778 va_end (ap);
1779 return ret;
1782 /* Same as pedwarn above, but using RICHLOC. */
1784 bool
1785 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1787 gcc_assert (richloc);
1789 auto_diagnostic_group d;
1790 va_list ap;
1791 va_start (ap, gmsgid);
1792 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1793 va_end (ap);
1794 return ret;
1797 /* A "permissive" error at LOCATION: issues an error unless
1798 -fpermissive was given on the command line, in which case it issues
1799 a warning. Use this for things that really should be errors but we
1800 want to support legacy code.
1802 Returns true if the warning was printed, false if it was inhibited. */
1804 bool
1805 permerror (location_t location, const char *gmsgid, ...)
1807 auto_diagnostic_group d;
1808 va_list ap;
1809 va_start (ap, gmsgid);
1810 rich_location richloc (line_table, location);
1811 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1812 va_end (ap);
1813 return ret;
1816 /* Same as "permerror" above, but at RICHLOC. */
1818 bool
1819 permerror (rich_location *richloc, const char *gmsgid, ...)
1821 gcc_assert (richloc);
1823 auto_diagnostic_group d;
1824 va_list ap;
1825 va_start (ap, gmsgid);
1826 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1827 va_end (ap);
1828 return ret;
1831 /* A hard error: the code is definitely ill-formed, and an object file
1832 will not be produced. */
1833 void
1834 error (const char *gmsgid, ...)
1836 auto_diagnostic_group d;
1837 va_list ap;
1838 va_start (ap, gmsgid);
1839 rich_location richloc (line_table, input_location);
1840 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1841 va_end (ap);
1844 /* A hard error: the code is definitely ill-formed, and an object file
1845 will not be produced. */
1846 void
1847 error_n (location_t location, unsigned HOST_WIDE_INT n,
1848 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1850 auto_diagnostic_group d;
1851 va_list ap;
1852 va_start (ap, plural_gmsgid);
1853 rich_location richloc (line_table, location);
1854 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1855 &ap, DK_ERROR);
1856 va_end (ap);
1859 /* Same as above, but use location LOC instead of input_location. */
1860 void
1861 error_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_ERROR);
1868 va_end (ap);
1871 /* Same as above, but use RICH_LOC. */
1873 void
1874 error_at (rich_location *richloc, const char *gmsgid, ...)
1876 gcc_assert (richloc);
1878 auto_diagnostic_group d;
1879 va_list ap;
1880 va_start (ap, gmsgid);
1881 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1882 va_end (ap);
1885 /* "Sorry, not implemented." Use for a language feature which is
1886 required by the relevant specification but not implemented by GCC.
1887 An object file will not be produced. */
1888 void
1889 sorry (const char *gmsgid, ...)
1891 auto_diagnostic_group d;
1892 va_list ap;
1893 va_start (ap, gmsgid);
1894 rich_location richloc (line_table, input_location);
1895 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1896 va_end (ap);
1899 /* Same as above, but use location LOC instead of input_location. */
1900 void
1901 sorry_at (location_t loc, const char *gmsgid, ...)
1903 auto_diagnostic_group d;
1904 va_list ap;
1905 va_start (ap, gmsgid);
1906 rich_location richloc (line_table, loc);
1907 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1908 va_end (ap);
1911 /* Return true if an error or a "sorry" has been seen. Various
1912 processing is disabled after errors. */
1913 bool
1914 seen_error (void)
1916 return errorcount || sorrycount;
1919 /* An error which is severe enough that we make no attempt to
1920 continue. Do not use this for internal consistency checks; that's
1921 internal_error. Use of this function should be rare. */
1922 void
1923 fatal_error (location_t loc, const char *gmsgid, ...)
1925 auto_diagnostic_group d;
1926 va_list ap;
1927 va_start (ap, gmsgid);
1928 rich_location richloc (line_table, loc);
1929 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1930 va_end (ap);
1932 gcc_unreachable ();
1935 /* An internal consistency check has failed. We make no attempt to
1936 continue. Note that unless there is debugging value to be had from
1937 a more specific message, or some other good reason, you should use
1938 abort () instead of calling this function directly. */
1939 void
1940 internal_error (const char *gmsgid, ...)
1942 auto_diagnostic_group d;
1943 va_list ap;
1944 va_start (ap, gmsgid);
1945 rich_location richloc (line_table, input_location);
1946 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
1947 va_end (ap);
1949 gcc_unreachable ();
1952 /* Like internal_error, but no backtrace will be printed. Used when
1953 the internal error does not happen at the current location, but happened
1954 somewhere else. */
1955 void
1956 internal_error_no_backtrace (const char *gmsgid, ...)
1958 auto_diagnostic_group d;
1959 va_list ap;
1960 va_start (ap, gmsgid);
1961 rich_location richloc (line_table, input_location);
1962 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1963 va_end (ap);
1965 gcc_unreachable ();
1968 /* Special case error functions. Most are implemented in terms of the
1969 above, or should be. */
1971 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1972 runs its second argument through gettext. */
1973 void
1974 fnotice (FILE *file, const char *cmsgid, ...)
1976 va_list ap;
1978 va_start (ap, cmsgid);
1979 vfprintf (file, _(cmsgid), ap);
1980 va_end (ap);
1983 /* Inform the user that an error occurred while trying to report some
1984 other error. This indicates catastrophic internal inconsistencies,
1985 so give up now. But do try to flush out the previous error.
1986 This mustn't use internal_error, that will cause infinite recursion. */
1988 static void
1989 error_recursion (diagnostic_context *context)
1991 if (context->lock < 3)
1992 pp_newline_and_flush (context->printer);
1994 fnotice (stderr,
1995 "internal compiler error: error reporting routines re-entered.\n");
1997 /* Call diagnostic_action_after_output to get the "please submit a bug
1998 report" message. */
1999 diagnostic_action_after_output (context, DK_ICE);
2001 /* Do not use gcc_unreachable here; that goes through internal_error
2002 and therefore would cause infinite recursion. */
2003 real_abort ();
2006 /* Report an internal compiler error in a friendly manner. This is
2007 the function that gets called upon use of abort() in the source
2008 code generally, thanks to a special macro. */
2010 void
2011 fancy_abort (const char *file, int line, const char *function)
2013 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2014 internal_error will crash internally in a way that prevents a
2015 useful message reaching the user.
2016 This can happen with libgccjit in the case of gcc_assert failures
2017 that occur outside of the libgccjit mutex that guards the rest of
2018 gcc's state, including global_dc (when global_dc may not be
2019 initialized yet, or might be in use by another thread).
2020 Handle such cases as gracefully as possible by falling back to a
2021 minimal abort handler that only relies on i18n. */
2022 if (global_dc->printer == NULL)
2024 /* Print the error message. */
2025 fnotice (stderr, "%s", diagnostic_kind_text[DK_ICE]);
2026 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2027 fputc ('\n', stderr);
2029 /* Attempt to print a backtrace. */
2030 struct backtrace_state *state
2031 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2032 int count = 0;
2033 if (state != NULL)
2034 backtrace_full (state, 2, bt_callback, bt_err_callback,
2035 (void *) &count);
2037 /* We can't call warn_if_plugins or emergency_dump_function as these
2038 rely on GCC state that might not be initialized, or might be in
2039 use by another thread. */
2041 /* Abort the process. */
2042 real_abort ();
2045 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2048 /* class auto_diagnostic_group. */
2050 /* Constructor: "push" this group into global_dc. */
2052 auto_diagnostic_group::auto_diagnostic_group ()
2054 global_dc->diagnostic_group_nesting_depth++;
2057 /* Destructor: "pop" this group from global_dc. */
2059 auto_diagnostic_group::~auto_diagnostic_group ()
2061 if (--global_dc->diagnostic_group_nesting_depth == 0)
2063 /* Handle the case where we've popped the final diagnostic group.
2064 If any diagnostics were emitted, give the context a chance
2065 to do something. */
2066 if (global_dc->diagnostic_group_emission_count > 0)
2068 if (global_dc->end_group_cb)
2069 global_dc->end_group_cb (global_dc);
2071 global_dc->diagnostic_group_emission_count = 0;
2075 /* Implementation of diagnostic_path::num_events vfunc for
2076 simple_diagnostic_path: simply get the number of events in the vec. */
2078 unsigned
2079 simple_diagnostic_path::num_events () const
2081 return m_events.length ();
2084 /* Implementation of diagnostic_path::get_event vfunc for
2085 simple_diagnostic_path: simply return the event in the vec. */
2087 const diagnostic_event &
2088 simple_diagnostic_path::get_event (int idx) const
2090 return *m_events[idx];
2093 /* Add an event to this path at LOC within function FNDECL at
2094 stack depth DEPTH.
2096 Use m_context's printer to format FMT, as the text of the new
2097 event.
2099 Return the id of the new event. */
2101 diagnostic_event_id_t
2102 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2103 const char *fmt, ...)
2105 pretty_printer *pp = m_event_pp;
2106 pp_clear_output_area (pp);
2108 text_info ti;
2109 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2111 va_list ap;
2113 va_start (ap, fmt);
2115 ti.format_spec = _(fmt);
2116 ti.args_ptr = &ap;
2117 ti.err_no = 0;
2118 ti.x_data = NULL;
2119 ti.m_richloc = &rich_loc;
2121 pp_format (pp, &ti);
2122 pp_output_formatted_text (pp);
2124 va_end (ap);
2126 simple_diagnostic_event *new_event
2127 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2128 m_events.safe_push (new_event);
2130 pp_clear_output_area (pp);
2132 return diagnostic_event_id_t (m_events.length () - 1);
2135 /* struct simple_diagnostic_event. */
2137 /* simple_diagnostic_event's ctor. */
2139 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2140 tree fndecl,
2141 int depth,
2142 const char *desc)
2143 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2147 /* simple_diagnostic_event's dtor. */
2149 simple_diagnostic_event::~simple_diagnostic_event ()
2151 free (m_desc);
2154 /* Print PATH by emitting a dummy "note" associated with it. */
2156 DEBUG_FUNCTION
2157 void debug (diagnostic_path *path)
2159 rich_location richloc (line_table, UNKNOWN_LOCATION);
2160 richloc.set_path (path);
2161 inform (&richloc, "debug path");
2164 /* Really call the system 'abort'. This has to go right at the end of
2165 this file, so that there are no functions after it that call abort
2166 and get the system abort instead of our macro. */
2167 #undef abort
2168 static void
2169 real_abort (void)
2171 abort ();
2174 #if CHECKING_P
2176 namespace selftest {
2178 /* Helper function for test_print_escaped_string. */
2180 static void
2181 assert_print_escaped_string (const location &loc, const char *expected_output,
2182 const char *input)
2184 pretty_printer pp;
2185 print_escaped_string (&pp, input);
2186 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2189 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2190 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2192 /* Tests of print_escaped_string. */
2194 static void
2195 test_print_escaped_string ()
2197 /* Empty string. */
2198 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2200 /* Non-empty string. */
2201 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2203 /* Various things that need to be escaped: */
2204 /* Backslash. */
2205 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2206 "before\\after");
2207 /* Tab. */
2208 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2209 "before\tafter");
2210 /* Newline. */
2211 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2212 "before\nafter");
2213 /* Double quote. */
2214 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2215 "before\"after");
2217 /* Non-printable characters: BEL: '\a': 0x07 */
2218 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2219 "before\aafter");
2220 /* Non-printable characters: vertical tab: '\v': 0x0b */
2221 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2222 "before\vafter");
2225 /* Tests of print_parseable_fixits. */
2227 /* Verify that print_parseable_fixits emits the empty string if there
2228 are no fixits. */
2230 static void
2231 test_print_parseable_fixits_none ()
2233 pretty_printer pp;
2234 rich_location richloc (line_table, UNKNOWN_LOCATION);
2236 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2237 ASSERT_STREQ ("", pp_formatted_text (&pp));
2240 /* Verify that print_parseable_fixits does the right thing if there
2241 is an insertion fixit hint. */
2243 static void
2244 test_print_parseable_fixits_insert ()
2246 pretty_printer pp;
2247 rich_location richloc (line_table, UNKNOWN_LOCATION);
2249 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2250 linemap_line_start (line_table, 5, 100);
2251 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2252 location_t where = linemap_position_for_column (line_table, 10);
2253 richloc.add_fixit_insert_before (where, "added content");
2255 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2256 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2257 pp_formatted_text (&pp));
2260 /* Verify that print_parseable_fixits does the right thing if there
2261 is an removal fixit hint. */
2263 static void
2264 test_print_parseable_fixits_remove ()
2266 pretty_printer pp;
2267 rich_location richloc (line_table, UNKNOWN_LOCATION);
2269 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2270 linemap_line_start (line_table, 5, 100);
2271 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2272 source_range where;
2273 where.m_start = linemap_position_for_column (line_table, 10);
2274 where.m_finish = linemap_position_for_column (line_table, 20);
2275 richloc.add_fixit_remove (where);
2277 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2278 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2279 pp_formatted_text (&pp));
2282 /* Verify that print_parseable_fixits does the right thing if there
2283 is an replacement fixit hint. */
2285 static void
2286 test_print_parseable_fixits_replace ()
2288 pretty_printer pp;
2289 rich_location richloc (line_table, UNKNOWN_LOCATION);
2291 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2292 linemap_line_start (line_table, 5, 100);
2293 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2294 source_range where;
2295 where.m_start = linemap_position_for_column (line_table, 10);
2296 where.m_finish = linemap_position_for_column (line_table, 20);
2297 richloc.add_fixit_replace (where, "replacement");
2299 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2300 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2301 pp_formatted_text (&pp));
2304 /* Verify that print_parseable_fixits correctly handles
2305 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2307 static void
2308 test_print_parseable_fixits_bytes_vs_display_columns ()
2310 line_table_test ltt;
2311 rich_location richloc (line_table, UNKNOWN_LOCATION);
2313 /* 1-based byte offsets: 12345677778888999900001234567. */
2314 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2315 /* 1-based display cols: 123456[......7-8.....]9012345. */
2316 const int tabstop = 8;
2318 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2319 const char *const fname = tmp.get_filename ();
2321 linemap_add (line_table, LC_ENTER, false, fname, 0);
2322 linemap_line_start (line_table, 1, 100);
2323 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2324 source_range where;
2325 where.m_start = linemap_position_for_column (line_table, 12);
2326 where.m_finish = linemap_position_for_column (line_table, 17);
2327 richloc.add_fixit_replace (where, "color");
2329 /* Escape fname. */
2330 pretty_printer tmp_pp;
2331 print_escaped_string (&tmp_pp, fname);
2332 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2334 const int buf_len = strlen (escaped_fname) + 100;
2335 char *const expected = XNEWVEC (char, buf_len);
2338 pretty_printer pp;
2339 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2340 tabstop);
2341 snprintf (expected, buf_len,
2342 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2343 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2346 pretty_printer pp;
2347 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2348 tabstop);
2349 snprintf (expected, buf_len,
2350 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2351 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2354 XDELETEVEC (expected);
2355 free (escaped_fname);
2358 /* Verify that
2359 diagnostic_get_location_text (..., SHOW_COLUMN)
2360 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2361 colorization disabled. */
2363 static void
2364 assert_location_text (const char *expected_loc_text,
2365 const char *filename, int line, int column,
2366 bool show_column,
2367 int origin = 1,
2368 enum diagnostics_column_unit column_unit
2369 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2371 test_diagnostic_context dc;
2372 dc.show_column = show_column;
2373 dc.column_unit = column_unit;
2374 dc.column_origin = origin;
2376 expanded_location xloc;
2377 xloc.file = filename;
2378 xloc.line = line;
2379 xloc.column = column;
2380 xloc.data = NULL;
2381 xloc.sysp = false;
2383 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2384 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2385 free (actual_loc_text);
2388 /* Verify that diagnostic_get_location_text works as expected. */
2390 static void
2391 test_diagnostic_get_location_text ()
2393 const char *old_progname = progname;
2394 progname = "PROGNAME";
2395 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2396 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2397 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2398 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2399 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2400 for (int origin = 0; origin != 2; ++origin)
2401 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2402 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2403 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2404 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2406 maybe_line_and_column (INT_MAX, INT_MAX);
2407 maybe_line_and_column (INT_MIN, INT_MIN);
2410 /* In order to test display columns vs byte columns, we need to create a
2411 file for location_get_source_line() to read. */
2413 const char *const content = "smile \xf0\x9f\x98\x82\n";
2414 const int line_bytes = strlen (content) - 1;
2415 const int def_tabstop = 8;
2416 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2417 const int display_width = cpp_display_width (content, line_bytes, policy);
2418 ASSERT_EQ (line_bytes - 2, display_width);
2419 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2420 const char *const fname = tmp.get_filename ();
2421 const int buf_len = strlen (fname) + 16;
2422 char *const expected = XNEWVEC (char, buf_len);
2424 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2425 assert_location_text (expected, fname, 1, line_bytes, true,
2426 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2428 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2429 assert_location_text (expected, fname, 1, line_bytes, true,
2430 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2432 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2433 assert_location_text (expected, fname, 1, line_bytes, true,
2434 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2436 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2437 assert_location_text (expected, fname, 1, line_bytes, true,
2438 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2440 XDELETEVEC (expected);
2444 progname = old_progname;
2447 /* Selftest for num_digits. */
2449 static void
2450 test_num_digits ()
2452 ASSERT_EQ (1, num_digits (0));
2453 ASSERT_EQ (1, num_digits (9));
2454 ASSERT_EQ (2, num_digits (10));
2455 ASSERT_EQ (2, num_digits (99));
2456 ASSERT_EQ (3, num_digits (100));
2457 ASSERT_EQ (3, num_digits (999));
2458 ASSERT_EQ (4, num_digits (1000));
2459 ASSERT_EQ (4, num_digits (9999));
2460 ASSERT_EQ (5, num_digits (10000));
2461 ASSERT_EQ (5, num_digits (99999));
2462 ASSERT_EQ (6, num_digits (100000));
2463 ASSERT_EQ (6, num_digits (999999));
2464 ASSERT_EQ (7, num_digits (1000000));
2465 ASSERT_EQ (7, num_digits (9999999));
2466 ASSERT_EQ (8, num_digits (10000000));
2467 ASSERT_EQ (8, num_digits (99999999));
2470 /* Run all of the selftests within this file. */
2472 void
2473 c_diagnostic_cc_tests ()
2475 test_print_escaped_string ();
2476 test_print_parseable_fixits_none ();
2477 test_print_parseable_fixits_insert ();
2478 test_print_parseable_fixits_remove ();
2479 test_print_parseable_fixits_replace ();
2480 test_print_parseable_fixits_bytes_vs_display_columns ();
2481 test_diagnostic_get_location_text ();
2482 test_num_digits ();
2486 } // namespace selftest
2488 #endif /* #if CHECKING_P */
2490 #if __GNUC__ >= 10
2491 # pragma GCC diagnostic pop
2492 #endif