Add GCC_EXTRA_DIAGNOSTIC_OUTPUT environment variable for fix-it hints
[official-gcc.git] / gcc / diagnostic.c
blob7d65ac7379f45f7a2148074bd4d5f1bd7112263c
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 /* Return a malloc'd string describing a location and the severity of the
453 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
454 freeing the memory. */
455 char *
456 diagnostic_build_prefix (diagnostic_context *context,
457 const diagnostic_info *diagnostic)
459 static const char *const diagnostic_kind_text[] = {
460 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
461 #include "diagnostic.def"
462 #undef DEFINE_DIAGNOSTIC_KIND
463 "must-not-happen"
465 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
467 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
468 const char *text_cs = "", *text_ce = "";
469 pretty_printer *pp = context->printer;
471 if (diagnostic_kind_color[diagnostic->kind])
473 text_cs = colorize_start (pp_show_color (pp),
474 diagnostic_kind_color[diagnostic->kind]);
475 text_ce = colorize_stop (pp_show_color (pp));
478 expanded_location s = diagnostic_expand_location (diagnostic);
479 char *location_text = diagnostic_get_location_text (context, s);
481 char *result = build_message_string ("%s %s%s%s", location_text,
482 text_cs, text, text_ce);
483 free (location_text);
484 return result;
487 /* Functions at which to stop the backtrace print. It's not
488 particularly helpful to print the callers of these functions. */
490 static const char * const bt_stop[] =
492 "main",
493 "toplev::main",
494 "execute_one_pass",
495 "compile_file",
498 /* A callback function passed to the backtrace_full function. */
500 static int
501 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
502 const char *function)
504 int *pcount = (int *) data;
506 /* If we don't have any useful information, don't print
507 anything. */
508 if (filename == NULL && function == NULL)
509 return 0;
511 /* Skip functions in diagnostic.c. */
512 if (*pcount == 0
513 && filename != NULL
514 && strcmp (lbasename (filename), "diagnostic.c") == 0)
515 return 0;
517 /* Print up to 20 functions. We could make this a --param, but
518 since this is only for debugging just use a constant for now. */
519 if (*pcount >= 20)
521 /* Returning a non-zero value stops the backtrace. */
522 return 1;
524 ++*pcount;
526 char *alc = NULL;
527 if (function != NULL)
529 char *str = cplus_demangle_v3 (function,
530 (DMGL_VERBOSE | DMGL_ANSI
531 | DMGL_GNU_V3 | DMGL_PARAMS));
532 if (str != NULL)
534 alc = str;
535 function = str;
538 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
540 size_t len = strlen (bt_stop[i]);
541 if (strncmp (function, bt_stop[i], len) == 0
542 && (function[len] == '\0' || function[len] == '('))
544 if (alc != NULL)
545 free (alc);
546 /* Returning a non-zero value stops the backtrace. */
547 return 1;
552 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
553 (unsigned long) pc,
554 function == NULL ? "???" : function,
555 filename == NULL ? "???" : filename,
556 lineno);
558 if (alc != NULL)
559 free (alc);
561 return 0;
564 /* A callback function passed to the backtrace_full function. This is
565 called if backtrace_full has an error. */
567 static void
568 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
570 if (errnum < 0)
572 /* This means that no debug info was available. Just quietly
573 skip printing backtrace info. */
574 return;
576 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
577 errnum == 0 ? "" : xstrerror (errnum));
580 /* Check if we've met the maximum error limit, and if so fatally exit
581 with a message. CONTEXT is the context to check, and FLUSH
582 indicates whether a diagnostic_finish call is needed. */
584 void
585 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
587 if (!context->max_errors)
588 return;
590 int count = (diagnostic_kind_count (context, DK_ERROR)
591 + diagnostic_kind_count (context, DK_SORRY)
592 + diagnostic_kind_count (context, DK_WERROR));
594 if (count >= context->max_errors)
596 fnotice (stderr,
597 "compilation terminated due to -fmax-errors=%u.\n",
598 context->max_errors);
599 if (flush)
600 diagnostic_finish (context);
601 exit (FATAL_EXIT_CODE);
605 /* Take any action which is expected to happen after the diagnostic
606 is written out. This function does not always return. */
607 void
608 diagnostic_action_after_output (diagnostic_context *context,
609 diagnostic_t diag_kind)
611 switch (diag_kind)
613 case DK_DEBUG:
614 case DK_NOTE:
615 case DK_ANACHRONISM:
616 case DK_WARNING:
617 break;
619 case DK_ERROR:
620 case DK_SORRY:
621 if (context->abort_on_error)
622 real_abort ();
623 if (context->fatal_errors)
625 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
626 diagnostic_finish (context);
627 exit (FATAL_EXIT_CODE);
629 break;
631 case DK_ICE:
632 case DK_ICE_NOBT:
634 struct backtrace_state *state = NULL;
635 if (diag_kind == DK_ICE)
636 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
637 int count = 0;
638 if (state != NULL)
639 backtrace_full (state, 2, bt_callback, bt_err_callback,
640 (void *) &count);
642 if (context->abort_on_error)
643 real_abort ();
645 fnotice (stderr, "Please submit a full bug report,\n"
646 "with preprocessed source if appropriate.\n");
647 if (count > 0)
648 fnotice (stderr,
649 ("Please include the complete backtrace "
650 "with any bug report.\n"));
651 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
653 exit (ICE_EXIT_CODE);
656 case DK_FATAL:
657 if (context->abort_on_error)
658 real_abort ();
659 diagnostic_finish (context);
660 fnotice (stderr, "compilation terminated.\n");
661 exit (FATAL_EXIT_CODE);
663 default:
664 gcc_unreachable ();
668 /* True if the last module or file in which a diagnostic was reported is
669 different from the current one. */
671 static bool
672 last_module_changed_p (diagnostic_context *context,
673 const line_map_ordinary *map)
675 return context->last_module != map;
678 /* Remember the current module or file as being the last one in which we
679 report a diagnostic. */
681 static void
682 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
684 context->last_module = map;
687 void
688 diagnostic_report_current_module (diagnostic_context *context, location_t where)
690 const line_map_ordinary *map = NULL;
692 if (pp_needs_newline (context->printer))
694 pp_newline (context->printer);
695 pp_needs_newline (context->printer) = false;
698 if (where <= BUILTINS_LOCATION)
699 return;
701 linemap_resolve_location (line_table, where,
702 LRK_MACRO_DEFINITION_LOCATION,
703 &map);
705 if (map && last_module_changed_p (context, map))
707 set_last_module (context, map);
708 if (! MAIN_FILE_P (map))
710 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
711 expanded_location s = {};
714 where = linemap_included_from (map);
715 map = linemap_included_from_linemap (line_table, map);
716 bool is_module = MAP_MODULE_P (map);
717 s.file = LINEMAP_FILE (map);
718 s.line = SOURCE_LINE (map, where);
719 int col = -1;
720 if (first && context->show_column)
722 s.column = SOURCE_COLUMN (map, where);
723 col = diagnostic_converted_column (context, s);
725 const char *line_col = maybe_line_and_column (s.line, col);
726 static const char *const msgs[] =
728 NULL,
729 N_(" from"),
730 N_("In file included from"), /* 2 */
731 N_(" included from"),
732 N_("In module"), /* 4 */
733 N_("of module"),
734 N_("In module imported at"), /* 6 */
735 N_("imported at"),
738 unsigned index = (was_module ? 6 : is_module ? 4
739 : need_inc ? 2 : 0) + !first;
741 pp_verbatim (context->printer, "%s%s %r%s%s%R",
742 first ? "" : was_module ? ", " : ",\n",
743 _(msgs[index]),
744 "locus", s.file, line_col);
745 first = false, need_inc = was_module, was_module = is_module;
747 while (! MAIN_FILE_P (map));
748 pp_verbatim (context->printer, ":");
749 pp_newline (context->printer);
754 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
755 print the path. */
757 void
758 diagnostic_show_any_path (diagnostic_context *context,
759 diagnostic_info *diagnostic)
761 const diagnostic_path *path = diagnostic->richloc->get_path ();
762 if (!path)
763 return;
765 if (context->print_path)
766 context->print_path (context, path);
769 /* Return true if the events in this path involve more than one
770 function, or false if it is purely intraprocedural. */
772 bool
773 diagnostic_path::interprocedural_p () const
775 const unsigned num = num_events ();
776 for (unsigned i = 0; i < num; i++)
778 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
779 return true;
780 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
781 return true;
783 return false;
786 void
787 default_diagnostic_starter (diagnostic_context *context,
788 diagnostic_info *diagnostic)
790 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
791 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
792 diagnostic));
795 void
796 default_diagnostic_start_span_fn (diagnostic_context *context,
797 expanded_location exploc)
799 char *text = diagnostic_get_location_text (context, exploc);
800 pp_string (context->printer, text);
801 free (text);
802 pp_newline (context->printer);
805 void
806 default_diagnostic_finalizer (diagnostic_context *context,
807 diagnostic_info *diagnostic,
808 diagnostic_t)
810 char *saved_prefix = pp_take_prefix (context->printer);
811 pp_set_prefix (context->printer, NULL);
812 pp_newline (context->printer);
813 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
814 pp_set_prefix (context->printer, saved_prefix);
815 pp_flush (context->printer);
818 /* Interface to specify diagnostic kind overrides. Returns the
819 previous setting, or DK_UNSPECIFIED if the parameters are out of
820 range. If OPTION_INDEX is zero, the new setting is for all the
821 diagnostics. */
822 diagnostic_t
823 diagnostic_classify_diagnostic (diagnostic_context *context,
824 int option_index,
825 diagnostic_t new_kind,
826 location_t where)
828 diagnostic_t old_kind;
830 if (option_index < 0
831 || option_index >= context->n_opts
832 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
833 return DK_UNSPECIFIED;
835 old_kind = context->classify_diagnostic[option_index];
837 /* Handle pragmas separately, since we need to keep track of *where*
838 the pragmas were. */
839 if (where != UNKNOWN_LOCATION)
841 int i;
843 /* Record the command-line status, so we can reset it back on DK_POP. */
844 if (old_kind == DK_UNSPECIFIED)
846 old_kind = !context->option_enabled (option_index,
847 context->lang_mask,
848 context->option_state)
849 ? DK_IGNORED : (context->warning_as_error_requested
850 ? DK_ERROR : DK_WARNING);
851 context->classify_diagnostic[option_index] = old_kind;
854 for (i = context->n_classification_history - 1; i >= 0; i --)
855 if (context->classification_history[i].option == option_index)
857 old_kind = context->classification_history[i].kind;
858 break;
861 i = context->n_classification_history;
862 context->classification_history =
863 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
864 * sizeof (diagnostic_classification_change_t));
865 context->classification_history[i].location = where;
866 context->classification_history[i].option = option_index;
867 context->classification_history[i].kind = new_kind;
868 context->n_classification_history ++;
870 else
871 context->classify_diagnostic[option_index] = new_kind;
873 return old_kind;
876 /* Save all diagnostic classifications in a stack. */
877 void
878 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
880 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
881 context->push_list[context->n_push ++] = context->n_classification_history;
884 /* Restore the topmost classification set off the stack. If the stack
885 is empty, revert to the state based on command line parameters. */
886 void
887 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
889 int jump_to;
890 int i;
892 if (context->n_push)
893 jump_to = context->push_list [-- context->n_push];
894 else
895 jump_to = 0;
897 i = context->n_classification_history;
898 context->classification_history =
899 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
900 * sizeof (diagnostic_classification_change_t));
901 context->classification_history[i].location = where;
902 context->classification_history[i].option = jump_to;
903 context->classification_history[i].kind = DK_POP;
904 context->n_classification_history ++;
907 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
908 escaping rules for -fdiagnostics-parseable-fixits. */
910 static void
911 print_escaped_string (pretty_printer *pp, const char *text)
913 gcc_assert (pp);
914 gcc_assert (text);
916 pp_character (pp, '"');
917 for (const char *ch = text; *ch; ch++)
919 switch (*ch)
921 case '\\':
922 /* Escape backslash as two backslashes. */
923 pp_string (pp, "\\\\");
924 break;
925 case '\t':
926 /* Escape tab as "\t". */
927 pp_string (pp, "\\t");
928 break;
929 case '\n':
930 /* Escape newline as "\n". */
931 pp_string (pp, "\\n");
932 break;
933 case '"':
934 /* Escape doublequotes as \". */
935 pp_string (pp, "\\\"");
936 break;
937 default:
938 if (ISPRINT (*ch))
939 pp_character (pp, *ch);
940 else
941 /* Use octal for non-printable chars. */
943 unsigned char c = (*ch & 0xff);
944 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
946 break;
949 pp_character (pp, '"');
952 /* Implementation of -fdiagnostics-parseable-fixits and
953 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
954 Print a machine-parseable version of all fixits in RICHLOC to PP,
955 using COLUMN_UNIT to express columns.
956 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
958 static void
959 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
960 enum diagnostics_column_unit column_unit,
961 int tabstop)
963 gcc_assert (pp);
964 gcc_assert (richloc);
966 char *saved_prefix = pp_take_prefix (pp);
967 pp_set_prefix (pp, NULL);
969 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
971 const fixit_hint *hint = richloc->get_fixit_hint (i);
972 location_t start_loc = hint->get_start_loc ();
973 expanded_location start_exploc = expand_location (start_loc);
974 pp_string (pp, "fix-it:");
975 print_escaped_string (pp, start_exploc.file);
976 /* For compatibility with clang, print as a half-open range. */
977 location_t next_loc = hint->get_next_loc ();
978 expanded_location next_exploc = expand_location (next_loc);
979 int start_col
980 = convert_column_unit (column_unit, tabstop, start_exploc);
981 int next_col
982 = convert_column_unit (column_unit, tabstop, next_exploc);
983 pp_printf (pp, ":{%i:%i-%i:%i}:",
984 start_exploc.line, start_col,
985 next_exploc.line, next_col);
986 print_escaped_string (pp, hint->get_string ());
987 pp_newline (pp);
990 pp_set_prefix (pp, saved_prefix);
993 /* Update the diag_class of DIAGNOSTIC based on its location
994 relative to any
995 #pragma GCC diagnostic
996 directives recorded within CONTEXT.
998 Return the new diag_class of DIAGNOSTIC if it was updated, or
999 DK_UNSPECIFIED otherwise. */
1001 static diagnostic_t
1002 update_effective_level_from_pragmas (diagnostic_context *context,
1003 diagnostic_info *diagnostic)
1005 diagnostic_t diag_class = DK_UNSPECIFIED;
1007 if (context->n_classification_history > 0)
1009 location_t location = diagnostic_location (diagnostic);
1011 /* FIXME: Stupid search. Optimize later. */
1012 for (int i = context->n_classification_history - 1; i >= 0; i --)
1014 if (linemap_location_before_p
1015 (line_table,
1016 context->classification_history[i].location,
1017 location))
1019 if (context->classification_history[i].kind == (int) DK_POP)
1021 i = context->classification_history[i].option;
1022 continue;
1024 int option = context->classification_history[i].option;
1025 /* The option 0 is for all the diagnostics. */
1026 if (option == 0 || option == diagnostic->option_index)
1028 diag_class = context->classification_history[i].kind;
1029 if (diag_class != DK_UNSPECIFIED)
1030 diagnostic->kind = diag_class;
1031 break;
1037 return diag_class;
1040 /* Generate a URL string describing CWE. The caller is responsible for
1041 freeing the string. */
1043 static char *
1044 get_cwe_url (int cwe)
1046 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1049 /* If DIAGNOSTIC has a CWE identifier, print it.
1051 For example, if the diagnostic metadata associates it with CWE-119,
1052 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1053 description of the security issue. */
1055 static void
1056 print_any_cwe (diagnostic_context *context,
1057 const diagnostic_info *diagnostic)
1059 if (diagnostic->metadata == NULL)
1060 return;
1062 int cwe = diagnostic->metadata->get_cwe ();
1063 if (cwe)
1065 pretty_printer *pp = context->printer;
1066 char *saved_prefix = pp_take_prefix (context->printer);
1067 pp_string (pp, " [");
1068 pp_string (pp, colorize_start (pp_show_color (pp),
1069 diagnostic_kind_color[diagnostic->kind]));
1070 if (pp->url_format != URL_FORMAT_NONE)
1072 char *cwe_url = get_cwe_url (cwe);
1073 pp_begin_url (pp, cwe_url);
1074 free (cwe_url);
1076 pp_printf (pp, "CWE-%i", cwe);
1077 pp_set_prefix (context->printer, saved_prefix);
1078 if (pp->url_format != URL_FORMAT_NONE)
1079 pp_end_url (pp);
1080 pp_string (pp, colorize_stop (pp_show_color (pp)));
1081 pp_character (pp, ']');
1085 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1086 printer, e.g. " [-Werror=uninitialized]".
1087 Subroutine of diagnostic_report_diagnostic. */
1089 static void
1090 print_option_information (diagnostic_context *context,
1091 const diagnostic_info *diagnostic,
1092 diagnostic_t orig_diag_kind)
1094 char *option_text;
1096 option_text = context->option_name (context, diagnostic->option_index,
1097 orig_diag_kind, diagnostic->kind);
1099 if (option_text)
1101 char *option_url = NULL;
1102 if (context->get_option_url
1103 && context->printer->url_format != URL_FORMAT_NONE)
1104 option_url = context->get_option_url (context,
1105 diagnostic->option_index);
1106 pretty_printer *pp = context->printer;
1107 pp_string (pp, " [");
1108 pp_string (pp, colorize_start (pp_show_color (pp),
1109 diagnostic_kind_color[diagnostic->kind]));
1110 if (option_url)
1111 pp_begin_url (pp, option_url);
1112 pp_string (pp, option_text);
1113 if (option_url)
1115 pp_end_url (pp);
1116 free (option_url);
1118 pp_string (pp, colorize_stop (pp_show_color (pp)));
1119 pp_character (pp, ']');
1120 free (option_text);
1124 /* Report a diagnostic message (an error or a warning) as specified by
1125 DC. This function is *the* subroutine in terms of which front-ends
1126 should implement their specific diagnostic handling modules. The
1127 front-end independent format specifiers are exactly those described
1128 in the documentation of output_format.
1129 Return true if a diagnostic was printed, false otherwise. */
1131 bool
1132 diagnostic_report_diagnostic (diagnostic_context *context,
1133 diagnostic_info *diagnostic)
1135 location_t location = diagnostic_location (diagnostic);
1136 diagnostic_t orig_diag_kind = diagnostic->kind;
1138 /* Give preference to being able to inhibit warnings, before they
1139 get reclassified to something else. */
1140 if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1141 && !diagnostic_report_warnings_p (context, location))
1142 return false;
1144 if (diagnostic->kind == DK_PEDWARN)
1146 diagnostic->kind = pedantic_warning_kind (context);
1147 /* We do this to avoid giving the message for -pedantic-errors. */
1148 orig_diag_kind = diagnostic->kind;
1151 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1152 return false;
1154 if (context->lock > 0)
1156 /* If we're reporting an ICE in the middle of some other error,
1157 try to flush out the previous error, then let this one
1158 through. Don't do this more than once. */
1159 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1160 && context->lock == 1)
1161 pp_newline_and_flush (context->printer);
1162 else
1163 error_recursion (context);
1166 /* If the user requested that warnings be treated as errors, so be
1167 it. Note that we do this before the next block so that
1168 individual warnings can be overridden back to warnings with
1169 -Wno-error=*. */
1170 if (context->warning_as_error_requested
1171 && diagnostic->kind == DK_WARNING)
1172 diagnostic->kind = DK_ERROR;
1174 if (diagnostic->option_index
1175 && diagnostic->option_index != permissive_error_option (context))
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;
1202 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1203 diagnostic_check_max_errors (context);
1205 context->lock++;
1207 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1209 /* When not checking, ICEs are converted to fatal errors when an
1210 error has already occurred. This is counteracted by
1211 abort_on_error. */
1212 if (!CHECKING_P
1213 && (diagnostic_kind_count (context, DK_ERROR) > 0
1214 || diagnostic_kind_count (context, DK_SORRY) > 0)
1215 && !context->abort_on_error)
1217 expanded_location s
1218 = expand_location (diagnostic_location (diagnostic));
1219 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1220 s.file, s.line);
1221 exit (ICE_EXIT_CODE);
1223 if (context->internal_error)
1224 (*context->internal_error) (context,
1225 diagnostic->message.format_spec,
1226 diagnostic->message.args_ptr);
1228 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1229 ++diagnostic_kind_count (context, DK_WERROR);
1230 else
1231 ++diagnostic_kind_count (context, diagnostic->kind);
1233 /* Is this the initial diagnostic within the stack of groups? */
1234 if (context->diagnostic_group_emission_count == 0)
1236 if (context->begin_group_cb)
1237 context->begin_group_cb (context);
1239 context->diagnostic_group_emission_count++;
1241 diagnostic->message.x_data = &diagnostic->x_data;
1242 diagnostic->x_data = NULL;
1243 pp_format (context->printer, &diagnostic->message);
1244 (*diagnostic_starter (context)) (context, diagnostic);
1245 pp_output_formatted_text (context->printer);
1246 if (context->show_cwe)
1247 print_any_cwe (context, diagnostic);
1248 if (context->show_option_requested)
1249 print_option_information (context, diagnostic, orig_diag_kind);
1250 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1251 switch (context->extra_output_kind)
1253 default:
1254 break;
1255 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1256 print_parseable_fixits (context->printer, diagnostic->richloc,
1257 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1258 context->tabstop);
1259 pp_flush (context->printer);
1260 break;
1261 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1262 print_parseable_fixits (context->printer, diagnostic->richloc,
1263 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1264 context->tabstop);
1265 pp_flush (context->printer);
1266 break;
1268 diagnostic_action_after_output (context, diagnostic->kind);
1269 diagnostic->x_data = NULL;
1271 if (context->edit_context_ptr)
1272 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1273 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1275 context->lock--;
1277 diagnostic_show_any_path (context, diagnostic);
1279 return true;
1282 /* Get the number of digits in the decimal representation of VALUE. */
1285 num_digits (int value)
1287 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1288 using floating point. */
1289 gcc_assert (value >= 0);
1291 if (value == 0)
1292 return 1;
1294 int digits = 0;
1295 while (value > 0)
1297 digits++;
1298 value /= 10;
1300 return digits;
1303 /* Given a partial pathname as input, return another pathname that
1304 shares no directory elements with the pathname of __FILE__. This
1305 is used by fancy_abort() to print `Internal compiler error in expr.c'
1306 instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
1308 const char *
1309 trim_filename (const char *name)
1311 static const char this_file[] = __FILE__;
1312 const char *p = name, *q = this_file;
1314 /* First skip any "../" in each filename. This allows us to give a proper
1315 reference to a file in a subdirectory. */
1316 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1317 p += 3;
1319 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1320 q += 3;
1322 /* Now skip any parts the two filenames have in common. */
1323 while (*p == *q && *p != 0 && *q != 0)
1324 p++, q++;
1326 /* Now go backwards until the previous directory separator. */
1327 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1328 p--;
1330 return p;
1333 /* Standard error reporting routines in increasing order of severity.
1334 All of these take arguments like printf. */
1336 /* Text to be emitted verbatim to the error message stream; this
1337 produces no prefix and disables line-wrapping. Use rarely. */
1338 void
1339 verbatim (const char *gmsgid, ...)
1341 text_info text;
1342 va_list ap;
1344 va_start (ap, gmsgid);
1345 text.err_no = errno;
1346 text.args_ptr = &ap;
1347 text.format_spec = _(gmsgid);
1348 text.x_data = NULL;
1349 pp_format_verbatim (global_dc->printer, &text);
1350 pp_newline_and_flush (global_dc->printer);
1351 va_end (ap);
1354 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1355 void
1356 diagnostic_append_note (diagnostic_context *context,
1357 location_t location,
1358 const char * gmsgid, ...)
1360 diagnostic_info diagnostic;
1361 va_list ap;
1362 rich_location richloc (line_table, location);
1364 va_start (ap, gmsgid);
1365 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1366 if (context->inhibit_notes_p)
1368 va_end (ap);
1369 return;
1371 char *saved_prefix = pp_take_prefix (context->printer);
1372 pp_set_prefix (context->printer,
1373 diagnostic_build_prefix (context, &diagnostic));
1374 pp_format (context->printer, &diagnostic.message);
1375 pp_output_formatted_text (context->printer);
1376 pp_destroy_prefix (context->printer);
1377 pp_set_prefix (context->printer, saved_prefix);
1378 pp_newline (context->printer);
1379 diagnostic_show_locus (context, &richloc, DK_NOTE);
1380 va_end (ap);
1383 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1384 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1385 and internal_error_no_backtrace, as documented and defined below. */
1386 static bool
1387 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1388 int opt, const char *gmsgid,
1389 va_list *ap, diagnostic_t kind)
1391 diagnostic_info diagnostic;
1392 if (kind == DK_PERMERROR)
1394 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1395 permissive_error_kind (global_dc));
1396 diagnostic.option_index = permissive_error_option (global_dc);
1398 else
1400 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1401 if (kind == DK_WARNING || kind == DK_PEDWARN)
1402 diagnostic.option_index = opt;
1404 diagnostic.metadata = metadata;
1405 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1408 /* Implement inform_n, warning_n, and error_n, as documented and
1409 defined below. */
1410 static bool
1411 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1412 int opt, unsigned HOST_WIDE_INT n,
1413 const char *singular_gmsgid,
1414 const char *plural_gmsgid,
1415 va_list *ap, diagnostic_t kind)
1417 diagnostic_info diagnostic;
1418 unsigned long gtn;
1420 if (sizeof n <= sizeof gtn)
1421 gtn = n;
1422 else
1423 /* Use the largest number ngettext can handle, otherwise
1424 preserve the six least significant decimal digits for
1425 languages where the plural form depends on them. */
1426 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1428 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1429 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1430 if (kind == DK_WARNING)
1431 diagnostic.option_index = opt;
1432 diagnostic.metadata = metadata;
1433 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1436 /* Wrapper around diagnostic_impl taking a variable argument list. */
1438 bool
1439 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1440 const char *gmsgid, ...)
1442 auto_diagnostic_group d;
1443 va_list ap;
1444 va_start (ap, gmsgid);
1445 rich_location richloc (line_table, location);
1446 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1447 va_end (ap);
1448 return ret;
1451 /* As above, but for rich_location *. */
1453 bool
1454 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1455 const char *gmsgid, ...)
1457 auto_diagnostic_group d;
1458 va_list ap;
1459 va_start (ap, gmsgid);
1460 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1461 va_end (ap);
1462 return ret;
1465 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1467 bool
1468 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1469 const char *gmsgid, va_list *ap)
1471 rich_location richloc (line_table, location);
1472 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1475 /* An informative note at LOCATION. Use this for additional details on an error
1476 message. */
1477 void
1478 inform (location_t location, const char *gmsgid, ...)
1480 auto_diagnostic_group d;
1481 va_list ap;
1482 va_start (ap, gmsgid);
1483 rich_location richloc (line_table, location);
1484 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1485 va_end (ap);
1488 /* Same as "inform" above, but at RICHLOC. */
1489 void
1490 inform (rich_location *richloc, const char *gmsgid, ...)
1492 gcc_assert (richloc);
1494 auto_diagnostic_group d;
1495 va_list ap;
1496 va_start (ap, gmsgid);
1497 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1498 va_end (ap);
1501 /* An informative note at LOCATION. Use this for additional details on an
1502 error message. */
1503 void
1504 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1505 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1507 va_list ap;
1508 va_start (ap, plural_gmsgid);
1509 auto_diagnostic_group d;
1510 rich_location richloc (line_table, location);
1511 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1512 &ap, DK_NOTE);
1513 va_end (ap);
1516 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1517 to the relevant language specification but is likely to be buggy anyway.
1518 Returns true if the warning was printed, false if it was inhibited. */
1519 bool
1520 warning (int opt, const char *gmsgid, ...)
1522 auto_diagnostic_group d;
1523 va_list ap;
1524 va_start (ap, gmsgid);
1525 rich_location richloc (line_table, input_location);
1526 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1527 va_end (ap);
1528 return ret;
1531 /* A warning at LOCATION. Use this for code which is correct according to the
1532 relevant language specification but is likely to be buggy anyway.
1533 Returns true if the warning was printed, false if it was inhibited. */
1535 bool
1536 warning_at (location_t location, int opt, const char *gmsgid, ...)
1538 auto_diagnostic_group d;
1539 va_list ap;
1540 va_start (ap, gmsgid);
1541 rich_location richloc (line_table, location);
1542 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1543 va_end (ap);
1544 return ret;
1547 /* Same as "warning at" above, but using RICHLOC. */
1549 bool
1550 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1552 gcc_assert (richloc);
1554 auto_diagnostic_group d;
1555 va_list ap;
1556 va_start (ap, gmsgid);
1557 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1558 va_end (ap);
1559 return ret;
1562 /* Same as "warning at" above, but using METADATA. */
1564 bool
1565 warning_meta (rich_location *richloc,
1566 const diagnostic_metadata &metadata,
1567 int opt, const char *gmsgid, ...)
1569 gcc_assert (richloc);
1571 auto_diagnostic_group d;
1572 va_list ap;
1573 va_start (ap, gmsgid);
1574 bool ret
1575 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1576 DK_WARNING);
1577 va_end (ap);
1578 return ret;
1581 /* Same as warning_n plural variant below, but using RICHLOC. */
1583 bool
1584 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1585 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1587 gcc_assert (richloc);
1589 auto_diagnostic_group d;
1590 va_list ap;
1591 va_start (ap, plural_gmsgid);
1592 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1593 singular_gmsgid, plural_gmsgid,
1594 &ap, DK_WARNING);
1595 va_end (ap);
1596 return ret;
1599 /* A warning at LOCATION. Use this for code which is correct according to the
1600 relevant language specification but is likely to be buggy anyway.
1601 Returns true if the warning was printed, false if it was inhibited. */
1603 bool
1604 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1605 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1607 auto_diagnostic_group d;
1608 va_list ap;
1609 va_start (ap, plural_gmsgid);
1610 rich_location richloc (line_table, location);
1611 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1612 singular_gmsgid, plural_gmsgid,
1613 &ap, DK_WARNING);
1614 va_end (ap);
1615 return ret;
1618 /* A "pedantic" warning at LOCATION: issues a warning unless
1619 -pedantic-errors was given on the command line, in which case it
1620 issues an error. Use this for diagnostics required by the relevant
1621 language standard, if you have chosen not to make them errors.
1623 Note that these diagnostics are issued independent of the setting
1624 of the -Wpedantic command-line switch. To get a warning enabled
1625 only with that switch, use either "if (pedantic) pedwarn
1626 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1627 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1629 Returns true if the warning was printed, false if it was inhibited. */
1631 bool
1632 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1634 auto_diagnostic_group d;
1635 va_list ap;
1636 va_start (ap, gmsgid);
1637 rich_location richloc (line_table, location);
1638 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1639 va_end (ap);
1640 return ret;
1643 /* Same as pedwarn above, but using RICHLOC. */
1645 bool
1646 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1648 gcc_assert (richloc);
1650 auto_diagnostic_group d;
1651 va_list ap;
1652 va_start (ap, gmsgid);
1653 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1654 va_end (ap);
1655 return ret;
1658 /* A "permissive" error at LOCATION: issues an error unless
1659 -fpermissive was given on the command line, in which case it issues
1660 a warning. Use this for things that really should be errors but we
1661 want to support legacy code.
1663 Returns true if the warning was printed, false if it was inhibited. */
1665 bool
1666 permerror (location_t location, const char *gmsgid, ...)
1668 auto_diagnostic_group d;
1669 va_list ap;
1670 va_start (ap, gmsgid);
1671 rich_location richloc (line_table, location);
1672 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1673 va_end (ap);
1674 return ret;
1677 /* Same as "permerror" above, but at RICHLOC. */
1679 bool
1680 permerror (rich_location *richloc, const char *gmsgid, ...)
1682 gcc_assert (richloc);
1684 auto_diagnostic_group d;
1685 va_list ap;
1686 va_start (ap, gmsgid);
1687 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1688 va_end (ap);
1689 return ret;
1692 /* A hard error: the code is definitely ill-formed, and an object file
1693 will not be produced. */
1694 void
1695 error (const char *gmsgid, ...)
1697 auto_diagnostic_group d;
1698 va_list ap;
1699 va_start (ap, gmsgid);
1700 rich_location richloc (line_table, input_location);
1701 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1702 va_end (ap);
1705 /* A hard error: the code is definitely ill-formed, and an object file
1706 will not be produced. */
1707 void
1708 error_n (location_t location, unsigned HOST_WIDE_INT n,
1709 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1711 auto_diagnostic_group d;
1712 va_list ap;
1713 va_start (ap, plural_gmsgid);
1714 rich_location richloc (line_table, location);
1715 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1716 &ap, DK_ERROR);
1717 va_end (ap);
1720 /* Same as above, but use location LOC instead of input_location. */
1721 void
1722 error_at (location_t loc, const char *gmsgid, ...)
1724 auto_diagnostic_group d;
1725 va_list ap;
1726 va_start (ap, gmsgid);
1727 rich_location richloc (line_table, loc);
1728 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1729 va_end (ap);
1732 /* Same as above, but use RICH_LOC. */
1734 void
1735 error_at (rich_location *richloc, const char *gmsgid, ...)
1737 gcc_assert (richloc);
1739 auto_diagnostic_group d;
1740 va_list ap;
1741 va_start (ap, gmsgid);
1742 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1743 va_end (ap);
1746 /* "Sorry, not implemented." Use for a language feature which is
1747 required by the relevant specification but not implemented by GCC.
1748 An object file will not be produced. */
1749 void
1750 sorry (const char *gmsgid, ...)
1752 auto_diagnostic_group d;
1753 va_list ap;
1754 va_start (ap, gmsgid);
1755 rich_location richloc (line_table, input_location);
1756 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1757 va_end (ap);
1760 /* Same as above, but use location LOC instead of input_location. */
1761 void
1762 sorry_at (location_t loc, const char *gmsgid, ...)
1764 auto_diagnostic_group d;
1765 va_list ap;
1766 va_start (ap, gmsgid);
1767 rich_location richloc (line_table, loc);
1768 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1769 va_end (ap);
1772 /* Return true if an error or a "sorry" has been seen. Various
1773 processing is disabled after errors. */
1774 bool
1775 seen_error (void)
1777 return errorcount || sorrycount;
1780 /* An error which is severe enough that we make no attempt to
1781 continue. Do not use this for internal consistency checks; that's
1782 internal_error. Use of this function should be rare. */
1783 void
1784 fatal_error (location_t loc, const char *gmsgid, ...)
1786 auto_diagnostic_group d;
1787 va_list ap;
1788 va_start (ap, gmsgid);
1789 rich_location richloc (line_table, loc);
1790 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1791 va_end (ap);
1793 gcc_unreachable ();
1796 /* An internal consistency check has failed. We make no attempt to
1797 continue. Note that unless there is debugging value to be had from
1798 a more specific message, or some other good reason, you should use
1799 abort () instead of calling this function directly. */
1800 void
1801 internal_error (const char *gmsgid, ...)
1803 auto_diagnostic_group d;
1804 va_list ap;
1805 va_start (ap, gmsgid);
1806 rich_location richloc (line_table, input_location);
1807 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
1808 va_end (ap);
1810 gcc_unreachable ();
1813 /* Like internal_error, but no backtrace will be printed. Used when
1814 the internal error does not happen at the current location, but happened
1815 somewhere else. */
1816 void
1817 internal_error_no_backtrace (const char *gmsgid, ...)
1819 auto_diagnostic_group d;
1820 va_list ap;
1821 va_start (ap, gmsgid);
1822 rich_location richloc (line_table, input_location);
1823 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1824 va_end (ap);
1826 gcc_unreachable ();
1829 /* Special case error functions. Most are implemented in terms of the
1830 above, or should be. */
1832 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1833 runs its second argument through gettext. */
1834 void
1835 fnotice (FILE *file, const char *cmsgid, ...)
1837 va_list ap;
1839 va_start (ap, cmsgid);
1840 vfprintf (file, _(cmsgid), ap);
1841 va_end (ap);
1844 /* Inform the user that an error occurred while trying to report some
1845 other error. This indicates catastrophic internal inconsistencies,
1846 so give up now. But do try to flush out the previous error.
1847 This mustn't use internal_error, that will cause infinite recursion. */
1849 static void
1850 error_recursion (diagnostic_context *context)
1852 if (context->lock < 3)
1853 pp_newline_and_flush (context->printer);
1855 fnotice (stderr,
1856 "Internal compiler error: Error reporting routines re-entered.\n");
1858 /* Call diagnostic_action_after_output to get the "please submit a bug
1859 report" message. */
1860 diagnostic_action_after_output (context, DK_ICE);
1862 /* Do not use gcc_unreachable here; that goes through internal_error
1863 and therefore would cause infinite recursion. */
1864 real_abort ();
1867 /* Report an internal compiler error in a friendly manner. This is
1868 the function that gets called upon use of abort() in the source
1869 code generally, thanks to a special macro. */
1871 void
1872 fancy_abort (const char *file, int line, const char *function)
1874 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
1877 /* class auto_diagnostic_group. */
1879 /* Constructor: "push" this group into global_dc. */
1881 auto_diagnostic_group::auto_diagnostic_group ()
1883 global_dc->diagnostic_group_nesting_depth++;
1886 /* Destructor: "pop" this group from global_dc. */
1888 auto_diagnostic_group::~auto_diagnostic_group ()
1890 if (--global_dc->diagnostic_group_nesting_depth == 0)
1892 /* Handle the case where we've popped the final diagnostic group.
1893 If any diagnostics were emitted, give the context a chance
1894 to do something. */
1895 if (global_dc->diagnostic_group_emission_count > 0)
1897 if (global_dc->end_group_cb)
1898 global_dc->end_group_cb (global_dc);
1900 global_dc->diagnostic_group_emission_count = 0;
1904 /* Implementation of diagnostic_path::num_events vfunc for
1905 simple_diagnostic_path: simply get the number of events in the vec. */
1907 unsigned
1908 simple_diagnostic_path::num_events () const
1910 return m_events.length ();
1913 /* Implementation of diagnostic_path::get_event vfunc for
1914 simple_diagnostic_path: simply return the event in the vec. */
1916 const diagnostic_event &
1917 simple_diagnostic_path::get_event (int idx) const
1919 return *m_events[idx];
1922 /* Add an event to this path at LOC within function FNDECL at
1923 stack depth DEPTH.
1925 Use m_context's printer to format FMT, as the text of the new
1926 event.
1928 Return the id of the new event. */
1930 diagnostic_event_id_t
1931 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
1932 const char *fmt, ...)
1934 pretty_printer *pp = m_event_pp;
1935 pp_clear_output_area (pp);
1937 text_info ti;
1938 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1940 va_list ap;
1942 va_start (ap, fmt);
1944 ti.format_spec = _(fmt);
1945 ti.args_ptr = &ap;
1946 ti.err_no = 0;
1947 ti.x_data = NULL;
1948 ti.m_richloc = &rich_loc;
1950 pp_format (pp, &ti);
1951 pp_output_formatted_text (pp);
1953 va_end (ap);
1955 simple_diagnostic_event *new_event
1956 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
1957 m_events.safe_push (new_event);
1959 pp_clear_output_area (pp);
1961 return diagnostic_event_id_t (m_events.length () - 1);
1964 /* struct simple_diagnostic_event. */
1966 /* simple_diagnostic_event's ctor. */
1968 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
1969 tree fndecl,
1970 int depth,
1971 const char *desc)
1972 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
1976 /* simple_diagnostic_event's dtor. */
1978 simple_diagnostic_event::~simple_diagnostic_event ()
1980 free (m_desc);
1983 /* Print PATH by emitting a dummy "note" associated with it. */
1985 DEBUG_FUNCTION
1986 void debug (diagnostic_path *path)
1988 rich_location richloc (line_table, UNKNOWN_LOCATION);
1989 richloc.set_path (path);
1990 inform (&richloc, "debug path");
1993 /* Really call the system 'abort'. This has to go right at the end of
1994 this file, so that there are no functions after it that call abort
1995 and get the system abort instead of our macro. */
1996 #undef abort
1997 static void
1998 real_abort (void)
2000 abort ();
2003 #if CHECKING_P
2005 namespace selftest {
2007 /* Helper function for test_print_escaped_string. */
2009 static void
2010 assert_print_escaped_string (const location &loc, const char *expected_output,
2011 const char *input)
2013 pretty_printer pp;
2014 print_escaped_string (&pp, input);
2015 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2018 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2019 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2021 /* Tests of print_escaped_string. */
2023 static void
2024 test_print_escaped_string ()
2026 /* Empty string. */
2027 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2029 /* Non-empty string. */
2030 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2032 /* Various things that need to be escaped: */
2033 /* Backslash. */
2034 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2035 "before\\after");
2036 /* Tab. */
2037 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2038 "before\tafter");
2039 /* Newline. */
2040 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2041 "before\nafter");
2042 /* Double quote. */
2043 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2044 "before\"after");
2046 /* Non-printable characters: BEL: '\a': 0x07 */
2047 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2048 "before\aafter");
2049 /* Non-printable characters: vertical tab: '\v': 0x0b */
2050 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2051 "before\vafter");
2054 /* Tests of print_parseable_fixits. */
2056 /* Verify that print_parseable_fixits emits the empty string if there
2057 are no fixits. */
2059 static void
2060 test_print_parseable_fixits_none ()
2062 pretty_printer pp;
2063 rich_location richloc (line_table, UNKNOWN_LOCATION);
2065 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2066 ASSERT_STREQ ("", pp_formatted_text (&pp));
2069 /* Verify that print_parseable_fixits does the right thing if there
2070 is an insertion fixit hint. */
2072 static void
2073 test_print_parseable_fixits_insert ()
2075 pretty_printer pp;
2076 rich_location richloc (line_table, UNKNOWN_LOCATION);
2078 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2079 linemap_line_start (line_table, 5, 100);
2080 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2081 location_t where = linemap_position_for_column (line_table, 10);
2082 richloc.add_fixit_insert_before (where, "added content");
2084 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2085 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2086 pp_formatted_text (&pp));
2089 /* Verify that print_parseable_fixits does the right thing if there
2090 is an removal fixit hint. */
2092 static void
2093 test_print_parseable_fixits_remove ()
2095 pretty_printer pp;
2096 rich_location richloc (line_table, UNKNOWN_LOCATION);
2098 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2099 linemap_line_start (line_table, 5, 100);
2100 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2101 source_range where;
2102 where.m_start = linemap_position_for_column (line_table, 10);
2103 where.m_finish = linemap_position_for_column (line_table, 20);
2104 richloc.add_fixit_remove (where);
2106 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2107 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2108 pp_formatted_text (&pp));
2111 /* Verify that print_parseable_fixits does the right thing if there
2112 is an replacement fixit hint. */
2114 static void
2115 test_print_parseable_fixits_replace ()
2117 pretty_printer pp;
2118 rich_location richloc (line_table, UNKNOWN_LOCATION);
2120 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2121 linemap_line_start (line_table, 5, 100);
2122 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2123 source_range where;
2124 where.m_start = linemap_position_for_column (line_table, 10);
2125 where.m_finish = linemap_position_for_column (line_table, 20);
2126 richloc.add_fixit_replace (where, "replacement");
2128 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2129 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2130 pp_formatted_text (&pp));
2133 /* Verify that print_parseable_fixits correctly handles
2134 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2136 static void
2137 test_print_parseable_fixits_bytes_vs_display_columns ()
2139 line_table_test ltt;
2140 rich_location richloc (line_table, UNKNOWN_LOCATION);
2142 /* 1-based byte offsets: 12345677778888999900001234567. */
2143 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2144 /* 1-based display cols: 123456[......7-8.....]9012345. */
2145 const int tabstop = 8;
2147 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2148 const char *const fname = tmp.get_filename ();
2150 linemap_add (line_table, LC_ENTER, false, fname, 0);
2151 linemap_line_start (line_table, 1, 100);
2152 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2153 source_range where;
2154 where.m_start = linemap_position_for_column (line_table, 12);
2155 where.m_finish = linemap_position_for_column (line_table, 17);
2156 richloc.add_fixit_replace (where, "color");
2158 const int buf_len = strlen (fname) + 100;
2159 char *const expected = XNEWVEC (char, buf_len);
2162 pretty_printer pp;
2163 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2164 tabstop);
2165 snprintf (expected, buf_len,
2166 "fix-it:\"%s\":{1:12-1:18}:\"color\"\n", fname);
2167 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2170 pretty_printer pp;
2171 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2172 tabstop);
2173 snprintf (expected, buf_len,
2174 "fix-it:\"%s\":{1:10-1:16}:\"color\"\n", fname);
2175 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2178 XDELETEVEC (expected);
2181 /* Verify that
2182 diagnostic_get_location_text (..., SHOW_COLUMN)
2183 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2184 colorization disabled. */
2186 static void
2187 assert_location_text (const char *expected_loc_text,
2188 const char *filename, int line, int column,
2189 bool show_column,
2190 int origin = 1,
2191 enum diagnostics_column_unit column_unit
2192 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2194 test_diagnostic_context dc;
2195 dc.show_column = show_column;
2196 dc.column_unit = column_unit;
2197 dc.column_origin = origin;
2199 expanded_location xloc;
2200 xloc.file = filename;
2201 xloc.line = line;
2202 xloc.column = column;
2203 xloc.data = NULL;
2204 xloc.sysp = false;
2206 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2207 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2208 free (actual_loc_text);
2211 /* Verify that diagnostic_get_location_text works as expected. */
2213 static void
2214 test_diagnostic_get_location_text ()
2216 const char *old_progname = progname;
2217 progname = "PROGNAME";
2218 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2219 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2220 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2221 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2222 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2223 for (int origin = 0; origin != 2; ++origin)
2224 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2225 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2226 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2227 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2229 maybe_line_and_column (INT_MAX, INT_MAX);
2230 maybe_line_and_column (INT_MIN, INT_MIN);
2233 /* In order to test display columns vs byte columns, we need to create a
2234 file for location_get_source_line() to read. */
2236 const char *const content = "smile \xf0\x9f\x98\x82\n";
2237 const int line_bytes = strlen (content) - 1;
2238 const int def_tabstop = 8;
2239 const int display_width = cpp_display_width (content, line_bytes,
2240 def_tabstop);
2241 ASSERT_EQ (line_bytes - 2, display_width);
2242 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2243 const char *const fname = tmp.get_filename ();
2244 const int buf_len = strlen (fname) + 16;
2245 char *const expected = XNEWVEC (char, buf_len);
2247 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2248 assert_location_text (expected, fname, 1, line_bytes, true,
2249 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2251 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2252 assert_location_text (expected, fname, 1, line_bytes, true,
2253 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2255 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2256 assert_location_text (expected, fname, 1, line_bytes, true,
2257 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2259 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2260 assert_location_text (expected, fname, 1, line_bytes, true,
2261 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2263 XDELETEVEC (expected);
2267 progname = old_progname;
2270 /* Selftest for num_digits. */
2272 static void
2273 test_num_digits ()
2275 ASSERT_EQ (1, num_digits (0));
2276 ASSERT_EQ (1, num_digits (9));
2277 ASSERT_EQ (2, num_digits (10));
2278 ASSERT_EQ (2, num_digits (99));
2279 ASSERT_EQ (3, num_digits (100));
2280 ASSERT_EQ (3, num_digits (999));
2281 ASSERT_EQ (4, num_digits (1000));
2282 ASSERT_EQ (4, num_digits (9999));
2283 ASSERT_EQ (5, num_digits (10000));
2284 ASSERT_EQ (5, num_digits (99999));
2285 ASSERT_EQ (6, num_digits (100000));
2286 ASSERT_EQ (6, num_digits (999999));
2287 ASSERT_EQ (7, num_digits (1000000));
2288 ASSERT_EQ (7, num_digits (9999999));
2289 ASSERT_EQ (8, num_digits (10000000));
2290 ASSERT_EQ (8, num_digits (99999999));
2293 /* Run all of the selftests within this file. */
2295 void
2296 diagnostic_c_tests ()
2298 test_print_escaped_string ();
2299 test_print_parseable_fixits_none ();
2300 test_print_parseable_fixits_insert ();
2301 test_print_parseable_fixits_remove ();
2302 test_print_parseable_fixits_replace ();
2303 test_print_parseable_fixits_bytes_vs_display_columns ();
2304 test_diagnostic_get_location_text ();
2305 test_num_digits ();
2309 } // namespace selftest
2311 #endif /* #if CHECKING_P */
2313 #if __GNUC__ >= 10
2314 # pragma GCC diagnostic pop
2315 #endif