]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/diagnostic.cc
PR middle-end/105604 - ICE: in tree_to_shwi with vla in struct and sprintf
[thirdparty/gcc.git] / gcc / diagnostic.cc
1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2022 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21
22 /* This file implements the language independent aspect of diagnostic
23 message module. */
24
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"
42
43 #ifdef HAVE_TERMIOS_H
44 # include <termios.h>
45 #endif
46
47 #ifdef GWINSZ_IN_SYS_IOCTL
48 # include <sys/ioctl.h>
49 #endif
50
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
57
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)
62
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);
71
72 static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
73 static void real_abort (void) ATTRIBUTE_NORETURN;
74
75 /* Name of program invoked, sans directories. */
76
77 const char *progname;
78
79 /* A diagnostic_context surrogate for stderr. */
80 static diagnostic_context global_diagnostic_context;
81 diagnostic_context *global_dc = &global_diagnostic_context;
82 \f
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, ...)
87 {
88 char *str;
89 va_list ap;
90
91 va_start (ap, msg);
92 str = xvasprintf (msg, ap);
93 va_end (ap);
94
95 return str;
96 }
97
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)
101 {
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);
106 }
107
108
109 \f
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. */
113 int
114 get_terminal_width (void)
115 {
116 const char * s = getenv ("COLUMNS");
117 if (s != NULL) {
118 int n = atoi (s);
119 if (n > 0)
120 return n;
121 }
122
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
129
130 return INT_MAX;
131 }
132
133 /* Set caret_max_width to value. */
134 void
135 diagnostic_set_caret_max_width (diagnostic_context *context, int value)
136 {
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);
141
142 if (value <= 0)
143 value = INT_MAX;
144
145 context->caret_max_width = value;
146 }
147
148 /* Default implementation of final_cb. */
149
150 static void
151 default_diagnostic_final_cb (diagnostic_context *context)
152 {
153 /* Some of the errors may actually have been warnings. */
154 if (diagnostic_kind_count (context, DK_WERROR))
155 {
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);
167 }
168 }
169
170 /* Initialize the diagnostic message outputting machinery. */
171 void
172 diagnostic_initialize (diagnostic_context *context, int n_opts)
173 {
174 int i;
175
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 ();
180
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 context->report_bug = false;
223
224 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
225 {
226 if (!strcmp (var, "fixits-v1"))
227 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
228 else if (!strcmp (var, "fixits-v2"))
229 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
230 /* Silently ignore unrecognized values. */
231 }
232 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
233 context->column_origin = 1;
234 context->tabstop = 8;
235 context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
236 context->edit_context_ptr = NULL;
237 context->diagnostic_group_nesting_depth = 0;
238 context->diagnostic_group_emission_count = 0;
239 context->begin_group_cb = NULL;
240 context->end_group_cb = NULL;
241 context->final_cb = default_diagnostic_final_cb;
242 context->includes_seen = NULL;
243 }
244
245 /* Maybe initialize the color support. We require clients to do this
246 explicitly, since most clients don't want color. When called
247 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
248
249 void
250 diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
251 {
252 /* value == -1 is the default value. */
253 if (value < 0)
254 {
255 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
256 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
257 otherwise default to -fdiagnostics-color=never, for other
258 values default to that
259 -fdiagnostics-color={never,auto,always}. */
260 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
261 {
262 if (!getenv ("GCC_COLORS"))
263 return;
264 value = DIAGNOSTICS_COLOR_AUTO;
265 }
266 else
267 value = DIAGNOSTICS_COLOR_DEFAULT;
268 }
269 pp_show_color (context->printer)
270 = colorize_init ((diagnostic_color_rule_t) value);
271 }
272
273 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
274
275 void
276 diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
277 {
278 /* value == -1 is the default value. */
279 if (value < 0)
280 {
281 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
282 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
283 environment, otherwise default to -fdiagnostics-urls=never,
284 for other values default to that
285 -fdiagnostics-urls={never,auto,always}. */
286 if (DIAGNOSTICS_URLS_DEFAULT == -1)
287 {
288 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
289 return;
290 value = DIAGNOSTICS_URL_AUTO;
291 }
292 else
293 value = DIAGNOSTICS_URLS_DEFAULT;
294 }
295
296 context->printer->url_format
297 = determine_url_format ((diagnostic_url_rule_t) value);
298 }
299
300 /* Create the file_cache, if not already created, and tell it how to
301 translate files on input. */
302 void diagnostic_initialize_input_context (diagnostic_context *context,
303 diagnostic_input_charset_callback ccb,
304 bool should_skip_bom)
305 {
306 if (!context->m_file_cache)
307 context->m_file_cache = new file_cache;
308 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
309 }
310
311 /* Do any cleaning up required after the last diagnostic is emitted. */
312
313 void
314 diagnostic_finish (diagnostic_context *context)
315 {
316 if (context->final_cb)
317 context->final_cb (context);
318
319 diagnostic_file_cache_fini ();
320
321 XDELETEVEC (context->classify_diagnostic);
322 context->classify_diagnostic = NULL;
323
324 /* diagnostic_initialize allocates context->printer using XNEW
325 and placement-new. */
326 context->printer->~pretty_printer ();
327 XDELETE (context->printer);
328 context->printer = NULL;
329
330 if (context->edit_context_ptr)
331 {
332 delete context->edit_context_ptr;
333 context->edit_context_ptr = NULL;
334 }
335
336 if (context->includes_seen)
337 {
338 delete context->includes_seen;
339 context->includes_seen = nullptr;
340 }
341 }
342
343 /* Initialize DIAGNOSTIC, where the message MSG has already been
344 translated. */
345 void
346 diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
347 va_list *args, rich_location *richloc,
348 diagnostic_t kind)
349 {
350 gcc_assert (richloc);
351 diagnostic->message.err_no = errno;
352 diagnostic->message.args_ptr = args;
353 diagnostic->message.format_spec = msg;
354 diagnostic->message.m_richloc = richloc;
355 diagnostic->richloc = richloc;
356 diagnostic->metadata = NULL;
357 diagnostic->kind = kind;
358 diagnostic->option_index = 0;
359 }
360
361 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
362 translated. */
363 void
364 diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
365 va_list *args, rich_location *richloc,
366 diagnostic_t kind)
367 {
368 gcc_assert (richloc);
369 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
370 }
371
372 static const char *const diagnostic_kind_color[] = {
373 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
374 #include "diagnostic.def"
375 #undef DEFINE_DIAGNOSTIC_KIND
376 NULL
377 };
378
379 /* Get a color name for diagnostics of type KIND
380 Result could be NULL. */
381
382 const char *
383 diagnostic_get_color_for_kind (diagnostic_t kind)
384 {
385 return diagnostic_kind_color[kind];
386 }
387
388 /* Given an expanded_location, convert the column (which is in 1-based bytes)
389 to the requested units, without converting the origin.
390 Return -1 if the column is invalid (<= 0). */
391
392 static int
393 convert_column_unit (enum diagnostics_column_unit column_unit,
394 int tabstop,
395 expanded_location s)
396 {
397 if (s.column <= 0)
398 return -1;
399
400 switch (column_unit)
401 {
402 default:
403 gcc_unreachable ();
404
405 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
406 {
407 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
408 return location_compute_display_column (s, policy);
409 }
410
411 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
412 return s.column;
413 }
414 }
415
416 /* Given an expanded_location, convert the column (which is in 1-based bytes)
417 to the requested units and origin. Return -1 if the column is
418 invalid (<= 0). */
419 int
420 diagnostic_converted_column (diagnostic_context *context, expanded_location s)
421 {
422 int one_based_col
423 = convert_column_unit (context->column_unit, context->tabstop, s);
424 if (one_based_col <= 0)
425 return -1;
426 return one_based_col + (context->column_origin - 1);
427 }
428
429 /* Return a formatted line and column ':%line:%column'. Elided if
430 line == 0 or col < 0. (A column of 0 may be valid due to the
431 -fdiagnostics-column-origin option.)
432 The result is a statically allocated buffer. */
433
434 static const char *
435 maybe_line_and_column (int line, int col)
436 {
437 static char result[32];
438
439 if (line)
440 {
441 size_t l
442 = snprintf (result, sizeof (result),
443 col >= 0 ? ":%d:%d" : ":%d", line, col);
444 gcc_checking_assert (l < sizeof (result));
445 }
446 else
447 result[0] = 0;
448 return result;
449 }
450
451 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
452 The caller is responsible for freeing the memory. */
453
454 static char *
455 diagnostic_get_location_text (diagnostic_context *context,
456 expanded_location s)
457 {
458 pretty_printer *pp = context->printer;
459 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
460 const char *locus_ce = colorize_stop (pp_show_color (pp));
461 const char *file = s.file ? s.file : progname;
462 int line = 0;
463 int col = -1;
464 if (strcmp (file, N_("<built-in>")))
465 {
466 line = s.line;
467 if (context->show_column)
468 col = diagnostic_converted_column (context, s);
469 }
470
471 const char *line_col = maybe_line_and_column (line, col);
472 return build_message_string ("%s%s%s:%s", locus_cs, file,
473 line_col, locus_ce);
474 }
475
476 static const char *const diagnostic_kind_text[] = {
477 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
478 #include "diagnostic.def"
479 #undef DEFINE_DIAGNOSTIC_KIND
480 "must-not-happen"
481 };
482
483 /* Return a malloc'd string describing a location and the severity of the
484 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
485 freeing the memory. */
486 char *
487 diagnostic_build_prefix (diagnostic_context *context,
488 const diagnostic_info *diagnostic)
489 {
490 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
491
492 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
493 const char *text_cs = "", *text_ce = "";
494 pretty_printer *pp = context->printer;
495
496 if (diagnostic_kind_color[diagnostic->kind])
497 {
498 text_cs = colorize_start (pp_show_color (pp),
499 diagnostic_kind_color[diagnostic->kind]);
500 text_ce = colorize_stop (pp_show_color (pp));
501 }
502
503 expanded_location s = diagnostic_expand_location (diagnostic);
504 char *location_text = diagnostic_get_location_text (context, s);
505
506 char *result = build_message_string ("%s %s%s%s", location_text,
507 text_cs, text, text_ce);
508 free (location_text);
509 return result;
510 }
511
512 /* Functions at which to stop the backtrace print. It's not
513 particularly helpful to print the callers of these functions. */
514
515 static const char * const bt_stop[] =
516 {
517 "main",
518 "toplev::main",
519 "execute_one_pass",
520 "compile_file",
521 };
522
523 /* A callback function passed to the backtrace_full function. */
524
525 static int
526 bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
527 const char *function)
528 {
529 int *pcount = (int *) data;
530
531 /* If we don't have any useful information, don't print
532 anything. */
533 if (filename == NULL && function == NULL)
534 return 0;
535
536 /* Skip functions in diagnostic.cc. */
537 if (*pcount == 0
538 && filename != NULL
539 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
540 return 0;
541
542 /* Print up to 20 functions. We could make this a --param, but
543 since this is only for debugging just use a constant for now. */
544 if (*pcount >= 20)
545 {
546 /* Returning a non-zero value stops the backtrace. */
547 return 1;
548 }
549 ++*pcount;
550
551 char *alc = NULL;
552 if (function != NULL)
553 {
554 char *str = cplus_demangle_v3 (function,
555 (DMGL_VERBOSE | DMGL_ANSI
556 | DMGL_GNU_V3 | DMGL_PARAMS));
557 if (str != NULL)
558 {
559 alc = str;
560 function = str;
561 }
562
563 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
564 {
565 size_t len = strlen (bt_stop[i]);
566 if (strncmp (function, bt_stop[i], len) == 0
567 && (function[len] == '\0' || function[len] == '('))
568 {
569 if (alc != NULL)
570 free (alc);
571 /* Returning a non-zero value stops the backtrace. */
572 return 1;
573 }
574 }
575 }
576
577 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
578 (unsigned long) pc,
579 function == NULL ? "???" : function,
580 filename == NULL ? "???" : filename,
581 lineno);
582
583 if (alc != NULL)
584 free (alc);
585
586 return 0;
587 }
588
589 /* A callback function passed to the backtrace_full function. This is
590 called if backtrace_full has an error. */
591
592 static void
593 bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
594 {
595 if (errnum < 0)
596 {
597 /* This means that no debug info was available. Just quietly
598 skip printing backtrace info. */
599 return;
600 }
601 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
602 errnum == 0 ? "" : xstrerror (errnum));
603 }
604
605 /* Check if we've met the maximum error limit, and if so fatally exit
606 with a message. CONTEXT is the context to check, and FLUSH
607 indicates whether a diagnostic_finish call is needed. */
608
609 void
610 diagnostic_check_max_errors (diagnostic_context *context, bool flush)
611 {
612 if (!context->max_errors)
613 return;
614
615 int count = (diagnostic_kind_count (context, DK_ERROR)
616 + diagnostic_kind_count (context, DK_SORRY)
617 + diagnostic_kind_count (context, DK_WERROR));
618
619 if (count >= context->max_errors)
620 {
621 fnotice (stderr,
622 "compilation terminated due to -fmax-errors=%u.\n",
623 context->max_errors);
624 if (flush)
625 diagnostic_finish (context);
626 exit (FATAL_EXIT_CODE);
627 }
628 }
629
630 /* Take any action which is expected to happen after the diagnostic
631 is written out. This function does not always return. */
632 void
633 diagnostic_action_after_output (diagnostic_context *context,
634 diagnostic_t diag_kind)
635 {
636 switch (diag_kind)
637 {
638 case DK_DEBUG:
639 case DK_NOTE:
640 case DK_ANACHRONISM:
641 case DK_WARNING:
642 break;
643
644 case DK_ERROR:
645 case DK_SORRY:
646 if (context->abort_on_error)
647 real_abort ();
648 if (context->fatal_errors)
649 {
650 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
651 diagnostic_finish (context);
652 exit (FATAL_EXIT_CODE);
653 }
654 break;
655
656 case DK_ICE:
657 case DK_ICE_NOBT:
658 {
659 struct backtrace_state *state = NULL;
660 if (diag_kind == DK_ICE)
661 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
662 int count = 0;
663 if (state != NULL)
664 backtrace_full (state, 2, bt_callback, bt_err_callback,
665 (void *) &count);
666
667 if (context->abort_on_error)
668 real_abort ();
669
670 if (context->report_bug)
671 fnotice (stderr, "Please submit a full bug report, "
672 "with preprocessed source.\n");
673 else
674 fnotice (stderr, "Please submit a full bug report, "
675 "with preprocessed source (by using -freport-bug).\n");
676
677 if (count > 0)
678 fnotice (stderr, "Please include the complete backtrace "
679 "with any bug report.\n");
680 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
681
682 exit (ICE_EXIT_CODE);
683 }
684
685 case DK_FATAL:
686 if (context->abort_on_error)
687 real_abort ();
688 diagnostic_finish (context);
689 fnotice (stderr, "compilation terminated.\n");
690 exit (FATAL_EXIT_CODE);
691
692 default:
693 gcc_unreachable ();
694 }
695 }
696
697 /* True if the last module or file in which a diagnostic was reported is
698 different from the current one. */
699
700 static bool
701 last_module_changed_p (diagnostic_context *context,
702 const line_map_ordinary *map)
703 {
704 return context->last_module != map;
705 }
706
707 /* Remember the current module or file as being the last one in which we
708 report a diagnostic. */
709
710 static void
711 set_last_module (diagnostic_context *context, const line_map_ordinary *map)
712 {
713 context->last_module = map;
714 }
715
716 /* Only dump the "In file included from..." stack once for each file. */
717
718 static bool
719 includes_seen (diagnostic_context *context, const line_map_ordinary *map)
720 {
721 /* No include path for main. */
722 if (MAIN_FILE_P (map))
723 return true;
724
725 /* Always identify C++ modules, at least for now. */
726 auto probe = map;
727 if (linemap_check_ordinary (map)->reason == LC_RENAME)
728 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
729 probe = linemap_included_from_linemap (line_table, map);
730 if (MAP_MODULE_P (probe))
731 return false;
732
733 if (!context->includes_seen)
734 context->includes_seen = new hash_set<location_t, false, location_hash>;
735
736 /* Hash the location of the #include directive to better handle files
737 that are included multiple times with different macros defined. */
738 return context->includes_seen->add (linemap_included_from (map));
739 }
740
741 void
742 diagnostic_report_current_module (diagnostic_context *context, location_t where)
743 {
744 const line_map_ordinary *map = NULL;
745
746 if (pp_needs_newline (context->printer))
747 {
748 pp_newline (context->printer);
749 pp_needs_newline (context->printer) = false;
750 }
751
752 if (where <= BUILTINS_LOCATION)
753 return;
754
755 linemap_resolve_location (line_table, where,
756 LRK_MACRO_DEFINITION_LOCATION,
757 &map);
758
759 if (map && last_module_changed_p (context, map))
760 {
761 set_last_module (context, map);
762 if (!includes_seen (context, map))
763 {
764 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
765 expanded_location s = {};
766 do
767 {
768 where = linemap_included_from (map);
769 map = linemap_included_from_linemap (line_table, map);
770 bool is_module = MAP_MODULE_P (map);
771 s.file = LINEMAP_FILE (map);
772 s.line = SOURCE_LINE (map, where);
773 int col = -1;
774 if (first && context->show_column)
775 {
776 s.column = SOURCE_COLUMN (map, where);
777 col = diagnostic_converted_column (context, s);
778 }
779 const char *line_col = maybe_line_and_column (s.line, col);
780 static const char *const msgs[] =
781 {
782 NULL,
783 N_(" from"),
784 N_("In file included from"), /* 2 */
785 N_(" included from"),
786 N_("In module"), /* 4 */
787 N_("of module"),
788 N_("In module imported at"), /* 6 */
789 N_("imported at"),
790 };
791
792 unsigned index = (was_module ? 6 : is_module ? 4
793 : need_inc ? 2 : 0) + !first;
794
795 pp_verbatim (context->printer, "%s%s %r%s%s%R",
796 first ? "" : was_module ? ", " : ",\n",
797 _(msgs[index]),
798 "locus", s.file, line_col);
799 first = false, need_inc = was_module, was_module = is_module;
800 }
801 while (!includes_seen (context, map));
802 pp_verbatim (context->printer, ":");
803 pp_newline (context->printer);
804 }
805 }
806 }
807
808 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
809 print the path. */
810
811 void
812 diagnostic_show_any_path (diagnostic_context *context,
813 diagnostic_info *diagnostic)
814 {
815 const diagnostic_path *path = diagnostic->richloc->get_path ();
816 if (!path)
817 return;
818
819 if (context->print_path)
820 context->print_path (context, path);
821 }
822
823 /* Return true if the events in this path involve more than one
824 function, or false if it is purely intraprocedural. */
825
826 bool
827 diagnostic_path::interprocedural_p () const
828 {
829 const unsigned num = num_events ();
830 for (unsigned i = 0; i < num; i++)
831 {
832 if (get_event (i).get_fndecl () != get_event (0).get_fndecl ())
833 return true;
834 if (get_event (i).get_stack_depth () != get_event (0).get_stack_depth ())
835 return true;
836 }
837 return false;
838 }
839
840 void
841 default_diagnostic_starter (diagnostic_context *context,
842 diagnostic_info *diagnostic)
843 {
844 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
845 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
846 diagnostic));
847 }
848
849 void
850 default_diagnostic_start_span_fn (diagnostic_context *context,
851 expanded_location exploc)
852 {
853 char *text = diagnostic_get_location_text (context, exploc);
854 pp_string (context->printer, text);
855 free (text);
856 pp_newline (context->printer);
857 }
858
859 void
860 default_diagnostic_finalizer (diagnostic_context *context,
861 diagnostic_info *diagnostic,
862 diagnostic_t)
863 {
864 char *saved_prefix = pp_take_prefix (context->printer);
865 pp_set_prefix (context->printer, NULL);
866 pp_newline (context->printer);
867 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
868 pp_set_prefix (context->printer, saved_prefix);
869 pp_flush (context->printer);
870 }
871
872 /* Interface to specify diagnostic kind overrides. Returns the
873 previous setting, or DK_UNSPECIFIED if the parameters are out of
874 range. If OPTION_INDEX is zero, the new setting is for all the
875 diagnostics. */
876 diagnostic_t
877 diagnostic_classify_diagnostic (diagnostic_context *context,
878 int option_index,
879 diagnostic_t new_kind,
880 location_t where)
881 {
882 diagnostic_t old_kind;
883
884 if (option_index < 0
885 || option_index >= context->n_opts
886 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
887 return DK_UNSPECIFIED;
888
889 old_kind = context->classify_diagnostic[option_index];
890
891 /* Handle pragmas separately, since we need to keep track of *where*
892 the pragmas were. */
893 if (where != UNKNOWN_LOCATION)
894 {
895 int i;
896
897 /* Record the command-line status, so we can reset it back on DK_POP. */
898 if (old_kind == DK_UNSPECIFIED)
899 {
900 old_kind = !context->option_enabled (option_index,
901 context->lang_mask,
902 context->option_state)
903 ? DK_IGNORED : (context->warning_as_error_requested
904 ? DK_ERROR : DK_WARNING);
905 context->classify_diagnostic[option_index] = old_kind;
906 }
907
908 for (i = context->n_classification_history - 1; i >= 0; i --)
909 if (context->classification_history[i].option == option_index)
910 {
911 old_kind = context->classification_history[i].kind;
912 break;
913 }
914
915 i = context->n_classification_history;
916 context->classification_history =
917 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
918 * sizeof (diagnostic_classification_change_t));
919 context->classification_history[i].location = where;
920 context->classification_history[i].option = option_index;
921 context->classification_history[i].kind = new_kind;
922 context->n_classification_history ++;
923 }
924 else
925 context->classify_diagnostic[option_index] = new_kind;
926
927 return old_kind;
928 }
929
930 /* Save all diagnostic classifications in a stack. */
931 void
932 diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
933 {
934 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
935 context->push_list[context->n_push ++] = context->n_classification_history;
936 }
937
938 /* Restore the topmost classification set off the stack. If the stack
939 is empty, revert to the state based on command line parameters. */
940 void
941 diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
942 {
943 int jump_to;
944 int i;
945
946 if (context->n_push)
947 jump_to = context->push_list [-- context->n_push];
948 else
949 jump_to = 0;
950
951 i = context->n_classification_history;
952 context->classification_history =
953 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
954 * sizeof (diagnostic_classification_change_t));
955 context->classification_history[i].location = where;
956 context->classification_history[i].option = jump_to;
957 context->classification_history[i].kind = DK_POP;
958 context->n_classification_history ++;
959 }
960
961 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
962 escaping rules for -fdiagnostics-parseable-fixits. */
963
964 static void
965 print_escaped_string (pretty_printer *pp, const char *text)
966 {
967 gcc_assert (pp);
968 gcc_assert (text);
969
970 pp_character (pp, '"');
971 for (const char *ch = text; *ch; ch++)
972 {
973 switch (*ch)
974 {
975 case '\\':
976 /* Escape backslash as two backslashes. */
977 pp_string (pp, "\\\\");
978 break;
979 case '\t':
980 /* Escape tab as "\t". */
981 pp_string (pp, "\\t");
982 break;
983 case '\n':
984 /* Escape newline as "\n". */
985 pp_string (pp, "\\n");
986 break;
987 case '"':
988 /* Escape doublequotes as \". */
989 pp_string (pp, "\\\"");
990 break;
991 default:
992 if (ISPRINT (*ch))
993 pp_character (pp, *ch);
994 else
995 /* Use octal for non-printable chars. */
996 {
997 unsigned char c = (*ch & 0xff);
998 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
999 }
1000 break;
1001 }
1002 }
1003 pp_character (pp, '"');
1004 }
1005
1006 /* Implementation of -fdiagnostics-parseable-fixits and
1007 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1008 Print a machine-parseable version of all fixits in RICHLOC to PP,
1009 using COLUMN_UNIT to express columns.
1010 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1011
1012 static void
1013 print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1014 enum diagnostics_column_unit column_unit,
1015 int tabstop)
1016 {
1017 gcc_assert (pp);
1018 gcc_assert (richloc);
1019
1020 char *saved_prefix = pp_take_prefix (pp);
1021 pp_set_prefix (pp, NULL);
1022
1023 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1024 {
1025 const fixit_hint *hint = richloc->get_fixit_hint (i);
1026 location_t start_loc = hint->get_start_loc ();
1027 expanded_location start_exploc = expand_location (start_loc);
1028 pp_string (pp, "fix-it:");
1029 print_escaped_string (pp, start_exploc.file);
1030 /* For compatibility with clang, print as a half-open range. */
1031 location_t next_loc = hint->get_next_loc ();
1032 expanded_location next_exploc = expand_location (next_loc);
1033 int start_col
1034 = convert_column_unit (column_unit, tabstop, start_exploc);
1035 int next_col
1036 = convert_column_unit (column_unit, tabstop, next_exploc);
1037 pp_printf (pp, ":{%i:%i-%i:%i}:",
1038 start_exploc.line, start_col,
1039 next_exploc.line, next_col);
1040 print_escaped_string (pp, hint->get_string ());
1041 pp_newline (pp);
1042 }
1043
1044 pp_set_prefix (pp, saved_prefix);
1045 }
1046
1047 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1048
1049 static void
1050 get_any_inlining_info (diagnostic_context *context,
1051 diagnostic_info *diagnostic)
1052 {
1053 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1054
1055 if (context->set_locations_cb)
1056 /* Retrieve the locations into which the expression about to be
1057 diagnosed has been inlined, including those of all the callers
1058 all the way down the inlining stack. */
1059 context->set_locations_cb (context, diagnostic);
1060 else
1061 {
1062 /* When there's no callback use just the one location provided
1063 by the caller of the diagnostic function. */
1064 location_t loc = diagnostic_location (diagnostic);
1065 ilocs.safe_push (loc);
1066 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1067 }
1068 }
1069
1070 /* Update the kind of DIAGNOSTIC based on its location(s), including
1071 any of those in its inlining stack, relative to any
1072 #pragma GCC diagnostic
1073 directives recorded within CONTEXT.
1074
1075 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1076 otherwise. */
1077
1078 static diagnostic_t
1079 update_effective_level_from_pragmas (diagnostic_context *context,
1080 diagnostic_info *diagnostic)
1081 {
1082 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
1083 {
1084 /* Ignore the diagnostic if all the inlined locations are
1085 in system headers and -Wno-system-headers is in effect. */
1086 diagnostic->kind = DK_IGNORED;
1087 return DK_IGNORED;
1088 }
1089
1090 if (context->n_classification_history <= 0)
1091 return DK_UNSPECIFIED;
1092
1093 /* Iterate over the locations, checking the diagnostic disposition
1094 for the diagnostic at each. If it's explicitly set as opposed
1095 to unspecified, update the disposition for this instance of
1096 the diagnostic and return it. */
1097 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1098 {
1099 /* FIXME: Stupid search. Optimize later. */
1100 for (int i = context->n_classification_history - 1; i >= 0; i --)
1101 {
1102 const diagnostic_classification_change_t &hist
1103 = context->classification_history[i];
1104
1105 location_t pragloc = hist.location;
1106 if (!linemap_location_before_p (line_table, pragloc, loc))
1107 continue;
1108
1109 if (hist.kind == (int) DK_POP)
1110 {
1111 /* Move on to the next region. */
1112 i = hist.option;
1113 continue;
1114 }
1115
1116 int option = hist.option;
1117 /* The option 0 is for all the diagnostics. */
1118 if (option == 0 || option == diagnostic->option_index)
1119 {
1120 diagnostic_t kind = hist.kind;
1121 if (kind != DK_UNSPECIFIED)
1122 diagnostic->kind = kind;
1123 return kind;
1124 }
1125 }
1126 }
1127
1128 return DK_UNSPECIFIED;
1129 }
1130
1131 /* Generate a URL string describing CWE. The caller is responsible for
1132 freeing the string. */
1133
1134 static char *
1135 get_cwe_url (int cwe)
1136 {
1137 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1138 }
1139
1140 /* If DIAGNOSTIC has a CWE identifier, print it.
1141
1142 For example, if the diagnostic metadata associates it with CWE-119,
1143 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1144 description of the security issue. */
1145
1146 static void
1147 print_any_cwe (diagnostic_context *context,
1148 const diagnostic_info *diagnostic)
1149 {
1150 if (diagnostic->metadata == NULL)
1151 return;
1152
1153 int cwe = diagnostic->metadata->get_cwe ();
1154 if (cwe)
1155 {
1156 pretty_printer *pp = context->printer;
1157 char *saved_prefix = pp_take_prefix (context->printer);
1158 pp_string (pp, " [");
1159 pp_string (pp, colorize_start (pp_show_color (pp),
1160 diagnostic_kind_color[diagnostic->kind]));
1161 if (pp->url_format != URL_FORMAT_NONE)
1162 {
1163 char *cwe_url = get_cwe_url (cwe);
1164 pp_begin_url (pp, cwe_url);
1165 free (cwe_url);
1166 }
1167 pp_printf (pp, "CWE-%i", cwe);
1168 pp_set_prefix (context->printer, saved_prefix);
1169 if (pp->url_format != URL_FORMAT_NONE)
1170 pp_end_url (pp);
1171 pp_string (pp, colorize_stop (pp_show_color (pp)));
1172 pp_character (pp, ']');
1173 }
1174 }
1175
1176 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1177 printer, e.g. " [-Werror=uninitialized]".
1178 Subroutine of diagnostic_report_diagnostic. */
1179
1180 static void
1181 print_option_information (diagnostic_context *context,
1182 const diagnostic_info *diagnostic,
1183 diagnostic_t orig_diag_kind)
1184 {
1185 char *option_text;
1186
1187 option_text = context->option_name (context, diagnostic->option_index,
1188 orig_diag_kind, diagnostic->kind);
1189
1190 if (option_text)
1191 {
1192 char *option_url = NULL;
1193 if (context->get_option_url
1194 && context->printer->url_format != URL_FORMAT_NONE)
1195 option_url = context->get_option_url (context,
1196 diagnostic->option_index);
1197 pretty_printer *pp = context->printer;
1198 pp_string (pp, " [");
1199 pp_string (pp, colorize_start (pp_show_color (pp),
1200 diagnostic_kind_color[diagnostic->kind]));
1201 if (option_url)
1202 pp_begin_url (pp, option_url);
1203 pp_string (pp, option_text);
1204 if (option_url)
1205 {
1206 pp_end_url (pp);
1207 free (option_url);
1208 }
1209 pp_string (pp, colorize_stop (pp_show_color (pp)));
1210 pp_character (pp, ']');
1211 free (option_text);
1212 }
1213 }
1214
1215 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1216 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1217
1218 static bool
1219 diagnostic_enabled (diagnostic_context *context,
1220 diagnostic_info *diagnostic)
1221 {
1222 /* Update the inlining stack for this diagnostic. */
1223 get_any_inlining_info (context, diagnostic);
1224
1225 /* Diagnostics with no option or -fpermissive are always enabled. */
1226 if (!diagnostic->option_index
1227 || diagnostic->option_index == permissive_error_option (context))
1228 return true;
1229
1230 /* This tests if the user provided the appropriate -Wfoo or
1231 -Wno-foo option. */
1232 if (! context->option_enabled (diagnostic->option_index,
1233 context->lang_mask,
1234 context->option_state))
1235 return false;
1236
1237 /* This tests for #pragma diagnostic changes. */
1238 diagnostic_t diag_class
1239 = update_effective_level_from_pragmas (context, diagnostic);
1240
1241 /* This tests if the user provided the appropriate -Werror=foo
1242 option. */
1243 if (diag_class == DK_UNSPECIFIED
1244 && (context->classify_diagnostic[diagnostic->option_index]
1245 != DK_UNSPECIFIED))
1246 diagnostic->kind
1247 = context->classify_diagnostic[diagnostic->option_index];
1248
1249 /* This allows for future extensions, like temporarily disabling
1250 warnings for ranges of source code. */
1251 if (diagnostic->kind == DK_IGNORED)
1252 return false;
1253
1254 return true;
1255 }
1256
1257 /* Returns whether warning OPT is enabled at LOC. */
1258
1259 bool
1260 warning_enabled_at (location_t loc, int opt)
1261 {
1262 if (!diagnostic_report_warnings_p (global_dc, loc))
1263 return false;
1264
1265 rich_location richloc (line_table, loc);
1266 diagnostic_info diagnostic = {};
1267 diagnostic.option_index = opt;
1268 diagnostic.richloc = &richloc;
1269 diagnostic.message.m_richloc = &richloc;
1270 diagnostic.kind = DK_WARNING;
1271 return diagnostic_enabled (global_dc, &diagnostic);
1272 }
1273
1274 /* Report a diagnostic message (an error or a warning) as specified by
1275 DC. This function is *the* subroutine in terms of which front-ends
1276 should implement their specific diagnostic handling modules. The
1277 front-end independent format specifiers are exactly those described
1278 in the documentation of output_format.
1279 Return true if a diagnostic was printed, false otherwise. */
1280
1281 bool
1282 diagnostic_report_diagnostic (diagnostic_context *context,
1283 diagnostic_info *diagnostic)
1284 {
1285 location_t location = diagnostic_location (diagnostic);
1286 diagnostic_t orig_diag_kind = diagnostic->kind;
1287
1288 /* Give preference to being able to inhibit warnings, before they
1289 get reclassified to something else. */
1290 bool report_warning_p = true;
1291 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1292 {
1293 if (context->dc_inhibit_warnings)
1294 return false;
1295 /* Remember the result of the overall system header warning setting
1296 but proceed to also check the inlining context. */
1297 report_warning_p = diagnostic_report_warnings_p (context, location);
1298 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1299 return false;
1300 }
1301
1302 if (diagnostic->kind == DK_PEDWARN)
1303 {
1304 diagnostic->kind = pedantic_warning_kind (context);
1305 /* We do this to avoid giving the message for -pedantic-errors. */
1306 orig_diag_kind = diagnostic->kind;
1307 }
1308
1309 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1310 return false;
1311
1312 if (context->lock > 0)
1313 {
1314 /* If we're reporting an ICE in the middle of some other error,
1315 try to flush out the previous error, then let this one
1316 through. Don't do this more than once. */
1317 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1318 && context->lock == 1)
1319 pp_newline_and_flush (context->printer);
1320 else
1321 error_recursion (context);
1322 }
1323
1324 /* If the user requested that warnings be treated as errors, so be
1325 it. Note that we do this before the next block so that
1326 individual warnings can be overridden back to warnings with
1327 -Wno-error=*. */
1328 if (context->warning_as_error_requested
1329 && diagnostic->kind == DK_WARNING)
1330 diagnostic->kind = DK_ERROR;
1331
1332 diagnostic->message.x_data = &diagnostic->x_data;
1333
1334 /* Check to see if the diagnostic is enabled at the location and
1335 not disabled by #pragma GCC diagnostic anywhere along the inlining
1336 stack. . */
1337 if (!diagnostic_enabled (context, diagnostic))
1338 return false;
1339
1340 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1341 /* Bail if the warning is not to be reported because all locations
1342 in the inlining stack (if there is one) are in system headers. */
1343 return false;
1344
1345 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
1346 diagnostic_check_max_errors (context);
1347
1348 context->lock++;
1349
1350 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1351 {
1352 /* When not checking, ICEs are converted to fatal errors when an
1353 error has already occurred. This is counteracted by
1354 abort_on_error. */
1355 if (!CHECKING_P
1356 && (diagnostic_kind_count (context, DK_ERROR) > 0
1357 || diagnostic_kind_count (context, DK_SORRY) > 0)
1358 && !context->abort_on_error)
1359 {
1360 expanded_location s
1361 = expand_location (diagnostic_location (diagnostic));
1362 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1363 s.file, s.line);
1364 exit (ICE_EXIT_CODE);
1365 }
1366 if (context->internal_error)
1367 (*context->internal_error) (context,
1368 diagnostic->message.format_spec,
1369 diagnostic->message.args_ptr);
1370 }
1371 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1372 ++diagnostic_kind_count (context, DK_WERROR);
1373 else
1374 ++diagnostic_kind_count (context, diagnostic->kind);
1375
1376 /* Is this the initial diagnostic within the stack of groups? */
1377 if (context->diagnostic_group_emission_count == 0)
1378 {
1379 if (context->begin_group_cb)
1380 context->begin_group_cb (context);
1381 }
1382 context->diagnostic_group_emission_count++;
1383
1384 pp_format (context->printer, &diagnostic->message);
1385 (*diagnostic_starter (context)) (context, diagnostic);
1386 pp_output_formatted_text (context->printer);
1387 if (context->show_cwe)
1388 print_any_cwe (context, diagnostic);
1389 if (context->show_option_requested)
1390 print_option_information (context, diagnostic, orig_diag_kind);
1391 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
1392 switch (context->extra_output_kind)
1393 {
1394 default:
1395 break;
1396 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1397 print_parseable_fixits (context->printer, diagnostic->richloc,
1398 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1399 context->tabstop);
1400 pp_flush (context->printer);
1401 break;
1402 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1403 print_parseable_fixits (context->printer, diagnostic->richloc,
1404 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1405 context->tabstop);
1406 pp_flush (context->printer);
1407 break;
1408 }
1409 diagnostic_action_after_output (context, diagnostic->kind);
1410 diagnostic->x_data = NULL;
1411
1412 if (context->edit_context_ptr)
1413 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1414 context->edit_context_ptr->add_fixits (diagnostic->richloc);
1415
1416 context->lock--;
1417
1418 diagnostic_show_any_path (context, diagnostic);
1419
1420 return true;
1421 }
1422
1423 /* Get the number of digits in the decimal representation of VALUE. */
1424
1425 int
1426 num_digits (int value)
1427 {
1428 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1429 using floating point. */
1430 gcc_assert (value >= 0);
1431
1432 if (value == 0)
1433 return 1;
1434
1435 int digits = 0;
1436 while (value > 0)
1437 {
1438 digits++;
1439 value /= 10;
1440 }
1441 return digits;
1442 }
1443
1444 /* Given a partial pathname as input, return another pathname that
1445 shares no directory elements with the pathname of __FILE__. This
1446 is used by fancy_abort() to print `internal compiler error in expr.cc'
1447 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1448
1449 const char *
1450 trim_filename (const char *name)
1451 {
1452 static const char this_file[] = __FILE__;
1453 const char *p = name, *q = this_file;
1454
1455 /* First skip any "../" in each filename. This allows us to give a proper
1456 reference to a file in a subdirectory. */
1457 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
1458 p += 3;
1459
1460 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
1461 q += 3;
1462
1463 /* Now skip any parts the two filenames have in common. */
1464 while (*p == *q && *p != 0 && *q != 0)
1465 p++, q++;
1466
1467 /* Now go backwards until the previous directory separator. */
1468 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
1469 p--;
1470
1471 return p;
1472 }
1473 \f
1474 /* Standard error reporting routines in increasing order of severity.
1475 All of these take arguments like printf. */
1476
1477 /* Text to be emitted verbatim to the error message stream; this
1478 produces no prefix and disables line-wrapping. Use rarely. */
1479 void
1480 verbatim (const char *gmsgid, ...)
1481 {
1482 text_info text;
1483 va_list ap;
1484
1485 va_start (ap, gmsgid);
1486 text.err_no = errno;
1487 text.args_ptr = &ap;
1488 text.format_spec = _(gmsgid);
1489 text.x_data = NULL;
1490 pp_format_verbatim (global_dc->printer, &text);
1491 pp_newline_and_flush (global_dc->printer);
1492 va_end (ap);
1493 }
1494
1495 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1496 void
1497 diagnostic_append_note (diagnostic_context *context,
1498 location_t location,
1499 const char * gmsgid, ...)
1500 {
1501 diagnostic_info diagnostic;
1502 va_list ap;
1503 rich_location richloc (line_table, location);
1504
1505 va_start (ap, gmsgid);
1506 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1507 if (context->inhibit_notes_p)
1508 {
1509 va_end (ap);
1510 return;
1511 }
1512 char *saved_prefix = pp_take_prefix (context->printer);
1513 pp_set_prefix (context->printer,
1514 diagnostic_build_prefix (context, &diagnostic));
1515 pp_format (context->printer, &diagnostic.message);
1516 pp_output_formatted_text (context->printer);
1517 pp_destroy_prefix (context->printer);
1518 pp_set_prefix (context->printer, saved_prefix);
1519 pp_newline (context->printer);
1520 diagnostic_show_locus (context, &richloc, DK_NOTE);
1521 va_end (ap);
1522 }
1523
1524 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1525 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1526 and internal_error_no_backtrace, as documented and defined below. */
1527 static bool
1528 diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1529 int opt, const char *gmsgid,
1530 va_list *ap, diagnostic_t kind)
1531 {
1532 diagnostic_info diagnostic;
1533 if (kind == DK_PERMERROR)
1534 {
1535 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
1536 permissive_error_kind (global_dc));
1537 diagnostic.option_index = permissive_error_option (global_dc);
1538 }
1539 else
1540 {
1541 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
1542 if (kind == DK_WARNING || kind == DK_PEDWARN)
1543 diagnostic.option_index = opt;
1544 }
1545 diagnostic.metadata = metadata;
1546 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1547 }
1548
1549 /* Implement inform_n, warning_n, and error_n, as documented and
1550 defined below. */
1551 static bool
1552 diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1553 int opt, unsigned HOST_WIDE_INT n,
1554 const char *singular_gmsgid,
1555 const char *plural_gmsgid,
1556 va_list *ap, diagnostic_t kind)
1557 {
1558 diagnostic_info diagnostic;
1559 unsigned long gtn;
1560
1561 if (sizeof n <= sizeof gtn)
1562 gtn = n;
1563 else
1564 /* Use the largest number ngettext can handle, otherwise
1565 preserve the six least significant decimal digits for
1566 languages where the plural form depends on them. */
1567 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1568
1569 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1570 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
1571 if (kind == DK_WARNING)
1572 diagnostic.option_index = opt;
1573 diagnostic.metadata = metadata;
1574 return diagnostic_report_diagnostic (global_dc, &diagnostic);
1575 }
1576
1577 /* Wrapper around diagnostic_impl taking a variable argument list. */
1578
1579 bool
1580 emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1581 const char *gmsgid, ...)
1582 {
1583 auto_diagnostic_group d;
1584 va_list ap;
1585 va_start (ap, gmsgid);
1586 rich_location richloc (line_table, location);
1587 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
1588 va_end (ap);
1589 return ret;
1590 }
1591
1592 /* As above, but for rich_location *. */
1593
1594 bool
1595 emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1596 const char *gmsgid, ...)
1597 {
1598 auto_diagnostic_group d;
1599 va_list ap;
1600 va_start (ap, gmsgid);
1601 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
1602 va_end (ap);
1603 return ret;
1604 }
1605
1606 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1607
1608 bool
1609 emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1610 const char *gmsgid, va_list *ap)
1611 {
1612 rich_location richloc (line_table, location);
1613 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1614 }
1615
1616 /* An informative note at LOCATION. Use this for additional details on an error
1617 message. */
1618 void
1619 inform (location_t location, const char *gmsgid, ...)
1620 {
1621 auto_diagnostic_group d;
1622 va_list ap;
1623 va_start (ap, gmsgid);
1624 rich_location richloc (line_table, location);
1625 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1626 va_end (ap);
1627 }
1628
1629 /* Same as "inform" above, but at RICHLOC. */
1630 void
1631 inform (rich_location *richloc, const char *gmsgid, ...)
1632 {
1633 gcc_assert (richloc);
1634
1635 auto_diagnostic_group d;
1636 va_list ap;
1637 va_start (ap, gmsgid);
1638 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
1639 va_end (ap);
1640 }
1641
1642 /* An informative note at LOCATION. Use this for additional details on an
1643 error message. */
1644 void
1645 inform_n (location_t location, unsigned HOST_WIDE_INT n,
1646 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1647 {
1648 va_list ap;
1649 va_start (ap, plural_gmsgid);
1650 auto_diagnostic_group d;
1651 rich_location richloc (line_table, location);
1652 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1653 &ap, DK_NOTE);
1654 va_end (ap);
1655 }
1656
1657 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1658 to the relevant language specification but is likely to be buggy anyway.
1659 Returns true if the warning was printed, false if it was inhibited. */
1660 bool
1661 warning (int opt, const char *gmsgid, ...)
1662 {
1663 auto_diagnostic_group d;
1664 va_list ap;
1665 va_start (ap, gmsgid);
1666 rich_location richloc (line_table, input_location);
1667 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1668 va_end (ap);
1669 return ret;
1670 }
1671
1672 /* A warning at LOCATION. Use this for code which is correct according to the
1673 relevant language specification but is likely to be buggy anyway.
1674 Returns true if the warning was printed, false if it was inhibited. */
1675
1676 bool
1677 warning_at (location_t location, int opt, const char *gmsgid, ...)
1678 {
1679 auto_diagnostic_group d;
1680 va_list ap;
1681 va_start (ap, gmsgid);
1682 rich_location richloc (line_table, location);
1683 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1684 va_end (ap);
1685 return ret;
1686 }
1687
1688 /* Same as "warning at" above, but using RICHLOC. */
1689
1690 bool
1691 warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
1692 {
1693 gcc_assert (richloc);
1694
1695 auto_diagnostic_group d;
1696 va_list ap;
1697 va_start (ap, gmsgid);
1698 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1699 va_end (ap);
1700 return ret;
1701 }
1702
1703 /* Same as "warning at" above, but using METADATA. */
1704
1705 bool
1706 warning_meta (rich_location *richloc,
1707 const diagnostic_metadata &metadata,
1708 int opt, const char *gmsgid, ...)
1709 {
1710 gcc_assert (richloc);
1711
1712 auto_diagnostic_group d;
1713 va_list ap;
1714 va_start (ap, gmsgid);
1715 bool ret
1716 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1717 DK_WARNING);
1718 va_end (ap);
1719 return ret;
1720 }
1721
1722 /* Same as warning_n plural variant below, but using RICHLOC. */
1723
1724 bool
1725 warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
1726 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1727 {
1728 gcc_assert (richloc);
1729
1730 auto_diagnostic_group d;
1731 va_list ap;
1732 va_start (ap, plural_gmsgid);
1733 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
1734 singular_gmsgid, plural_gmsgid,
1735 &ap, DK_WARNING);
1736 va_end (ap);
1737 return ret;
1738 }
1739
1740 /* A warning at LOCATION. Use this for code which is correct according to the
1741 relevant language specification but is likely to be buggy anyway.
1742 Returns true if the warning was printed, false if it was inhibited. */
1743
1744 bool
1745 warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1746 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1747 {
1748 auto_diagnostic_group d;
1749 va_list ap;
1750 va_start (ap, plural_gmsgid);
1751 rich_location richloc (line_table, location);
1752 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
1753 singular_gmsgid, plural_gmsgid,
1754 &ap, DK_WARNING);
1755 va_end (ap);
1756 return ret;
1757 }
1758
1759 /* A "pedantic" warning at LOCATION: issues a warning unless
1760 -pedantic-errors was given on the command line, in which case it
1761 issues an error. Use this for diagnostics required by the relevant
1762 language standard, if you have chosen not to make them errors.
1763
1764 Note that these diagnostics are issued independent of the setting
1765 of the -Wpedantic command-line switch. To get a warning enabled
1766 only with that switch, use either "if (pedantic) pedwarn
1767 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1768 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1769
1770 Returns true if the warning was printed, false if it was inhibited. */
1771
1772 bool
1773 pedwarn (location_t location, int opt, const char *gmsgid, ...)
1774 {
1775 auto_diagnostic_group d;
1776 va_list ap;
1777 va_start (ap, gmsgid);
1778 rich_location richloc (line_table, location);
1779 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1780 va_end (ap);
1781 return ret;
1782 }
1783
1784 /* Same as pedwarn above, but using RICHLOC. */
1785
1786 bool
1787 pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1788 {
1789 gcc_assert (richloc);
1790
1791 auto_diagnostic_group d;
1792 va_list ap;
1793 va_start (ap, gmsgid);
1794 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1795 va_end (ap);
1796 return ret;
1797 }
1798
1799 /* A "permissive" error at LOCATION: issues an error unless
1800 -fpermissive was given on the command line, in which case it issues
1801 a warning. Use this for things that really should be errors but we
1802 want to support legacy code.
1803
1804 Returns true if the warning was printed, false if it was inhibited. */
1805
1806 bool
1807 permerror (location_t location, const char *gmsgid, ...)
1808 {
1809 auto_diagnostic_group d;
1810 va_list ap;
1811 va_start (ap, gmsgid);
1812 rich_location richloc (line_table, location);
1813 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1814 va_end (ap);
1815 return ret;
1816 }
1817
1818 /* Same as "permerror" above, but at RICHLOC. */
1819
1820 bool
1821 permerror (rich_location *richloc, const char *gmsgid, ...)
1822 {
1823 gcc_assert (richloc);
1824
1825 auto_diagnostic_group d;
1826 va_list ap;
1827 va_start (ap, gmsgid);
1828 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
1829 va_end (ap);
1830 return ret;
1831 }
1832
1833 /* A hard error: the code is definitely ill-formed, and an object file
1834 will not be produced. */
1835 void
1836 error (const char *gmsgid, ...)
1837 {
1838 auto_diagnostic_group d;
1839 va_list ap;
1840 va_start (ap, gmsgid);
1841 rich_location richloc (line_table, input_location);
1842 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1843 va_end (ap);
1844 }
1845
1846 /* A hard error: the code is definitely ill-formed, and an object file
1847 will not be produced. */
1848 void
1849 error_n (location_t location, unsigned HOST_WIDE_INT n,
1850 const char *singular_gmsgid, const char *plural_gmsgid, ...)
1851 {
1852 auto_diagnostic_group d;
1853 va_list ap;
1854 va_start (ap, plural_gmsgid);
1855 rich_location richloc (line_table, location);
1856 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
1857 &ap, DK_ERROR);
1858 va_end (ap);
1859 }
1860
1861 /* Same as above, but use location LOC instead of input_location. */
1862 void
1863 error_at (location_t loc, const char *gmsgid, ...)
1864 {
1865 auto_diagnostic_group d;
1866 va_list ap;
1867 va_start (ap, gmsgid);
1868 rich_location richloc (line_table, loc);
1869 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1870 va_end (ap);
1871 }
1872
1873 /* Same as above, but use RICH_LOC. */
1874
1875 void
1876 error_at (rich_location *richloc, const char *gmsgid, ...)
1877 {
1878 gcc_assert (richloc);
1879
1880 auto_diagnostic_group d;
1881 va_list ap;
1882 va_start (ap, gmsgid);
1883 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
1884 va_end (ap);
1885 }
1886
1887 /* "Sorry, not implemented." Use for a language feature which is
1888 required by the relevant specification but not implemented by GCC.
1889 An object file will not be produced. */
1890 void
1891 sorry (const char *gmsgid, ...)
1892 {
1893 auto_diagnostic_group d;
1894 va_list ap;
1895 va_start (ap, gmsgid);
1896 rich_location richloc (line_table, input_location);
1897 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1898 va_end (ap);
1899 }
1900
1901 /* Same as above, but use location LOC instead of input_location. */
1902 void
1903 sorry_at (location_t loc, const char *gmsgid, ...)
1904 {
1905 auto_diagnostic_group d;
1906 va_list ap;
1907 va_start (ap, gmsgid);
1908 rich_location richloc (line_table, loc);
1909 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
1910 va_end (ap);
1911 }
1912
1913 /* Return true if an error or a "sorry" has been seen. Various
1914 processing is disabled after errors. */
1915 bool
1916 seen_error (void)
1917 {
1918 return errorcount || sorrycount;
1919 }
1920
1921 /* An error which is severe enough that we make no attempt to
1922 continue. Do not use this for internal consistency checks; that's
1923 internal_error. Use of this function should be rare. */
1924 void
1925 fatal_error (location_t loc, const char *gmsgid, ...)
1926 {
1927 auto_diagnostic_group d;
1928 va_list ap;
1929 va_start (ap, gmsgid);
1930 rich_location richloc (line_table, loc);
1931 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
1932 va_end (ap);
1933
1934 gcc_unreachable ();
1935 }
1936
1937 /* An internal consistency check has failed. We make no attempt to
1938 continue. */
1939 void
1940 internal_error (const char *gmsgid, ...)
1941 {
1942 auto_diagnostic_group d;
1943 va_list ap;
1944 va_start (ap, gmsgid);
1945 rich_location richloc (line_table, input_location);
1946 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
1947 va_end (ap);
1948
1949 gcc_unreachable ();
1950 }
1951
1952 /* Like internal_error, but no backtrace will be printed. Used when
1953 the internal error does not happen at the current location, but happened
1954 somewhere else. */
1955 void
1956 internal_error_no_backtrace (const char *gmsgid, ...)
1957 {
1958 auto_diagnostic_group d;
1959 va_list ap;
1960 va_start (ap, gmsgid);
1961 rich_location richloc (line_table, input_location);
1962 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
1963 va_end (ap);
1964
1965 gcc_unreachable ();
1966 }
1967 \f
1968 /* Special case error functions. Most are implemented in terms of the
1969 above, or should be. */
1970
1971 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1972 runs its second argument through gettext. */
1973 void
1974 fnotice (FILE *file, const char *cmsgid, ...)
1975 {
1976 va_list ap;
1977
1978 va_start (ap, cmsgid);
1979 vfprintf (file, _(cmsgid), ap);
1980 va_end (ap);
1981 }
1982
1983 /* Inform the user that an error occurred while trying to report some
1984 other error. This indicates catastrophic internal inconsistencies,
1985 so give up now. But do try to flush out the previous error.
1986 This mustn't use internal_error, that will cause infinite recursion. */
1987
1988 static void
1989 error_recursion (diagnostic_context *context)
1990 {
1991 if (context->lock < 3)
1992 pp_newline_and_flush (context->printer);
1993
1994 fnotice (stderr,
1995 "internal compiler error: error reporting routines re-entered.\n");
1996
1997 /* Call diagnostic_action_after_output to get the "please submit a bug
1998 report" message. */
1999 diagnostic_action_after_output (context, DK_ICE);
2000
2001 /* Do not use gcc_unreachable here; that goes through internal_error
2002 and therefore would cause infinite recursion. */
2003 real_abort ();
2004 }
2005
2006 /* Report an internal compiler error in a friendly manner. This is
2007 the function that gets called upon use of abort() in the source
2008 code generally, thanks to a special macro. */
2009
2010 void
2011 fancy_abort (const char *file, int line, const char *function)
2012 {
2013 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2014 internal_error will crash internally in a way that prevents a
2015 useful message reaching the user.
2016 This can happen with libgccjit in the case of gcc_assert failures
2017 that occur outside of the libgccjit mutex that guards the rest of
2018 gcc's state, including global_dc (when global_dc may not be
2019 initialized yet, or might be in use by another thread).
2020 Handle such cases as gracefully as possible by falling back to a
2021 minimal abort handler that only relies on i18n. */
2022 if (global_dc->printer == NULL)
2023 {
2024 /* Print the error message. */
2025 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2026 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2027 fputc ('\n', stderr);
2028
2029 /* Attempt to print a backtrace. */
2030 struct backtrace_state *state
2031 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2032 int count = 0;
2033 if (state != NULL)
2034 backtrace_full (state, 2, bt_callback, bt_err_callback,
2035 (void *) &count);
2036
2037 /* We can't call warn_if_plugins or emergency_dump_function as these
2038 rely on GCC state that might not be initialized, or might be in
2039 use by another thread. */
2040
2041 /* Abort the process. */
2042 real_abort ();
2043 }
2044
2045 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2046 }
2047
2048 /* class auto_diagnostic_group. */
2049
2050 /* Constructor: "push" this group into global_dc. */
2051
2052 auto_diagnostic_group::auto_diagnostic_group ()
2053 {
2054 global_dc->diagnostic_group_nesting_depth++;
2055 }
2056
2057 /* Destructor: "pop" this group from global_dc. */
2058
2059 auto_diagnostic_group::~auto_diagnostic_group ()
2060 {
2061 if (--global_dc->diagnostic_group_nesting_depth == 0)
2062 {
2063 /* Handle the case where we've popped the final diagnostic group.
2064 If any diagnostics were emitted, give the context a chance
2065 to do something. */
2066 if (global_dc->diagnostic_group_emission_count > 0)
2067 {
2068 if (global_dc->end_group_cb)
2069 global_dc->end_group_cb (global_dc);
2070 }
2071 global_dc->diagnostic_group_emission_count = 0;
2072 }
2073 }
2074
2075 /* Implementation of diagnostic_path::num_events vfunc for
2076 simple_diagnostic_path: simply get the number of events in the vec. */
2077
2078 unsigned
2079 simple_diagnostic_path::num_events () const
2080 {
2081 return m_events.length ();
2082 }
2083
2084 /* Implementation of diagnostic_path::get_event vfunc for
2085 simple_diagnostic_path: simply return the event in the vec. */
2086
2087 const diagnostic_event &
2088 simple_diagnostic_path::get_event (int idx) const
2089 {
2090 return *m_events[idx];
2091 }
2092
2093 /* Add an event to this path at LOC within function FNDECL at
2094 stack depth DEPTH.
2095
2096 Use m_context's printer to format FMT, as the text of the new
2097 event.
2098
2099 Return the id of the new event. */
2100
2101 diagnostic_event_id_t
2102 simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2103 const char *fmt, ...)
2104 {
2105 pretty_printer *pp = m_event_pp;
2106 pp_clear_output_area (pp);
2107
2108 text_info ti;
2109 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2110
2111 va_list ap;
2112
2113 va_start (ap, fmt);
2114
2115 ti.format_spec = _(fmt);
2116 ti.args_ptr = &ap;
2117 ti.err_no = 0;
2118 ti.x_data = NULL;
2119 ti.m_richloc = &rich_loc;
2120
2121 pp_format (pp, &ti);
2122 pp_output_formatted_text (pp);
2123
2124 va_end (ap);
2125
2126 simple_diagnostic_event *new_event
2127 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2128 m_events.safe_push (new_event);
2129
2130 pp_clear_output_area (pp);
2131
2132 return diagnostic_event_id_t (m_events.length () - 1);
2133 }
2134
2135 /* struct simple_diagnostic_event. */
2136
2137 /* simple_diagnostic_event's ctor. */
2138
2139 simple_diagnostic_event::simple_diagnostic_event (location_t loc,
2140 tree fndecl,
2141 int depth,
2142 const char *desc)
2143 : m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc))
2144 {
2145 }
2146
2147 /* simple_diagnostic_event's dtor. */
2148
2149 simple_diagnostic_event::~simple_diagnostic_event ()
2150 {
2151 free (m_desc);
2152 }
2153
2154 /* Print PATH by emitting a dummy "note" associated with it. */
2155
2156 DEBUG_FUNCTION
2157 void debug (diagnostic_path *path)
2158 {
2159 rich_location richloc (line_table, UNKNOWN_LOCATION);
2160 richloc.set_path (path);
2161 inform (&richloc, "debug path");
2162 }
2163
2164 /* Really call the system 'abort'. This has to go right at the end of
2165 this file, so that there are no functions after it that call abort
2166 and get the system abort instead of our macro. */
2167 #undef abort
2168 static void
2169 real_abort (void)
2170 {
2171 abort ();
2172 }
2173
2174 #if CHECKING_P
2175
2176 namespace selftest {
2177
2178 /* Helper function for test_print_escaped_string. */
2179
2180 static void
2181 assert_print_escaped_string (const location &loc, const char *expected_output,
2182 const char *input)
2183 {
2184 pretty_printer pp;
2185 print_escaped_string (&pp, input);
2186 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2187 }
2188
2189 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2190 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2191
2192 /* Tests of print_escaped_string. */
2193
2194 static void
2195 test_print_escaped_string ()
2196 {
2197 /* Empty string. */
2198 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2199
2200 /* Non-empty string. */
2201 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2202
2203 /* Various things that need to be escaped: */
2204 /* Backslash. */
2205 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2206 "before\\after");
2207 /* Tab. */
2208 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2209 "before\tafter");
2210 /* Newline. */
2211 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2212 "before\nafter");
2213 /* Double quote. */
2214 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2215 "before\"after");
2216
2217 /* Non-printable characters: BEL: '\a': 0x07 */
2218 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2219 "before\aafter");
2220 /* Non-printable characters: vertical tab: '\v': 0x0b */
2221 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2222 "before\vafter");
2223 }
2224
2225 /* Tests of print_parseable_fixits. */
2226
2227 /* Verify that print_parseable_fixits emits the empty string if there
2228 are no fixits. */
2229
2230 static void
2231 test_print_parseable_fixits_none ()
2232 {
2233 pretty_printer pp;
2234 rich_location richloc (line_table, UNKNOWN_LOCATION);
2235
2236 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2237 ASSERT_STREQ ("", pp_formatted_text (&pp));
2238 }
2239
2240 /* Verify that print_parseable_fixits does the right thing if there
2241 is an insertion fixit hint. */
2242
2243 static void
2244 test_print_parseable_fixits_insert ()
2245 {
2246 pretty_printer pp;
2247 rich_location richloc (line_table, UNKNOWN_LOCATION);
2248
2249 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2250 linemap_line_start (line_table, 5, 100);
2251 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2252 location_t where = linemap_position_for_column (line_table, 10);
2253 richloc.add_fixit_insert_before (where, "added content");
2254
2255 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2256 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2257 pp_formatted_text (&pp));
2258 }
2259
2260 /* Verify that print_parseable_fixits does the right thing if there
2261 is an removal fixit hint. */
2262
2263 static void
2264 test_print_parseable_fixits_remove ()
2265 {
2266 pretty_printer pp;
2267 rich_location richloc (line_table, UNKNOWN_LOCATION);
2268
2269 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2270 linemap_line_start (line_table, 5, 100);
2271 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2272 source_range where;
2273 where.m_start = linemap_position_for_column (line_table, 10);
2274 where.m_finish = linemap_position_for_column (line_table, 20);
2275 richloc.add_fixit_remove (where);
2276
2277 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2278 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2279 pp_formatted_text (&pp));
2280 }
2281
2282 /* Verify that print_parseable_fixits does the right thing if there
2283 is an replacement fixit hint. */
2284
2285 static void
2286 test_print_parseable_fixits_replace ()
2287 {
2288 pretty_printer pp;
2289 rich_location richloc (line_table, UNKNOWN_LOCATION);
2290
2291 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2292 linemap_line_start (line_table, 5, 100);
2293 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2294 source_range where;
2295 where.m_start = linemap_position_for_column (line_table, 10);
2296 where.m_finish = linemap_position_for_column (line_table, 20);
2297 richloc.add_fixit_replace (where, "replacement");
2298
2299 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
2300 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2301 pp_formatted_text (&pp));
2302 }
2303
2304 /* Verify that print_parseable_fixits correctly handles
2305 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2306
2307 static void
2308 test_print_parseable_fixits_bytes_vs_display_columns ()
2309 {
2310 line_table_test ltt;
2311 rich_location richloc (line_table, UNKNOWN_LOCATION);
2312
2313 /* 1-based byte offsets: 12345677778888999900001234567. */
2314 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2315 /* 1-based display cols: 123456[......7-8.....]9012345. */
2316 const int tabstop = 8;
2317
2318 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2319 const char *const fname = tmp.get_filename ();
2320
2321 linemap_add (line_table, LC_ENTER, false, fname, 0);
2322 linemap_line_start (line_table, 1, 100);
2323 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2324 source_range where;
2325 where.m_start = linemap_position_for_column (line_table, 12);
2326 where.m_finish = linemap_position_for_column (line_table, 17);
2327 richloc.add_fixit_replace (where, "color");
2328
2329 /* Escape fname. */
2330 pretty_printer tmp_pp;
2331 print_escaped_string (&tmp_pp, fname);
2332 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2333
2334 const int buf_len = strlen (escaped_fname) + 100;
2335 char *const expected = XNEWVEC (char, buf_len);
2336
2337 {
2338 pretty_printer pp;
2339 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2340 tabstop);
2341 snprintf (expected, buf_len,
2342 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
2343 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2344 }
2345 {
2346 pretty_printer pp;
2347 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2348 tabstop);
2349 snprintf (expected, buf_len,
2350 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
2351 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2352 }
2353
2354 XDELETEVEC (expected);
2355 free (escaped_fname);
2356 }
2357
2358 /* Verify that
2359 diagnostic_get_location_text (..., SHOW_COLUMN)
2360 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2361 colorization disabled. */
2362
2363 static void
2364 assert_location_text (const char *expected_loc_text,
2365 const char *filename, int line, int column,
2366 bool show_column,
2367 int origin = 1,
2368 enum diagnostics_column_unit column_unit
2369 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
2370 {
2371 test_diagnostic_context dc;
2372 dc.show_column = show_column;
2373 dc.column_unit = column_unit;
2374 dc.column_origin = origin;
2375
2376 expanded_location xloc;
2377 xloc.file = filename;
2378 xloc.line = line;
2379 xloc.column = column;
2380 xloc.data = NULL;
2381 xloc.sysp = false;
2382
2383 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2384 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2385 free (actual_loc_text);
2386 }
2387
2388 /* Verify that diagnostic_get_location_text works as expected. */
2389
2390 static void
2391 test_diagnostic_get_location_text ()
2392 {
2393 const char *old_progname = progname;
2394 progname = "PROGNAME";
2395 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
2396 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2397 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2398 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2399 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2400 for (int origin = 0; origin != 2; ++origin)
2401 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
2402 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2403 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2404 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2405
2406 maybe_line_and_column (INT_MAX, INT_MAX);
2407 maybe_line_and_column (INT_MIN, INT_MIN);
2408
2409 {
2410 /* In order to test display columns vs byte columns, we need to create a
2411 file for location_get_source_line() to read. */
2412
2413 const char *const content = "smile \xf0\x9f\x98\x82\n";
2414 const int line_bytes = strlen (content) - 1;
2415 const int def_tabstop = 8;
2416 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2417 const int display_width = cpp_display_width (content, line_bytes, policy);
2418 ASSERT_EQ (line_bytes - 2, display_width);
2419 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2420 const char *const fname = tmp.get_filename ();
2421 const int buf_len = strlen (fname) + 16;
2422 char *const expected = XNEWVEC (char, buf_len);
2423
2424 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2425 assert_location_text (expected, fname, 1, line_bytes, true,
2426 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2427
2428 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2429 assert_location_text (expected, fname, 1, line_bytes, true,
2430 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2431
2432 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2433 assert_location_text (expected, fname, 1, line_bytes, true,
2434 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2435
2436 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2437 assert_location_text (expected, fname, 1, line_bytes, true,
2438 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2439
2440 XDELETEVEC (expected);
2441 }
2442
2443
2444 progname = old_progname;
2445 }
2446
2447 /* Selftest for num_digits. */
2448
2449 static void
2450 test_num_digits ()
2451 {
2452 ASSERT_EQ (1, num_digits (0));
2453 ASSERT_EQ (1, num_digits (9));
2454 ASSERT_EQ (2, num_digits (10));
2455 ASSERT_EQ (2, num_digits (99));
2456 ASSERT_EQ (3, num_digits (100));
2457 ASSERT_EQ (3, num_digits (999));
2458 ASSERT_EQ (4, num_digits (1000));
2459 ASSERT_EQ (4, num_digits (9999));
2460 ASSERT_EQ (5, num_digits (10000));
2461 ASSERT_EQ (5, num_digits (99999));
2462 ASSERT_EQ (6, num_digits (100000));
2463 ASSERT_EQ (6, num_digits (999999));
2464 ASSERT_EQ (7, num_digits (1000000));
2465 ASSERT_EQ (7, num_digits (9999999));
2466 ASSERT_EQ (8, num_digits (10000000));
2467 ASSERT_EQ (8, num_digits (99999999));
2468 }
2469
2470 /* Run all of the selftests within this file. */
2471
2472 void
2473 c_diagnostic_cc_tests ()
2474 {
2475 test_print_escaped_string ();
2476 test_print_parseable_fixits_none ();
2477 test_print_parseable_fixits_insert ();
2478 test_print_parseable_fixits_remove ();
2479 test_print_parseable_fixits_replace ();
2480 test_print_parseable_fixits_bytes_vs_display_columns ();
2481 test_diagnostic_get_location_text ();
2482 test_num_digits ();
2483
2484 }
2485
2486 } // namespace selftest
2487
2488 #endif /* #if CHECKING_P */
2489
2490 #if __GNUC__ >= 10
2491 # pragma GCC diagnostic pop
2492 #endif