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