Don't warn when alignment of global common data exceeds maximum alignment.
[official-gcc.git] / gcc / diagnostic.c
blob8361f68aaceb5bc0f8487899197eb97dcf296c65
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 /* Do any cleaning up required after the last diagnostic is emitted. */
298 void
299 diagnostic_finish (diagnostic_context *context)
301 if (context->final_cb)
302 context->final_cb (context);
304 diagnostic_file_cache_fini ();
306 XDELETEVEC (context->classify_diagnostic);
307 context->classify_diagnostic = NULL;
309 /* diagnostic_initialize allocates context->printer using XNEW
310 and placement-new. */
311 context->printer->~pretty_printer ();
312 XDELETE (context->printer);
313 context->printer = NULL;
315 if (context->edit_context_ptr)
317 delete context->edit_context_ptr;
318 context->edit_context_ptr = NULL;
322 /* Initialize DIAGNOSTIC, where the message MSG has already been
323 translated. */
324 void
325 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
326 va_list *args, rich_location *richloc,
327 diagnostic_t kind)
329 gcc_assert (richloc);
330 diagnostic->message.err_no = errno;
331 diagnostic->message.args_ptr = args;
332 diagnostic->message.format_spec = msg;
333 diagnostic->message.m_richloc = richloc;
334 diagnostic->richloc = richloc;
335 diagnostic->metadata = NULL;
336 diagnostic->kind = kind;
337 diagnostic->option_index = 0;
340 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
341 translated. */
342 void
343 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
344 va_list *args, rich_location *richloc,
345 diagnostic_t kind)
347 gcc_assert (richloc);
348 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
351 static const char *const diagnostic_kind_color[] = {
352 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
353 #include "diagnostic.def"
354 #undef DEFINE_DIAGNOSTIC_KIND
355 NULL
358 /* Get a color name for diagnostics of type KIND
359 Result could be NULL. */
361 const char *
362 diagnostic_get_color_for_kind (diagnostic_t kind)
364 return diagnostic_kind_color[kind];
367 /* Given an expanded_location, convert the column (which is in 1-based bytes)
368 to the requested units, without converting the origin.
369 Return -1 if the column is invalid (<= 0). */
371 static int
372 convert_column_unit (enum diagnostics_column_unit column_unit,
373 int tabstop,
374 expanded_location s)
376 if (s.column <= 0)
377 return -1;
379 switch (column_unit)
381 default:
382 gcc_unreachable ();
384 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
385 return location_compute_display_column (s, tabstop);
387 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
388 return s.column;
392 /* Given an expanded_location, convert the column (which is in 1-based bytes)
393 to the requested units and origin. Return -1 if the column is
394 invalid (<= 0). */
396 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
398 int one_based_col
399 = convert_column_unit (context->column_unit, context->tabstop, s);
400 if (one_based_col <= 0)
401 return -1;
402 return one_based_col + (context->column_origin - 1);
405 /* Return a formatted line and column ':%line:%column'. Elided if
406 line == 0 or col < 0. (A column of 0 may be valid due to the
407 -fdiagnostics-column-origin option.)
408 The result is a statically allocated buffer. */
410 static const char *
411 maybe_line_and_column (int line, int col)
413 static char result[32];
415 if (line)
417 size_t l
418 = snprintf (result, sizeof (result),
419 col >= 0 ? ":%d:%d" : ":%d", line, col);
420 gcc_checking_assert (l < sizeof (result));
422 else
423 result[0] = 0;
424 return result;
427 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
428 The caller is responsible for freeing the memory. */
430 static char *
431 diagnostic_get_location_text (diagnostic_context *context,
432 expanded_location s)
434 pretty_printer *pp = context->printer;
435 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
436 const char *locus_ce = colorize_stop (pp_show_color (pp));
437 const char *file = s.file ? s.file : progname;
438 int line = 0;
439 int col = -1;
440 if (strcmp (file, N_("<built-in>")))
442 line = s.line;
443 if (context->show_column)
444 col = diagnostic_converted_column (context, s);
447 const char *line_col = maybe_line_and_column (line, col);
448 return build_message_string ("%s%s%s:%s", locus_cs, file,
449 line_col, locus_ce);
452 static const char *const diagnostic_kind_text[] = {
453 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
454 #include "diagnostic.def"
455 #undef DEFINE_DIAGNOSTIC_KIND
456 "must-not-happen"
459 /* Return a malloc'd string describing a location and the severity of the
460 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
461 freeing the memory. */
462 char *
463 diagnostic_build_prefix (diagnostic_context *context,
464 const diagnostic_info *diagnostic)
466 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
468 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
469 const char *text_cs = "", *text_ce = "";
470 pretty_printer *pp = context->printer;
472 if (diagnostic_kind_color[diagnostic->kind])
474 text_cs = colorize_start (pp_show_color (pp),
475 diagnostic_kind_color[diagnostic->kind]);
476 text_ce = colorize_stop (pp_show_color (pp));
479 expanded_location s = diagnostic_expand_location (diagnostic);
480 char *location_text = diagnostic_get_location_text (context, s);
482 char *result = build_message_string ("%s %s%s%s", location_text,
483 text_cs, text, text_ce);
484 free (location_text);
485 return result;
488 /* Functions at which to stop the backtrace print. It's not
489 particularly helpful to print the callers of these functions. */
491 static const char * const bt_stop[] =
493 "main",
494 "toplev::main",
495 "execute_one_pass",
496 "compile_file",
499 /* A callback function passed to the backtrace_full function. */
501 static int
502 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
503 const char *function)
505 int *pcount = (int *) data;
507 /* If we don't have any useful information, don't print
508 anything. */
509 if (filename == NULL && function == NULL)
510 return 0;
512 /* Skip functions in diagnostic.c. */
513 if (*pcount == 0
514 && filename != NULL
515 && strcmp (lbasename (filename), "diagnostic.c") == 0)
516 return 0;
518 /* Print up to 20 functions. We could make this a --param, but
519 since this is only for debugging just use a constant for now. */
520 if (*pcount >= 20)
522 /* Returning a non-zero value stops the backtrace. */
523 return 1;
525 ++*pcount;
527 char *alc = NULL;
528 if (function != NULL)
530 char *str = cplus_demangle_v3 (function,
531 (DMGL_VERBOSE | DMGL_ANSI
532 | DMGL_GNU_V3 | DMGL_PARAMS));
533 if (str != NULL)
535 alc = str;
536 function = str;
539 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
541 size_t len = strlen (bt_stop[i]);
542 if (strncmp (function, bt_stop[i], len) == 0
543 && (function[len] == '\0' || function[len] == '('))
545 if (alc != NULL)
546 free (alc);
547 /* Returning a non-zero value stops the backtrace. */
548 return 1;
553 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
554 (unsigned long) pc,
555 function == NULL ? "???" : function,
556 filename == NULL ? "???" : filename,
557 lineno);
559 if (alc != NULL)
560 free (alc);
562 return 0;
565 /* A callback function passed to the backtrace_full function. This is
566 called if backtrace_full has an error. */
568 static void
569 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
571 if (errnum < 0)
573 /* This means that no debug info was available. Just quietly
574 skip printing backtrace info. */
575 return;
577 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
578 errnum == 0 ? "" : xstrerror (errnum));
581 /* Check if we've met the maximum error limit, and if so fatally exit
582 with a message. CONTEXT is the context to check, and FLUSH
583 indicates whether a diagnostic_finish call is needed. */
585 void
586 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
588 if (!context->max_errors)
589 return;
591 int count = (diagnostic_kind_count (context, DK_ERROR)
592 + diagnostic_kind_count (context, DK_SORRY)
593 + diagnostic_kind_count (context, DK_WERROR));
595 if (count >= context->max_errors)
597 fnotice (stderr,
598 "compilation terminated due to -fmax-errors=%u.\n",
599 context->max_errors);
600 if (flush)
601 diagnostic_finish (context);
602 exit (FATAL_EXIT_CODE);
606 /* Take any action which is expected to happen after the diagnostic
607 is written out. This function does not always return. */
608 void
609 diagnostic_action_after_output (diagnostic_context *context,
610 diagnostic_t diag_kind)
612 switch (diag_kind)
614 case DK_DEBUG:
615 case DK_NOTE:
616 case DK_ANACHRONISM:
617 case DK_WARNING:
618 break;
620 case DK_ERROR:
621 case DK_SORRY:
622 if (context->abort_on_error)
623 real_abort ();
624 if (context->fatal_errors)
626 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
627 diagnostic_finish (context);
628 exit (FATAL_EXIT_CODE);
630 break;
632 case DK_ICE:
633 case DK_ICE_NOBT:
635 struct backtrace_state *state = NULL;
636 if (diag_kind == DK_ICE)
637 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
638 int count = 0;
639 if (state != NULL)
640 backtrace_full (state, 2, bt_callback, bt_err_callback,
641 (void *) &count);
643 if (context->abort_on_error)
644 real_abort ();
646 fnotice (stderr, "Please submit a full bug report,\n"
647 "with preprocessed source if appropriate.\n");
648 if (count > 0)
649 fnotice (stderr,
650 ("Please include the complete backtrace "
651 "with any bug report.\n"));
652 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
654 exit (ICE_EXIT_CODE);
657 case DK_FATAL:
658 if (context->abort_on_error)
659 real_abort ();
660 diagnostic_finish (context);
661 fnotice (stderr, "compilation terminated.\n");
662 exit (FATAL_EXIT_CODE);
664 default:
665 gcc_unreachable ();
669 /* True if the last module or file in which a diagnostic was reported is
670 different from the current one. */
672 static bool
673 last_module_changed_p (diagnostic_context *context,
674 const line_map_ordinary *map)
676 return context->last_module != map;
679 /* Remember the current module or file as being the last one in which we
680 report a diagnostic. */
682 static void
683 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
685 context->last_module = map;
688 void
689 diagnostic_report_current_module (diagnostic_context *context, location_t where)
691 const line_map_ordinary *map = NULL;
693 if (pp_needs_newline (context->printer))
695 pp_newline (context->printer);
696 pp_needs_newline (context->printer) = false;
699 if (where <= BUILTINS_LOCATION)
700 return;
702 linemap_resolve_location (line_table, where,
703 LRK_MACRO_DEFINITION_LOCATION,
704 &map);
706 if (map && last_module_changed_p (context, map))
708 set_last_module (context, map);
709 if (! MAIN_FILE_P (map))
711 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
712 expanded_location s = {};
715 where = linemap_included_from (map);
716 map = linemap_included_from_linemap (line_table, map);
717 bool is_module = MAP_MODULE_P (map);
718 s.file = LINEMAP_FILE (map);
719 s.line = SOURCE_LINE (map, where);
720 int col = -1;
721 if (first && context->show_column)
723 s.column = SOURCE_COLUMN (map, where);
724 col = diagnostic_converted_column (context, s);
726 const char *line_col = maybe_line_and_column (s.line, col);
727 static const char *const msgs[] =
729 NULL,
730 N_(" from"),
731 N_("In file included from"), /* 2 */
732 N_(" included from"),
733 N_("In module"), /* 4 */
734 N_("of module"),
735 N_("In module imported at"), /* 6 */
736 N_("imported at"),
739 unsigned index = (was_module ? 6 : is_module ? 4
740 : need_inc ? 2 : 0) + !first;
742 pp_verbatim (context->printer, "%s%s %r%s%s%R",
743 first ? "" : was_module ? ", " : ",\n",
744 _(msgs[index]),
745 "locus", s.file, line_col);
746 first = false, need_inc = was_module, was_module = is_module;
748 while (! MAIN_FILE_P (map));
749 pp_verbatim (context->printer, ":");
750 pp_newline (context->printer);
755 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
756 print the path. */
758 void
759 diagnostic_show_any_path (diagnostic_context *context,
760 diagnostic_info *diagnostic)
762 const diagnostic_path *path = diagnostic->richloc->get_path ();
763 if (!path)
764 return;
766 if (context->print_path)
767 context->print_path (context, path);
770 /* Return true if the events in this path involve more than one
771 function, or false if it is purely intraprocedural. */
773 bool
774 diagnostic_path::interprocedural_p () const
776 const unsigned num = num_events ();
777 for (unsigned i = 0; i < num; i++)
779 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
780 return true;
781 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
782 return true;
784 return false;
787 void
788 default_diagnostic_starter (diagnostic_context *context,
789 diagnostic_info *diagnostic)
791 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
792 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
793 diagnostic));
796 void
797 default_diagnostic_start_span_fn (diagnostic_context *context,
798 expanded_location exploc)
800 char *text = diagnostic_get_location_text (context, exploc);
801 pp_string (context->printer, text);
802 free (text);
803 pp_newline (context->printer);
806 void
807 default_diagnostic_finalizer (diagnostic_context *context,
808 diagnostic_info *diagnostic,
809 diagnostic_t)
811 char *saved_prefix = pp_take_prefix (context->printer);
812 pp_set_prefix (context->printer, NULL);
813 pp_newline (context->printer);
814 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
815 pp_set_prefix (context->printer, saved_prefix);
816 pp_flush (context->printer);
819 /* Interface to specify diagnostic kind overrides. Returns the
820 previous setting, or DK_UNSPECIFIED if the parameters are out of
821 range. If OPTION_INDEX is zero, the new setting is for all the
822 diagnostics. */
823 diagnostic_t
824 diagnostic_classify_diagnostic (diagnostic_context *context,
825 int option_index,
826 diagnostic_t new_kind,
827 location_t where)
829 diagnostic_t old_kind;
831 if (option_index < 0
832 || option_index >= context->n_opts
833 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
834 return DK_UNSPECIFIED;
836 old_kind = context->classify_diagnostic[option_index];
838 /* Handle pragmas separately, since we need to keep track of *where*
839 the pragmas were. */
840 if (where != UNKNOWN_LOCATION)
842 int i;
844 /* Record the command-line status, so we can reset it back on DK_POP. */
845 if (old_kind == DK_UNSPECIFIED)
847 old_kind = !context->option_enabled (option_index,
848 context->lang_mask,
849 context->option_state)
850 ? DK_IGNORED : (context->warning_as_error_requested
851 ? DK_ERROR : DK_WARNING);
852 context->classify_diagnostic[option_index] = old_kind;
855 for (i = context->n_classification_history - 1; i >= 0; i --)
856 if (context->classification_history[i].option == option_index)
858 old_kind = context->classification_history[i].kind;
859 break;
862 i = context->n_classification_history;
863 context->classification_history =
864 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
865 * sizeof (diagnostic_classification_change_t));
866 context->classification_history[i].location = where;
867 context->classification_history[i].option = option_index;
868 context->classification_history[i].kind = new_kind;
869 context->n_classification_history ++;
871 else
872 context->classify_diagnostic[option_index] = new_kind;
874 return old_kind;
877 /* Save all diagnostic classifications in a stack. */
878 void
879 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
881 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
882 context->push_list[context->n_push ++] = context->n_classification_history;
885 /* Restore the topmost classification set off the stack. If the stack
886 is empty, revert to the state based on command line parameters. */
887 void
888 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
890 int jump_to;
891 int i;
893 if (context->n_push)
894 jump_to = context->push_list [-- context->n_push];
895 else
896 jump_to = 0;
898 i = context->n_classification_history;
899 context->classification_history =
900 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
901 * sizeof (diagnostic_classification_change_t));
902 context->classification_history[i].location = where;
903 context->classification_history[i].option = jump_to;
904 context->classification_history[i].kind = DK_POP;
905 context->n_classification_history ++;
908 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
909 escaping rules for -fdiagnostics-parseable-fixits. */
911 static void
912 print_escaped_string (pretty_printer *pp, const char *text)
914 gcc_assert (pp);
915 gcc_assert (text);
917 pp_character (pp, '"');
918 for (const char *ch = text; *ch; ch++)
920 switch (*ch)
922 case '\\':
923 /* Escape backslash as two backslashes. */
924 pp_string (pp, "\\\\");
925 break;
926 case '\t':
927 /* Escape tab as "\t". */
928 pp_string (pp, "\\t");
929 break;
930 case '\n':
931 /* Escape newline as "\n". */
932 pp_string (pp, "\\n");
933 break;
934 case '"':
935 /* Escape doublequotes as \". */
936 pp_string (pp, "\\\"");
937 break;
938 default:
939 if (ISPRINT (*ch))
940 pp_character (pp, *ch);
941 else
942 /* Use octal for non-printable chars. */
944 unsigned char c = (*ch & 0xff);
945 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
947 break;
950 pp_character (pp, '"');
953 /* Implementation of -fdiagnostics-parseable-fixits and
954 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
955 Print a machine-parseable version of all fixits in RICHLOC to PP,
956 using COLUMN_UNIT to express columns.
957 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
959 static void
960 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
961 enum diagnostics_column_unit column_unit,
962 int tabstop)
964 gcc_assert (pp);
965 gcc_assert (richloc);
967 char *saved_prefix = pp_take_prefix (pp);
968 pp_set_prefix (pp, NULL);
970 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
972 const fixit_hint *hint = richloc->get_fixit_hint (i);
973 location_t start_loc = hint->get_start_loc ();
974 expanded_location start_exploc = expand_location (start_loc);
975 pp_string (pp, "fix-it:");
976 print_escaped_string (pp, start_exploc.file);
977 /* For compatibility with clang, print as a half-open range. */
978 location_t next_loc = hint->get_next_loc ();
979 expanded_location next_exploc = expand_location (next_loc);
980 int start_col
981 = convert_column_unit (column_unit, tabstop, start_exploc);
982 int next_col
983 = convert_column_unit (column_unit, tabstop, next_exploc);
984 pp_printf (pp, ":{%i:%i-%i:%i}:",
985 start_exploc.line, start_col,
986 next_exploc.line, next_col);
987 print_escaped_string (pp, hint->get_string ());
988 pp_newline (pp);
991 pp_set_prefix (pp, saved_prefix);
994 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
996 static void
997 get_any_inlining_info (diagnostic_context *context,
998 diagnostic_info *diagnostic)
1000 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1002 if (context->set_locations_cb)
1003 /* Retrieve the locations into which the expression about to be
1004 diagnosed has been inlined, including those of all the callers
1005 all the way down the inlining stack. */
1006 context->set_locations_cb (context, diagnostic);
1007 else
1009 /* When there's no callback use just the one location provided
1010 by the caller of the diagnostic function. */
1011 location_t loc = diagnostic_location (diagnostic);
1012 ilocs.safe_push (loc);
1013 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1017 /* Update the kind of DIAGNOSTIC based on its location(s), including
1018 any of those in its inlining stack, relative to any
1019 #pragma GCC diagnostic
1020 directives recorded within CONTEXT.
1022 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1023 otherwise. */
1025 static diagnostic_t
1026 update_effective_level_from_pragmas (diagnostic_context *context,
1027 diagnostic_info *diagnostic)
1029 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1031 /* Ignore the diagnostic if all the inlined locations are
1032 in system headers and -Wno-system-headers is in effect. */
1033 diagnostic->kind = DK_IGNORED;
1034 return DK_IGNORED;
1037 if (context->n_classification_history <= 0)
1038 return DK_UNSPECIFIED;
1040 /* Iterate over the locations, checking the diagnostic disposition
1041 for the diagnostic at each. If it's explicitly set as opposed
1042 to unspecified, update the disposition for this instance of
1043 the diagnostic and return it. */
1044 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1046 /* FIXME: Stupid search. Optimize later. */
1047 for (int i = context->n_classification_history - 1; i >= 0; i --)
1049 const diagnostic_classification_change_t &hist
1050 = context->classification_history[i];
1052 location_t pragloc = hist.location;
1053 if (!linemap_location_before_p (line_table, pragloc, loc))
1054 continue;
1056 if (hist.kind == (int) DK_POP)
1058 /* Move on to the next region. */
1059 i = hist.option;
1060 continue;
1063 int option = hist.option;
1064 /* The option 0 is for all the diagnostics. */
1065 if (option == 0 || option == diagnostic->option_index)
1067 diagnostic_t kind = hist.kind;
1068 if (kind != DK_UNSPECIFIED)
1069 diagnostic->kind = kind;
1070 return kind;
1075 return DK_UNSPECIFIED;
1078 /* Generate a URL string describing CWE. The caller is responsible for
1079 freeing the string. */
1081 static char *
1082 get_cwe_url (int cwe)
1084 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1087 /* If DIAGNOSTIC has a CWE identifier, print it.
1089 For example, if the diagnostic metadata associates it with CWE-119,
1090 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1091 description of the security issue. */
1093 static void
1094 print_any_cwe (diagnostic_context *context,
1095 const diagnostic_info *diagnostic)
1097 if (diagnostic->metadata == NULL)
1098 return;
1100 int cwe = diagnostic->metadata->get_cwe ();
1101 if (cwe)
1103 pretty_printer *pp = context->printer;
1104 char *saved_prefix = pp_take_prefix (context->printer);
1105 pp_string (pp, " [");
1106 pp_string (pp, colorize_start (pp_show_color (pp),
1107 diagnostic_kind_color[diagnostic->kind]));
1108 if (pp->url_format != URL_FORMAT_NONE)
1110 char *cwe_url = get_cwe_url (cwe);
1111 pp_begin_url (pp, cwe_url);
1112 free (cwe_url);
1114 pp_printf (pp, "CWE-%i", cwe);
1115 pp_set_prefix (context->printer, saved_prefix);
1116 if (pp->url_format != URL_FORMAT_NONE)
1117 pp_end_url (pp);
1118 pp_string (pp, colorize_stop (pp_show_color (pp)));
1119 pp_character (pp, ']');
1123 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1124 printer, e.g. " [-Werror=uninitialized]".
1125 Subroutine of diagnostic_report_diagnostic. */
1127 static void
1128 print_option_information (diagnostic_context *context,
1129 const diagnostic_info *diagnostic,
1130 diagnostic_t orig_diag_kind)
1132 char *option_text;
1134 option_text = context->option_name (context, diagnostic->option_index,
1135 orig_diag_kind, diagnostic->kind);
1137 if (option_text)
1139 char *option_url = NULL;
1140 if (context->get_option_url
1141 && context->printer->url_format != URL_FORMAT_NONE)
1142 option_url = context->get_option_url (context,
1143 diagnostic->option_index);
1144 pretty_printer *pp = context->printer;
1145 pp_string (pp, " [");
1146 pp_string (pp, colorize_start (pp_show_color (pp),
1147 diagnostic_kind_color[diagnostic->kind]));
1148 if (option_url)
1149 pp_begin_url (pp, option_url);
1150 pp_string (pp, option_text);
1151 if (option_url)
1153 pp_end_url (pp);
1154 free (option_url);
1156 pp_string (pp, colorize_stop (pp_show_color (pp)));
1157 pp_character (pp, ']');
1158 free (option_text);
1162 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1163 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1165 static bool
1166 diagnostic_enabled (diagnostic_context *context,
1167 diagnostic_info *diagnostic)
1169 /* Update the inlining stack for this diagnostic. */
1170 get_any_inlining_info (context, diagnostic);
1172 /* Diagnostics with no option or -fpermissive are always enabled. */
1173 if (!diagnostic->option_index
1174 || diagnostic->option_index == permissive_error_option (context))
1175 return true;
1177 /* This tests if the user provided the appropriate -Wfoo or
1178 -Wno-foo option. */
1179 if (! context->option_enabled (diagnostic->option_index,
1180 context->lang_mask,
1181 context->option_state))
1182 return false;
1184 /* This tests for #pragma diagnostic changes. */
1185 diagnostic_t diag_class
1186 = update_effective_level_from_pragmas (context, diagnostic);
1188 /* This tests if the user provided the appropriate -Werror=foo
1189 option. */
1190 if (diag_class == DK_UNSPECIFIED
1191 && (context->classify_diagnostic[diagnostic->option_index]
1192 != DK_UNSPECIFIED))
1193 diagnostic->kind
1194 = context->classify_diagnostic[diagnostic->option_index];
1196 /* This allows for future extensions, like temporarily disabling
1197 warnings for ranges of source code. */
1198 if (diagnostic->kind == DK_IGNORED)
1199 return false;
1201 return true;
1204 /* Returns whether warning OPT is enabled at LOC. */
1206 bool
1207 warning_enabled_at (location_t loc, int opt)
1209 if (!diagnostic_report_warnings_p (global_dc, loc))
1210 return false;
1212 rich_location richloc (line_table, loc);
1213 diagnostic_info diagnostic = {};
1214 diagnostic.option_index = opt;
1215 diagnostic.richloc = &richloc;
1216 diagnostic.message.m_richloc = &richloc;
1217 diagnostic.kind = DK_WARNING;
1218 return diagnostic_enabled (global_dc, &diagnostic);
1221 /* Report a diagnostic message (an error or a warning) as specified by
1222 DC. This function is *the* subroutine in terms of which front-ends
1223 should implement their specific diagnostic handling modules. The
1224 front-end independent format specifiers are exactly those described
1225 in the documentation of output_format.
1226 Return true if a diagnostic was printed, false otherwise. */
1228 bool
1229 diagnostic_report_diagnostic (diagnostic_context *context,
1230 diagnostic_info *diagnostic)
1232 location_t location = diagnostic_location (diagnostic);
1233 diagnostic_t orig_diag_kind = diagnostic->kind;
1235 /* Give preference to being able to inhibit warnings, before they
1236 get reclassified to something else. */
1237 bool report_warning_p = true;
1238 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1240 if (context->dc_inhibit_warnings)
1241 return false;
1242 /* Remember the result of the overall system header warning setting
1243 but proceed to also check the inlining context. */
1244 report_warning_p = diagnostic_report_warnings_p (context, location);
1245 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1246 return false;
1249 if (diagnostic->kind == DK_PEDWARN)
1251 diagnostic->kind = pedantic_warning_kind (context);
1252 /* We do this to avoid giving the message for -pedantic-errors. */
1253 orig_diag_kind = diagnostic->kind;
1256 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1257 return false;
1259 if (context->lock > 0)
1261 /* If we're reporting an ICE in the middle of some other error,
1262 try to flush out the previous error, then let this one
1263 through. Don't do this more than once. */
1264 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1265 && context->lock == 1)
1266 pp_newline_and_flush (context->printer);
1267 else
1268 error_recursion (context);
1271 /* If the user requested that warnings be treated as errors, so be
1272 it. Note that we do this before the next block so that
1273 individual warnings can be overridden back to warnings with
1274 -Wno-error=*. */
1275 if (context->warning_as_error_requested
1276 && diagnostic->kind == DK_WARNING)
1277 diagnostic->kind = DK_ERROR;
1279 diagnostic->message.x_data = &diagnostic->x_data;
1281 /* Check to see if the diagnostic is enabled at the location and
1282 not disabled by #pragma GCC diagnostic anywhere along the inlining
1283 stack. . */
1284 if (!diagnostic_enabled (context, diagnostic))
1285 return false;
1287 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1288 /* Bail if the warning is not to be reported because all locations
1289 in the inlining stack (if there is one) are in system headers. */
1290 return false;
1292 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1293 diagnostic_check_max_errors (context);
1295 context->lock++;
1297 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1299 /* When not checking, ICEs are converted to fatal errors when an
1300 error has already occurred. This is counteracted by
1301 abort_on_error. */
1302 if (!CHECKING_P
1303 && (diagnostic_kind_count (context, DK_ERROR) > 0
1304 || diagnostic_kind_count (context, DK_SORRY) > 0)
1305 && !context->abort_on_error)
1307 expanded_location s
1308 = expand_location (diagnostic_location (diagnostic));
1309 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1310 s.file, s.line);
1311 exit (ICE_EXIT_CODE);
1313 if (context->internal_error)
1314 (*context->internal_error) (context,
1315 diagnostic->message.format_spec,
1316 diagnostic->message.args_ptr);
1318 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1319 ++diagnostic_kind_count (context, DK_WERROR);
1320 else
1321 ++diagnostic_kind_count (context, diagnostic->kind);
1323 /* Is this the initial diagnostic within the stack of groups? */
1324 if (context->diagnostic_group_emission_count == 0)
1326 if (context->begin_group_cb)
1327 context->begin_group_cb (context);
1329 context->diagnostic_group_emission_count++;
1331 pp_format (context->printer, &diagnostic->message);
1332 (*diagnostic_starter (context)) (context, diagnostic);
1333 pp_output_formatted_text (context->printer);
1334 if (context->show_cwe)
1335 print_any_cwe (context, diagnostic);
1336 if (context->show_option_requested)
1337 print_option_information (context, diagnostic, orig_diag_kind);
1338 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1339 switch (context->extra_output_kind)
1341 default:
1342 break;
1343 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1344 print_parseable_fixits (context->printer, diagnostic->richloc,
1345 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1346 context->tabstop);
1347 pp_flush (context->printer);
1348 break;
1349 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1350 print_parseable_fixits (context->printer, diagnostic->richloc,
1351 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1352 context->tabstop);
1353 pp_flush (context->printer);
1354 break;
1356 diagnostic_action_after_output (context, diagnostic->kind);
1357 diagnostic->x_data = NULL;
1359 if (context->edit_context_ptr)
1360 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1361 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1363 context->lock--;
1365 diagnostic_show_any_path (context, diagnostic);
1367 return true;
1370 /* Get the number of digits in the decimal representation of VALUE. */
1373 num_digits (int value)
1375 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1376 using floating point. */
1377 gcc_assert (value >= 0);
1379 if (value == 0)
1380 return 1;
1382 int digits = 0;
1383 while (value > 0)
1385 digits++;
1386 value /= 10;
1388 return digits;
1391 /* Given a partial pathname as input, return another pathname that
1392 shares no directory elements with the pathname of __FILE__. This
1393 is used by fancy_abort() to print `Internal compiler error in expr.c'
1394 instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
1396 const char *
1397 trim_filename (const char *name)
1399 static const char this_file[] = __FILE__;
1400 const char *p = name, *q = this_file;
1402 /* First skip any "../" in each filename. This allows us to give a proper
1403 reference to a file in a subdirectory. */
1404 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1405 p += 3;
1407 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1408 q += 3;
1410 /* Now skip any parts the two filenames have in common. */
1411 while (*p == *q && *p != 0 && *q != 0)
1412 p++, q++;
1414 /* Now go backwards until the previous directory separator. */
1415 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1416 p--;
1418 return p;
1421 /* Standard error reporting routines in increasing order of severity.
1422 All of these take arguments like printf. */
1424 /* Text to be emitted verbatim to the error message stream; this
1425 produces no prefix and disables line-wrapping. Use rarely. */
1426 void
1427 verbatim (const char *gmsgid, ...)
1429 text_info text;
1430 va_list ap;
1432 va_start (ap, gmsgid);
1433 text.err_no = errno;
1434 text.args_ptr = &ap;
1435 text.format_spec = _(gmsgid);
1436 text.x_data = NULL;
1437 pp_format_verbatim (global_dc->printer, &text);
1438 pp_newline_and_flush (global_dc->printer);
1439 va_end (ap);
1442 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1443 void
1444 diagnostic_append_note (diagnostic_context *context,
1445 location_t location,
1446 const char * gmsgid, ...)
1448 diagnostic_info diagnostic;
1449 va_list ap;
1450 rich_location richloc (line_table, location);
1452 va_start (ap, gmsgid);
1453 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1454 if (context->inhibit_notes_p)
1456 va_end (ap);
1457 return;
1459 char *saved_prefix = pp_take_prefix (context->printer);
1460 pp_set_prefix (context->printer,
1461 diagnostic_build_prefix (context, &diagnostic));
1462 pp_format (context->printer, &diagnostic.message);
1463 pp_output_formatted_text (context->printer);
1464 pp_destroy_prefix (context->printer);
1465 pp_set_prefix (context->printer, saved_prefix);
1466 pp_newline (context->printer);
1467 diagnostic_show_locus (context, &richloc, DK_NOTE);
1468 va_end (ap);
1471 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1472 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1473 and internal_error_no_backtrace, as documented and defined below. */
1474 static bool
1475 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1476 int opt, const char *gmsgid,
1477 va_list *ap, diagnostic_t kind)
1479 diagnostic_info diagnostic;
1480 if (kind == DK_PERMERROR)
1482 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1483 permissive_error_kind (global_dc));
1484 diagnostic.option_index = permissive_error_option (global_dc);
1486 else
1488 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1489 if (kind == DK_WARNING || kind == DK_PEDWARN)
1490 diagnostic.option_index = opt;
1492 diagnostic.metadata = metadata;
1493 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1496 /* Implement inform_n, warning_n, and error_n, as documented and
1497 defined below. */
1498 static bool
1499 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1500 int opt, unsigned HOST_WIDE_INT n,
1501 const char *singular_gmsgid,
1502 const char *plural_gmsgid,
1503 va_list *ap, diagnostic_t kind)
1505 diagnostic_info diagnostic;
1506 unsigned long gtn;
1508 if (sizeof n <= sizeof gtn)
1509 gtn = n;
1510 else
1511 /* Use the largest number ngettext can handle, otherwise
1512 preserve the six least significant decimal digits for
1513 languages where the plural form depends on them. */
1514 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1516 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1517 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1518 if (kind == DK_WARNING)
1519 diagnostic.option_index = opt;
1520 diagnostic.metadata = metadata;
1521 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1524 /* Wrapper around diagnostic_impl taking a variable argument list. */
1526 bool
1527 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1528 const char *gmsgid, ...)
1530 auto_diagnostic_group d;
1531 va_list ap;
1532 va_start (ap, gmsgid);
1533 rich_location richloc (line_table, location);
1534 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1535 va_end (ap);
1536 return ret;
1539 /* As above, but for rich_location *. */
1541 bool
1542 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1543 const char *gmsgid, ...)
1545 auto_diagnostic_group d;
1546 va_list ap;
1547 va_start (ap, gmsgid);
1548 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1549 va_end (ap);
1550 return ret;
1553 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1555 bool
1556 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1557 const char *gmsgid, va_list *ap)
1559 rich_location richloc (line_table, location);
1560 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1563 /* An informative note at LOCATION. Use this for additional details on an error
1564 message. */
1565 void
1566 inform (location_t location, const char *gmsgid, ...)
1568 auto_diagnostic_group d;
1569 va_list ap;
1570 va_start (ap, gmsgid);
1571 rich_location richloc (line_table, location);
1572 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1573 va_end (ap);
1576 /* Same as "inform" above, but at RICHLOC. */
1577 void
1578 inform (rich_location *richloc, const char *gmsgid, ...)
1580 gcc_assert (richloc);
1582 auto_diagnostic_group d;
1583 va_list ap;
1584 va_start (ap, gmsgid);
1585 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1586 va_end (ap);
1589 /* An informative note at LOCATION. Use this for additional details on an
1590 error message. */
1591 void
1592 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1593 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1595 va_list ap;
1596 va_start (ap, plural_gmsgid);
1597 auto_diagnostic_group d;
1598 rich_location richloc (line_table, location);
1599 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1600 &ap, DK_NOTE);
1601 va_end (ap);
1604 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1605 to the relevant language specification but is likely to be buggy anyway.
1606 Returns true if the warning was printed, false if it was inhibited. */
1607 bool
1608 warning (int opt, const char *gmsgid, ...)
1610 auto_diagnostic_group d;
1611 va_list ap;
1612 va_start (ap, gmsgid);
1613 rich_location richloc (line_table, input_location);
1614 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1615 va_end (ap);
1616 return ret;
1619 /* A warning at LOCATION. Use this for code which is correct according to the
1620 relevant language specification but is likely to be buggy anyway.
1621 Returns true if the warning was printed, false if it was inhibited. */
1623 bool
1624 warning_at (location_t location, int opt, const char *gmsgid, ...)
1626 auto_diagnostic_group d;
1627 va_list ap;
1628 va_start (ap, gmsgid);
1629 rich_location richloc (line_table, location);
1630 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1631 va_end (ap);
1632 return ret;
1635 /* Same as "warning at" above, but using RICHLOC. */
1637 bool
1638 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1640 gcc_assert (richloc);
1642 auto_diagnostic_group d;
1643 va_list ap;
1644 va_start (ap, gmsgid);
1645 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1646 va_end (ap);
1647 return ret;
1650 /* Same as "warning at" above, but using METADATA. */
1652 bool
1653 warning_meta (rich_location *richloc,
1654 const diagnostic_metadata &metadata,
1655 int opt, const char *gmsgid, ...)
1657 gcc_assert (richloc);
1659 auto_diagnostic_group d;
1660 va_list ap;
1661 va_start (ap, gmsgid);
1662 bool ret
1663 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1664 DK_WARNING);
1665 va_end (ap);
1666 return ret;
1669 /* Same as warning_n plural variant below, but using RICHLOC. */
1671 bool
1672 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1673 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1675 gcc_assert (richloc);
1677 auto_diagnostic_group d;
1678 va_list ap;
1679 va_start (ap, plural_gmsgid);
1680 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1681 singular_gmsgid, plural_gmsgid,
1682 &ap, DK_WARNING);
1683 va_end (ap);
1684 return ret;
1687 /* A warning at LOCATION. Use this for code which is correct according to the
1688 relevant language specification but is likely to be buggy anyway.
1689 Returns true if the warning was printed, false if it was inhibited. */
1691 bool
1692 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1693 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1695 auto_diagnostic_group d;
1696 va_list ap;
1697 va_start (ap, plural_gmsgid);
1698 rich_location richloc (line_table, location);
1699 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1700 singular_gmsgid, plural_gmsgid,
1701 &ap, DK_WARNING);
1702 va_end (ap);
1703 return ret;
1706 /* A "pedantic" warning at LOCATION: issues a warning unless
1707 -pedantic-errors was given on the command line, in which case it
1708 issues an error. Use this for diagnostics required by the relevant
1709 language standard, if you have chosen not to make them errors.
1711 Note that these diagnostics are issued independent of the setting
1712 of the -Wpedantic command-line switch. To get a warning enabled
1713 only with that switch, use either "if (pedantic) pedwarn
1714 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1715 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1717 Returns true if the warning was printed, false if it was inhibited. */
1719 bool
1720 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1722 auto_diagnostic_group d;
1723 va_list ap;
1724 va_start (ap, gmsgid);
1725 rich_location richloc (line_table, location);
1726 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1727 va_end (ap);
1728 return ret;
1731 /* Same as pedwarn above, but using RICHLOC. */
1733 bool
1734 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1736 gcc_assert (richloc);
1738 auto_diagnostic_group d;
1739 va_list ap;
1740 va_start (ap, gmsgid);
1741 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1742 va_end (ap);
1743 return ret;
1746 /* A "permissive" error at LOCATION: issues an error unless
1747 -fpermissive was given on the command line, in which case it issues
1748 a warning. Use this for things that really should be errors but we
1749 want to support legacy code.
1751 Returns true if the warning was printed, false if it was inhibited. */
1753 bool
1754 permerror (location_t location, const char *gmsgid, ...)
1756 auto_diagnostic_group d;
1757 va_list ap;
1758 va_start (ap, gmsgid);
1759 rich_location richloc (line_table, location);
1760 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1761 va_end (ap);
1762 return ret;
1765 /* Same as "permerror" above, but at RICHLOC. */
1767 bool
1768 permerror (rich_location *richloc, const char *gmsgid, ...)
1770 gcc_assert (richloc);
1772 auto_diagnostic_group d;
1773 va_list ap;
1774 va_start (ap, gmsgid);
1775 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1776 va_end (ap);
1777 return ret;
1780 /* A hard error: the code is definitely ill-formed, and an object file
1781 will not be produced. */
1782 void
1783 error (const char *gmsgid, ...)
1785 auto_diagnostic_group d;
1786 va_list ap;
1787 va_start (ap, gmsgid);
1788 rich_location richloc (line_table, input_location);
1789 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1790 va_end (ap);
1793 /* A hard error: the code is definitely ill-formed, and an object file
1794 will not be produced. */
1795 void
1796 error_n (location_t location, unsigned HOST_WIDE_INT n,
1797 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1799 auto_diagnostic_group d;
1800 va_list ap;
1801 va_start (ap, plural_gmsgid);
1802 rich_location richloc (line_table, location);
1803 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1804 &ap, DK_ERROR);
1805 va_end (ap);
1808 /* Same as above, but use location LOC instead of input_location. */
1809 void
1810 error_at (location_t loc, const char *gmsgid, ...)
1812 auto_diagnostic_group d;
1813 va_list ap;
1814 va_start (ap, gmsgid);
1815 rich_location richloc (line_table, loc);
1816 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1817 va_end (ap);
1820 /* Same as above, but use RICH_LOC. */
1822 void
1823 error_at (rich_location *richloc, const char *gmsgid, ...)
1825 gcc_assert (richloc);
1827 auto_diagnostic_group d;
1828 va_list ap;
1829 va_start (ap, gmsgid);
1830 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1831 va_end (ap);
1834 /* "Sorry, not implemented." Use for a language feature which is
1835 required by the relevant specification but not implemented by GCC.
1836 An object file will not be produced. */
1837 void
1838 sorry (const char *gmsgid, ...)
1840 auto_diagnostic_group d;
1841 va_list ap;
1842 va_start (ap, gmsgid);
1843 rich_location richloc (line_table, input_location);
1844 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1845 va_end (ap);
1848 /* Same as above, but use location LOC instead of input_location. */
1849 void
1850 sorry_at (location_t loc, const char *gmsgid, ...)
1852 auto_diagnostic_group d;
1853 va_list ap;
1854 va_start (ap, gmsgid);
1855 rich_location richloc (line_table, loc);
1856 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1857 va_end (ap);
1860 /* Return true if an error or a "sorry" has been seen. Various
1861 processing is disabled after errors. */
1862 bool
1863 seen_error (void)
1865 return errorcount || sorrycount;
1868 /* An error which is severe enough that we make no attempt to
1869 continue. Do not use this for internal consistency checks; that's
1870 internal_error. Use of this function should be rare. */
1871 void
1872 fatal_error (location_t loc, const char *gmsgid, ...)
1874 auto_diagnostic_group d;
1875 va_list ap;
1876 va_start (ap, gmsgid);
1877 rich_location richloc (line_table, loc);
1878 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1879 va_end (ap);
1881 gcc_unreachable ();
1884 /* An internal consistency check has failed. We make no attempt to
1885 continue. Note that unless there is debugging value to be had from
1886 a more specific message, or some other good reason, you should use
1887 abort () instead of calling this function directly. */
1888 void
1889 internal_error (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_ICE);
1896 va_end (ap);
1898 gcc_unreachable ();
1901 /* Like internal_error, but no backtrace will be printed. Used when
1902 the internal error does not happen at the current location, but happened
1903 somewhere else. */
1904 void
1905 internal_error_no_backtrace (const char *gmsgid, ...)
1907 auto_diagnostic_group d;
1908 va_list ap;
1909 va_start (ap, gmsgid);
1910 rich_location richloc (line_table, input_location);
1911 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1912 va_end (ap);
1914 gcc_unreachable ();
1917 /* Special case error functions. Most are implemented in terms of the
1918 above, or should be. */
1920 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1921 runs its second argument through gettext. */
1922 void
1923 fnotice (FILE *file, const char *cmsgid, ...)
1925 va_list ap;
1927 va_start (ap, cmsgid);
1928 vfprintf (file, _(cmsgid), ap);
1929 va_end (ap);
1932 /* Inform the user that an error occurred while trying to report some
1933 other error. This indicates catastrophic internal inconsistencies,
1934 so give up now. But do try to flush out the previous error.
1935 This mustn't use internal_error, that will cause infinite recursion. */
1937 static void
1938 error_recursion (diagnostic_context *context)
1940 if (context->lock < 3)
1941 pp_newline_and_flush (context->printer);
1943 fnotice (stderr,
1944 "Internal compiler error: Error reporting routines re-entered.\n");
1946 /* Call diagnostic_action_after_output to get the "please submit a bug
1947 report" message. */
1948 diagnostic_action_after_output (context, DK_ICE);
1950 /* Do not use gcc_unreachable here; that goes through internal_error
1951 and therefore would cause infinite recursion. */
1952 real_abort ();
1955 /* Report an internal compiler error in a friendly manner. This is
1956 the function that gets called upon use of abort() in the source
1957 code generally, thanks to a special macro. */
1959 void
1960 fancy_abort (const char *file, int line, const char *function)
1962 /* If fancy_abort is called before the diagnostic subsystem is initialized,
1963 internal_error will crash internally in a way that prevents a
1964 useful message reaching the user.
1965 This can happen with libgccjit in the case of gcc_assert failures
1966 that occur outside of the libgccjit mutex that guards the rest of
1967 gcc's state, including global_dc (when global_dc may not be
1968 initialized yet, or might be in use by another thread).
1969 Handle such cases as gracefully as possible by falling back to a
1970 minimal abort handler that only relies on i18n. */
1971 if (global_dc->printer == NULL)
1973 /* Print the error message. */
1974 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
1975 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
1976 fputc ('\n', stderr);
1978 /* Attempt to print a backtrace. */
1979 struct backtrace_state *state
1980 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
1981 int count = 0;
1982 if (state != NULL)
1983 backtrace_full (state, 2, bt_callback, bt_err_callback,
1984 (void *) &count);
1986 /* We can't call warn_if_plugins or emergency_dump_function as these
1987 rely on GCC state that might not be initialized, or might be in
1988 use by another thread. */
1990 /* Abort the process. */
1991 real_abort ();
1994 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
1997 /* class auto_diagnostic_group. */
1999 /* Constructor: "push" this group into global_dc. */
2001 auto_diagnostic_group::auto_diagnostic_group ()
2003 global_dc->diagnostic_group_nesting_depth++;
2006 /* Destructor: "pop" this group from global_dc. */
2008 auto_diagnostic_group::~auto_diagnostic_group ()
2010 if (--global_dc->diagnostic_group_nesting_depth == 0)
2012 /* Handle the case where we've popped the final diagnostic group.
2013 If any diagnostics were emitted, give the context a chance
2014 to do something. */
2015 if (global_dc->diagnostic_group_emission_count > 0)
2017 if (global_dc->end_group_cb)
2018 global_dc->end_group_cb (global_dc);
2020 global_dc->diagnostic_group_emission_count = 0;
2024 /* Implementation of diagnostic_path::num_events vfunc for
2025 simple_diagnostic_path: simply get the number of events in the vec. */
2027 unsigned
2028 simple_diagnostic_path::num_events () const
2030 return m_events.length ();
2033 /* Implementation of diagnostic_path::get_event vfunc for
2034 simple_diagnostic_path: simply return the event in the vec. */
2036 const diagnostic_event &
2037 simple_diagnostic_path::get_event (int idx) const
2039 return *m_events[idx];
2042 /* Add an event to this path at LOC within function FNDECL at
2043 stack depth DEPTH.
2045 Use m_context's printer to format FMT, as the text of the new
2046 event.
2048 Return the id of the new event. */
2050 diagnostic_event_id_t
2051 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2052 const char *fmt, ...)
2054 pretty_printer *pp = m_event_pp;
2055 pp_clear_output_area (pp);
2057 text_info ti;
2058 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2060 va_list ap;
2062 va_start (ap, fmt);
2064 ti.format_spec = _(fmt);
2065 ti.args_ptr = &ap;
2066 ti.err_no = 0;
2067 ti.x_data = NULL;
2068 ti.m_richloc = &rich_loc;
2070 pp_format (pp, &ti);
2071 pp_output_formatted_text (pp);
2073 va_end (ap);
2075 simple_diagnostic_event *new_event
2076 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2077 m_events.safe_push (new_event);
2079 pp_clear_output_area (pp);
2081 return diagnostic_event_id_t (m_events.length () - 1);
2084 /* struct simple_diagnostic_event. */
2086 /* simple_diagnostic_event's ctor. */
2088 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2089 tree fndecl,
2090 int depth,
2091 const char *desc)
2092 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2096 /* simple_diagnostic_event's dtor. */
2098 simple_diagnostic_event::~simple_diagnostic_event ()
2100 free (m_desc);
2103 /* Print PATH by emitting a dummy "note" associated with it. */
2105 DEBUG_FUNCTION
2106 void debug (diagnostic_path *path)
2108 rich_location richloc (line_table, UNKNOWN_LOCATION);
2109 richloc.set_path (path);
2110 inform (&richloc, "debug path");
2113 /* Really call the system 'abort'. This has to go right at the end of
2114 this file, so that there are no functions after it that call abort
2115 and get the system abort instead of our macro. */
2116 #undef abort
2117 static void
2118 real_abort (void)
2120 abort ();
2123 #if CHECKING_P
2125 namespace selftest {
2127 /* Helper function for test_print_escaped_string. */
2129 static void
2130 assert_print_escaped_string (const location &loc, const char *expected_output,
2131 const char *input)
2133 pretty_printer pp;
2134 print_escaped_string (&pp, input);
2135 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2138 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2139 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2141 /* Tests of print_escaped_string. */
2143 static void
2144 test_print_escaped_string ()
2146 /* Empty string. */
2147 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2149 /* Non-empty string. */
2150 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2152 /* Various things that need to be escaped: */
2153 /* Backslash. */
2154 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2155 "before\\after");
2156 /* Tab. */
2157 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2158 "before\tafter");
2159 /* Newline. */
2160 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2161 "before\nafter");
2162 /* Double quote. */
2163 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2164 "before\"after");
2166 /* Non-printable characters: BEL: '\a': 0x07 */
2167 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2168 "before\aafter");
2169 /* Non-printable characters: vertical tab: '\v': 0x0b */
2170 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2171 "before\vafter");
2174 /* Tests of print_parseable_fixits. */
2176 /* Verify that print_parseable_fixits emits the empty string if there
2177 are no fixits. */
2179 static void
2180 test_print_parseable_fixits_none ()
2182 pretty_printer pp;
2183 rich_location richloc (line_table, UNKNOWN_LOCATION);
2185 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2186 ASSERT_STREQ ("", pp_formatted_text (&pp));
2189 /* Verify that print_parseable_fixits does the right thing if there
2190 is an insertion fixit hint. */
2192 static void
2193 test_print_parseable_fixits_insert ()
2195 pretty_printer pp;
2196 rich_location richloc (line_table, UNKNOWN_LOCATION);
2198 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2199 linemap_line_start (line_table, 5, 100);
2200 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2201 location_t where = linemap_position_for_column (line_table, 10);
2202 richloc.add_fixit_insert_before (where, "added content");
2204 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2205 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2206 pp_formatted_text (&pp));
2209 /* Verify that print_parseable_fixits does the right thing if there
2210 is an removal fixit hint. */
2212 static void
2213 test_print_parseable_fixits_remove ()
2215 pretty_printer pp;
2216 rich_location richloc (line_table, UNKNOWN_LOCATION);
2218 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2219 linemap_line_start (line_table, 5, 100);
2220 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2221 source_range where;
2222 where.m_start = linemap_position_for_column (line_table, 10);
2223 where.m_finish = linemap_position_for_column (line_table, 20);
2224 richloc.add_fixit_remove (where);
2226 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2227 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2228 pp_formatted_text (&pp));
2231 /* Verify that print_parseable_fixits does the right thing if there
2232 is an replacement fixit hint. */
2234 static void
2235 test_print_parseable_fixits_replace ()
2237 pretty_printer pp;
2238 rich_location richloc (line_table, UNKNOWN_LOCATION);
2240 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2241 linemap_line_start (line_table, 5, 100);
2242 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2243 source_range where;
2244 where.m_start = linemap_position_for_column (line_table, 10);
2245 where.m_finish = linemap_position_for_column (line_table, 20);
2246 richloc.add_fixit_replace (where, "replacement");
2248 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2249 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2250 pp_formatted_text (&pp));
2253 /* Verify that print_parseable_fixits correctly handles
2254 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2256 static void
2257 test_print_parseable_fixits_bytes_vs_display_columns ()
2259 line_table_test ltt;
2260 rich_location richloc (line_table, UNKNOWN_LOCATION);
2262 /* 1-based byte offsets: 12345677778888999900001234567. */
2263 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2264 /* 1-based display cols: 123456[......7-8.....]9012345. */
2265 const int tabstop = 8;
2267 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2268 const char *const fname = tmp.get_filename ();
2270 linemap_add (line_table, LC_ENTER, false, fname, 0);
2271 linemap_line_start (line_table, 1, 100);
2272 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2273 source_range where;
2274 where.m_start = linemap_position_for_column (line_table, 12);
2275 where.m_finish = linemap_position_for_column (line_table, 17);
2276 richloc.add_fixit_replace (where, "color");
2278 /* Escape fname. */
2279 pretty_printer tmp_pp;
2280 print_escaped_string (&tmp_pp, fname);
2281 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2283 const int buf_len = strlen (escaped_fname) + 100;
2284 char *const expected = XNEWVEC (char, buf_len);
2287 pretty_printer pp;
2288 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2289 tabstop);
2290 snprintf (expected, buf_len,
2291 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2292 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2295 pretty_printer pp;
2296 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2297 tabstop);
2298 snprintf (expected, buf_len,
2299 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2300 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2303 XDELETEVEC (expected);
2304 free (escaped_fname);
2307 /* Verify that
2308 diagnostic_get_location_text (..., SHOW_COLUMN)
2309 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2310 colorization disabled. */
2312 static void
2313 assert_location_text (const char *expected_loc_text,
2314 const char *filename, int line, int column,
2315 bool show_column,
2316 int origin = 1,
2317 enum diagnostics_column_unit column_unit
2318 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2320 test_diagnostic_context dc;
2321 dc.show_column = show_column;
2322 dc.column_unit = column_unit;
2323 dc.column_origin = origin;
2325 expanded_location xloc;
2326 xloc.file = filename;
2327 xloc.line = line;
2328 xloc.column = column;
2329 xloc.data = NULL;
2330 xloc.sysp = false;
2332 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2333 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2334 free (actual_loc_text);
2337 /* Verify that diagnostic_get_location_text works as expected. */
2339 static void
2340 test_diagnostic_get_location_text ()
2342 const char *old_progname = progname;
2343 progname = "PROGNAME";
2344 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2345 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2346 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2347 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2348 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2349 for (int origin = 0; origin != 2; ++origin)
2350 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2351 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2352 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2353 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2355 maybe_line_and_column (INT_MAX, INT_MAX);
2356 maybe_line_and_column (INT_MIN, INT_MIN);
2359 /* In order to test display columns vs byte columns, we need to create a
2360 file for location_get_source_line() to read. */
2362 const char *const content = "smile \xf0\x9f\x98\x82\n";
2363 const int line_bytes = strlen (content) - 1;
2364 const int def_tabstop = 8;
2365 const int display_width = cpp_display_width (content, line_bytes,
2366 def_tabstop);
2367 ASSERT_EQ (line_bytes - 2, display_width);
2368 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2369 const char *const fname = tmp.get_filename ();
2370 const int buf_len = strlen (fname) + 16;
2371 char *const expected = XNEWVEC (char, buf_len);
2373 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2374 assert_location_text (expected, fname, 1, line_bytes, true,
2375 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2377 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2378 assert_location_text (expected, fname, 1, line_bytes, true,
2379 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2381 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2382 assert_location_text (expected, fname, 1, line_bytes, true,
2383 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2385 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2386 assert_location_text (expected, fname, 1, line_bytes, true,
2387 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2389 XDELETEVEC (expected);
2393 progname = old_progname;
2396 /* Selftest for num_digits. */
2398 static void
2399 test_num_digits ()
2401 ASSERT_EQ (1, num_digits (0));
2402 ASSERT_EQ (1, num_digits (9));
2403 ASSERT_EQ (2, num_digits (10));
2404 ASSERT_EQ (2, num_digits (99));
2405 ASSERT_EQ (3, num_digits (100));
2406 ASSERT_EQ (3, num_digits (999));
2407 ASSERT_EQ (4, num_digits (1000));
2408 ASSERT_EQ (4, num_digits (9999));
2409 ASSERT_EQ (5, num_digits (10000));
2410 ASSERT_EQ (5, num_digits (99999));
2411 ASSERT_EQ (6, num_digits (100000));
2412 ASSERT_EQ (6, num_digits (999999));
2413 ASSERT_EQ (7, num_digits (1000000));
2414 ASSERT_EQ (7, num_digits (9999999));
2415 ASSERT_EQ (8, num_digits (10000000));
2416 ASSERT_EQ (8, num_digits (99999999));
2419 /* Run all of the selftests within this file. */
2421 void
2422 diagnostic_c_tests ()
2424 test_print_escaped_string ();
2425 test_print_parseable_fixits_none ();
2426 test_print_parseable_fixits_insert ();
2427 test_print_parseable_fixits_remove ();
2428 test_print_parseable_fixits_replace ();
2429 test_print_parseable_fixits_bytes_vs_display_columns ();
2430 test_diagnostic_get_location_text ();
2431 test_num_digits ();
2435 } // namespace selftest
2437 #endif /* #if CHECKING_P */
2439 #if __GNUC__ >= 10
2440 # pragma GCC diagnostic pop
2441 #endif