]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/diagnostic.cc
check undefine_p for one more vr
[thirdparty/gcc.git] / gcc / diagnostic.cc
CommitLineData
47b69537 1/* Language-independent diagnostic subroutines for the GNU Compiler Collection
aeee4812 2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
406a65d0 3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
6ed551b4 4
1322177d 5This file is part of GCC.
6ed551b4 6
1322177d
LB
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9dcd6f09 9Software Foundation; either version 3, or (at your option) any later
1322177d 10version.
6ed551b4 11
1322177d
LB
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
6ed551b4
GDR
16
17You should have received a copy of the GNU General Public License
9dcd6f09
NC
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
6ed551b4
GDR
20
21
4eb00163 22/* This file implements the language independent aspect of diagnostic
6ed551b4
GDR
23 message module. */
24
25#include "config.h"
b2e075a5 26#define INCLUDE_VECTOR
6ed551b4 27#include "system.h"
4977bab6 28#include "coretypes.h"
a757585a 29#include "version.h"
d83697f4 30#include "demangle.h"
6ed551b4 31#include "intl.h"
d83697f4 32#include "backtrace.h"
345ed1fe 33#include "diagnostic.h"
4b84d650 34#include "diagnostic-color.h"
d2608235 35#include "diagnostic-url.h"
6d4a35ca 36#include "diagnostic-metadata.h"
4bc1899b 37#include "diagnostic-path.h"
6cf276dd 38#include "diagnostic-client-data-hooks.h"
4f01ae37
DM
39#include "diagnostic-text-art.h"
40#include "diagnostic-diagram.h"
717ebe91 41#include "edit-context.h"
a93eac6a 42#include "selftest.h"
ace72598 43#include "selftest-diagnostic.h"
fa5baeed 44#include "opts.h"
004bb936 45#include "cpplib.h"
4f01ae37 46#include "text-art/theme.h"
6ed551b4 47
c9db45aa
TB
48#ifdef HAVE_TERMIOS_H
49# include <termios.h>
50#endif
51
52#ifdef GWINSZ_IN_SYS_IOCTL
53# include <sys/ioctl.h>
54#endif
55
0ecf545c
MS
56/* Disable warnings about quoting issues in the pp_xxx calls below
57 that (intentionally) don't follow GCC diagnostic conventions. */
58#if __GNUC__ >= 10
59# pragma GCC diagnostic push
60# pragma GCC diagnostic ignored "-Wformat-diag"
61#endif
62
243fbddd
JM
63#define pedantic_warning_kind(DC) \
64 ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
65#define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
5f0f4a3b 66#define permissive_error_option(DC) ((DC)->opt_permissive)
c707a408 67
30f7a378 68/* Prototypes. */
6d4a35ca
DM
69static bool diagnostic_impl (rich_location *, const diagnostic_metadata *,
70 int, const char *,
71 va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(4,0);
72static bool diagnostic_n_impl (rich_location *, const diagnostic_metadata *,
73 int, unsigned HOST_WIDE_INT,
1c89478a 74 const char *, const char *, va_list *,
6d4a35ca 75 diagnostic_t) ATTRIBUTE_GCC_DIAG(6,0);
a5fb7ad2 76
79a490a9 77static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
79a490a9 78static void real_abort (void) ATTRIBUTE_NORETURN;
fbfc1192 79
1da2ed5f
JM
80/* Name of program invoked, sans directories. */
81
82const char *progname;
83
f68fc4db
GDR
84/* A diagnostic_context surrogate for stderr. */
85static diagnostic_context global_diagnostic_context;
86diagnostic_context *global_dc = &global_diagnostic_context;
6ed551b4 87\f
59650e48
ZW
88/* Return a malloc'd string containing MSG formatted a la printf. The
89 caller is responsible for freeing the memory. */
8e54f6d3 90char *
e34d07f2 91build_message_string (const char *msg, ...)
b903d81e 92{
36244024 93 char *str;
e34d07f2 94 va_list ap;
b903d81e 95
e34d07f2 96 va_start (ap, msg);
582f770b 97 str = xvasprintf (msg, ap);
e34d07f2 98 va_end (ap);
b903d81e
GDR
99
100 return str;
101}
102
95bd1dd7 103/* Same as diagnostic_build_prefix, but only the source FILE is given. */
24805e80 104char *
e78e8a0b 105file_name_as_prefix (diagnostic_context *context, const char *f)
24805e80 106{
e78e8a0b
JJ
107 const char *locus_cs
108 = colorize_start (pp_show_color (context->printer), "locus");
109 const char *locus_ce = colorize_stop (pp_show_color (context->printer));
110 return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
24805e80
GDR
111}
112
47b69537 113
6ed551b4 114\f
9fec0042 115/* Return the value of the getenv("COLUMNS") as an integer. If the
c9db45aa
TB
116 value is not set to a positive integer, use ioctl to get the
117 terminal width. If it fails, return INT_MAX. */
118int
119get_terminal_width (void)
9fec0042
MLI
120{
121 const char * s = getenv ("COLUMNS");
122 if (s != NULL) {
123 int n = atoi (s);
124 if (n > 0)
125 return n;
126 }
c9db45aa
TB
127
128#ifdef TIOCGWINSZ
129 struct winsize w;
130 w.ws_col = 0;
131 if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
132 return w.ws_col;
133#endif
134
9fec0042
MLI
135 return INT_MAX;
136}
137
138/* Set caret_max_width to value. */
139void
140diagnostic_set_caret_max_width (diagnostic_context *context, int value)
141{
142 /* One minus to account for the leading empty space. */
143 value = value ? value - 1
025311c4 144 : (isatty (fileno (pp_buffer (context->printer)->stream))
c9db45aa 145 ? get_terminal_width () - 1: INT_MAX);
9fec0042
MLI
146
147 if (value <= 0)
148 value = INT_MAX;
149
150 context->caret_max_width = value;
151}
152
478dd60d
DM
153/* Default implementation of final_cb. */
154
155static void
156default_diagnostic_final_cb (diagnostic_context *context)
157{
158 /* Some of the errors may actually have been warnings. */
159 if (diagnostic_kind_count (context, DK_WERROR))
160 {
161 /* -Werror was given. */
162 if (context->warning_as_error_requested)
163 pp_verbatim (context->printer,
164 _("%s: all warnings being treated as errors"),
165 progname);
166 /* At least one -Werror= was given. */
167 else
168 pp_verbatim (context->printer,
169 _("%s: some warnings being treated as errors"),
170 progname);
171 pp_newline_and_flush (context->printer);
172 }
173}
174
47b69537
GDR
175/* Initialize the diagnostic message outputting machinery. */
176void
5f0f4a3b 177diagnostic_initialize (diagnostic_context *context, int n_opts)
47b69537 178{
5f0f4a3b
JM
179 int i;
180
b6fe0bb8
GDR
181 /* Allocate a basic pretty-printer. Clients will replace this a
182 much more elaborated pretty-printer if they wish. */
5ed6ace5 183 context->printer = XNEW (pretty_printer);
da6ca2b5 184 new (context->printer) pretty_printer ();
47b69537 185
b6fe0bb8 186 memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
7783b402 187 context->warning_as_error_requested = false;
5f0f4a3b
JM
188 context->n_opts = n_opts;
189 context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
190 for (i = 0; i < n_opts; i++)
191 context->classify_diagnostic[i] = DK_UNSPECIFIED;
9fec0042
MLI
192 context->show_caret = false;
193 diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
b816477a 194 for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
2a2703a2 195 context->caret_chars[i] = '^';
6d4a35ca 196 context->show_cwe = false;
0b14f590 197 context->show_rules = false;
4bc1899b
DM
198 context->path_format = DPF_NONE;
199 context->show_path_depths = false;
2098fe9e 200 context->show_option_requested = false;
b6fe0bb8 201 context->abort_on_error = false;
5f0f4a3b
JM
202 context->show_column = false;
203 context->pedantic_errors = false;
204 context->permissive = false;
205 context->opt_permissive = 0;
206 context->fatal_errors = false;
e3339d0f
JM
207 context->dc_inhibit_warnings = false;
208 context->dc_warn_system_headers = false;
3a789837 209 context->max_errors = 0;
b6fe0bb8 210 context->internal_error = NULL;
47b69537 211 diagnostic_starter (context) = default_diagnostic_starter;
876217ae 212 context->start_span = default_diagnostic_start_span_fn;
47b69537 213 diagnostic_finalizer (context) = default_diagnostic_finalizer;
5f0f4a3b 214 context->option_enabled = NULL;
46625112 215 context->option_state = NULL;
5f0f4a3b 216 context->option_name = NULL;
b4c7ca2e 217 context->get_option_url = NULL;
1b8b126f 218 context->last_location = UNKNOWN_LOCATION;
b6fe0bb8 219 context->last_module = 0;
cf835838 220 context->x_data = NULL;
b6fe0bb8 221 context->lock = 0;
0e94b750 222 context->inhibit_notes_p = false;
cc015f3a 223 context->colorize_source_p = false;
96e6ae57 224 context->show_labels_p = false;
56b61d7f 225 context->show_line_numbers_p = false;
0141ab44 226 context->min_margin_width = 0;
cc015f3a 227 context->show_ruler_p = false;
76ef38e3
ML
228 context->report_bug = false;
229
f1096055
DM
230 if (const char *var = getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
231 {
232 if (!strcmp (var, "fixits-v1"))
233 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1;
234 else if (!strcmp (var, "fixits-v2"))
235 context->extra_output_kind = EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2;
236 /* Silently ignore unrecognized values. */
237 }
004bb936
LH
238 context->column_unit = DIAGNOSTICS_COLUMN_UNIT_DISPLAY;
239 context->column_origin = 1;
240 context->tabstop = 8;
bd5e882c 241 context->escape_format = DIAGNOSTICS_ESCAPE_FORMAT_UNICODE;
717ebe91 242 context->edit_context_ptr = NULL;
097f82ec
DM
243 context->diagnostic_group_nesting_depth = 0;
244 context->diagnostic_group_emission_count = 0;
245 context->begin_group_cb = NULL;
246 context->end_group_cb = NULL;
478dd60d 247 context->final_cb = default_diagnostic_final_cb;
79aaba0a 248 context->ice_handler_cb = NULL;
d3a57993 249 context->includes_seen = NULL;
6cf276dd 250 context->m_client_data_hooks = NULL;
4f01ae37
DM
251 context->m_diagrams.m_theme = NULL;
252 context->m_diagrams.m_emission_cb = NULL;
253 diagnostics_text_art_charset_init (context,
254 DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT);
47b69537
GDR
255}
256
97aa8bb6
MLI
257/* Maybe initialize the color support. We require clients to do this
258 explicitly, since most clients don't want color. When called
259 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
260
261void
262diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
263{
264 /* value == -1 is the default value. */
265 if (value < 0)
266 {
267 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
268 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
269 otherwise default to -fdiagnostics-color=never, for other
270 values default to that
271 -fdiagnostics-color={never,auto,always}. */
272 if (DIAGNOSTICS_COLOR_DEFAULT == -1)
273 {
274 if (!getenv ("GCC_COLORS"))
275 return;
276 value = DIAGNOSTICS_COLOR_AUTO;
277 }
278 else
279 value = DIAGNOSTICS_COLOR_DEFAULT;
280 }
281 pp_show_color (context->printer)
282 = colorize_init ((diagnostic_color_rule_t) value);
283}
284
d2608235
DM
285/* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
286
287void
288diagnostic_urls_init (diagnostic_context *context, int value /*= -1 */)
289{
458c8d64 290 /* value == -1 is the default value. */
d2608235 291 if (value < 0)
458c8d64
BE
292 {
293 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
294 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
295 environment, otherwise default to -fdiagnostics-urls=never,
296 for other values default to that
297 -fdiagnostics-urls={never,auto,always}. */
298 if (DIAGNOSTICS_URLS_DEFAULT == -1)
299 {
300 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
301 return;
302 value = DIAGNOSTICS_URL_AUTO;
303 }
304 else
305 value = DIAGNOSTICS_URLS_DEFAULT;
306 }
d2608235 307
458c8d64
BE
308 context->printer->url_format
309 = determine_url_format ((diagnostic_url_rule_t) value);
d2608235
DM
310}
311
3ac6b5cf
LH
312/* Create the file_cache, if not already created, and tell it how to
313 translate files on input. */
314void diagnostic_initialize_input_context (diagnostic_context *context,
315 diagnostic_input_charset_callback ccb,
316 bool should_skip_bom)
317{
318 if (!context->m_file_cache)
319 context->m_file_cache = new file_cache;
320 context->m_file_cache->initialize_input_context (ccb, should_skip_bom);
321}
322
d0b8780d
MLI
323/* Do any cleaning up required after the last diagnostic is emitted. */
324
325void
326diagnostic_finish (diagnostic_context *context)
327{
478dd60d
DM
328 if (context->final_cb)
329 context->final_cb (context);
7ecc3eb9 330
4f01ae37
DM
331 if (context->m_diagrams.m_theme)
332 {
333 delete context->m_diagrams.m_theme;
334 context->m_diagrams.m_theme = NULL;
335 }
336
7ecc3eb9 337 diagnostic_file_cache_fini ();
3edf64aa
DM
338
339 XDELETEVEC (context->classify_diagnostic);
340 context->classify_diagnostic = NULL;
341
342 /* diagnostic_initialize allocates context->printer using XNEW
343 and placement-new. */
344 context->printer->~pretty_printer ();
345 XDELETE (context->printer);
346 context->printer = NULL;
717ebe91
DM
347
348 if (context->edit_context_ptr)
349 {
350 delete context->edit_context_ptr;
351 context->edit_context_ptr = NULL;
352 }
d3a57993
JM
353
354 if (context->includes_seen)
355 {
356 delete context->includes_seen;
357 context->includes_seen = nullptr;
358 }
6cf276dd
DM
359
360 if (context->m_client_data_hooks)
361 {
362 delete context->m_client_data_hooks;
363 context->m_client_data_hooks = NULL;
364 }
d0b8780d
MLI
365}
366
178b58b5
JM
367/* Initialize DIAGNOSTIC, where the message MSG has already been
368 translated. */
47b69537 369void
178b58b5 370diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
8a645150 371 va_list *args, rich_location *richloc,
178b58b5 372 diagnostic_t kind)
47b69537 373{
8a645150 374 gcc_assert (richloc);
fa6ef813 375 diagnostic->message.err_no = errno;
47b69537 376 diagnostic->message.args_ptr = args;
178b58b5 377 diagnostic->message.format_spec = msg;
8a645150
DM
378 diagnostic->message.m_richloc = richloc;
379 diagnostic->richloc = richloc;
6d4a35ca 380 diagnostic->metadata = NULL;
47b69537 381 diagnostic->kind = kind;
ccf08a6e 382 diagnostic->option_index = 0;
47b69537
GDR
383}
384
178b58b5
JM
385/* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
386 translated. */
387void
388diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
8a645150 389 va_list *args, rich_location *richloc,
178b58b5
JM
390 diagnostic_t kind)
391{
8a645150
DM
392 gcc_assert (richloc);
393 diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
394}
395
396static const char *const diagnostic_kind_color[] = {
397#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
398#include "diagnostic.def"
399#undef DEFINE_DIAGNOSTIC_KIND
400 NULL
401};
402
403/* Get a color name for diagnostics of type KIND
404 Result could be NULL. */
405
406const char *
407diagnostic_get_color_for_kind (diagnostic_t kind)
408{
409 return diagnostic_kind_color[kind];
178b58b5
JM
410}
411
004bb936 412/* Given an expanded_location, convert the column (which is in 1-based bytes)
f1096055
DM
413 to the requested units, without converting the origin.
414 Return -1 if the column is invalid (<= 0). */
415
416static int
417convert_column_unit (enum diagnostics_column_unit column_unit,
418 int tabstop,
419 expanded_location s)
004bb936
LH
420{
421 if (s.column <= 0)
422 return -1;
423
f1096055 424 switch (column_unit)
004bb936 425 {
f1096055
DM
426 default:
427 gcc_unreachable ();
428
004bb936 429 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY:
bd5e882c
DM
430 {
431 cpp_char_column_policy policy (tabstop, cpp_wcwidth);
432 return location_compute_display_column (s, policy);
433 }
004bb936
LH
434
435 case DIAGNOSTICS_COLUMN_UNIT_BYTE:
f1096055 436 return s.column;
004bb936 437 }
f1096055 438}
004bb936 439
f1096055
DM
440/* Given an expanded_location, convert the column (which is in 1-based bytes)
441 to the requested units and origin. Return -1 if the column is
442 invalid (<= 0). */
443int
444diagnostic_converted_column (diagnostic_context *context, expanded_location s)
445{
446 int one_based_col
447 = convert_column_unit (context->column_unit, context->tabstop, s);
448 if (one_based_col <= 0)
449 return -1;
004bb936
LH
450 return one_based_col + (context->column_origin - 1);
451}
452
101e910b 453/* Return a formatted line and column ':%line:%column'. Elided if
004bb936
LH
454 line == 0 or col < 0. (A column of 0 may be valid due to the
455 -fdiagnostics-column-origin option.)
456 The result is a statically allocated buffer. */
101e910b
NS
457
458static const char *
459maybe_line_and_column (int line, int col)
460{
461 static char result[32];
462
463 if (line)
464 {
004bb936
LH
465 size_t l
466 = snprintf (result, sizeof (result),
467 col >= 0 ? ":%d:%d" : ":%d", line, col);
101e910b
NS
468 gcc_checking_assert (l < sizeof (result));
469 }
470 else
471 result[0] = 0;
472 return result;
473}
474
876217ae
DM
475/* Return a malloc'd string describing a location e.g. "foo.c:42:10".
476 The caller is responsible for freeing the memory. */
477
478static char *
479diagnostic_get_location_text (diagnostic_context *context,
480 expanded_location s)
481{
482 pretty_printer *pp = context->printer;
483 const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
484 const char *locus_ce = colorize_stop (pp_show_color (pp));
101e910b 485 const char *file = s.file ? s.file : progname;
004bb936
LH
486 int line = 0;
487 int col = -1;
15d31555 488 if (strcmp (file, special_fname_builtin ()))
004bb936
LH
489 {
490 line = s.line;
491 if (context->show_column)
492 col = diagnostic_converted_column (context, s);
493 }
876217ae 494
101e910b
NS
495 const char *line_col = maybe_line_and_column (line, col);
496 return build_message_string ("%s%s%s:%s", locus_cs, file,
497 line_col, locus_ce);
876217ae
DM
498}
499
387f6c15
DM
500static const char *const diagnostic_kind_text[] = {
501#define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
502#include "diagnostic.def"
503#undef DEFINE_DIAGNOSTIC_KIND
504 "must-not-happen"
505};
506
876217ae
DM
507/* Return a malloc'd string describing a location and the severity of the
508 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
509 freeing the memory. */
47b69537 510char *
243fbddd 511diagnostic_build_prefix (diagnostic_context *context,
dfa32261 512 const diagnostic_info *diagnostic)
47b69537 513{
99abe958
MLI
514 gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
515
255508dd 516 const char *text = _(diagnostic_kind_text[diagnostic->kind]);
4b84d650 517 const char *text_cs = "", *text_ce = "";
4b84d650
JJ
518 pretty_printer *pp = context->printer;
519
520 if (diagnostic_kind_color[diagnostic->kind])
521 {
522 text_cs = colorize_start (pp_show_color (pp),
523 diagnostic_kind_color[diagnostic->kind]);
524 text_ce = colorize_stop (pp_show_color (pp));
525 }
4b84d650 526
99abe958 527 expanded_location s = diagnostic_expand_location (diagnostic);
876217ae
DM
528 char *location_text = diagnostic_get_location_text (context, s);
529
530 char *result = build_message_string ("%s %s%s%s", location_text,
531 text_cs, text, text_ce);
532 free (location_text);
533 return result;
47b69537
GDR
534}
535
d83697f4
ILT
536/* Functions at which to stop the backtrace print. It's not
537 particularly helpful to print the callers of these functions. */
538
539static const char * const bt_stop[] =
540{
541 "main",
3edf64aa 542 "toplev::main",
d83697f4
ILT
543 "execute_one_pass",
544 "compile_file",
545};
546
547/* A callback function passed to the backtrace_full function. */
548
549static int
550bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
551 const char *function)
552{
553 int *pcount = (int *) data;
554
555 /* If we don't have any useful information, don't print
556 anything. */
557 if (filename == NULL && function == NULL)
558 return 0;
559
e53b6e56 560 /* Skip functions in diagnostic.cc. */
d83697f4
ILT
561 if (*pcount == 0
562 && filename != NULL
e53b6e56 563 && strcmp (lbasename (filename), "diagnostic.cc") == 0)
d83697f4
ILT
564 return 0;
565
566 /* Print up to 20 functions. We could make this a --param, but
567 since this is only for debugging just use a constant for now. */
568 if (*pcount >= 20)
569 {
570 /* Returning a non-zero value stops the backtrace. */
571 return 1;
572 }
573 ++*pcount;
574
575 char *alc = NULL;
576 if (function != NULL)
577 {
578 char *str = cplus_demangle_v3 (function,
579 (DMGL_VERBOSE | DMGL_ANSI
580 | DMGL_GNU_V3 | DMGL_PARAMS));
581 if (str != NULL)
582 {
583 alc = str;
584 function = str;
585 }
586
587 for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
588 {
589 size_t len = strlen (bt_stop[i]);
590 if (strncmp (function, bt_stop[i], len) == 0
591 && (function[len] == '\0' || function[len] == '('))
592 {
593 if (alc != NULL)
594 free (alc);
595 /* Returning a non-zero value stops the backtrace. */
596 return 1;
597 }
598 }
599 }
600
601 fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
a67a73fd 602 (unsigned long) pc,
d83697f4
ILT
603 function == NULL ? "???" : function,
604 filename == NULL ? "???" : filename,
605 lineno);
606
607 if (alc != NULL)
608 free (alc);
609
610 return 0;
611}
612
613/* A callback function passed to the backtrace_full function. This is
614 called if backtrace_full has an error. */
615
616static void
617bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
618{
619 if (errnum < 0)
620 {
621 /* This means that no debug info was available. Just quietly
622 skip printing backtrace info. */
623 return;
624 }
625 fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
626 errnum == 0 ? "" : xstrerror (errnum));
627}
628
d0ea9f0a
NS
629/* Check if we've met the maximum error limit, and if so fatally exit
630 with a message. CONTEXT is the context to check, and FLUSH
631 indicates whether a diagnostic_finish call is needed. */
632
633void
634diagnostic_check_max_errors (diagnostic_context *context, bool flush)
635{
636 if (!context->max_errors)
637 return;
638
639 int count = (diagnostic_kind_count (context, DK_ERROR)
640 + diagnostic_kind_count (context, DK_SORRY)
641 + diagnostic_kind_count (context, DK_WERROR));
642
643 if (count >= context->max_errors)
644 {
645 fnotice (stderr,
646 "compilation terminated due to -fmax-errors=%u.\n",
647 context->max_errors);
648 if (flush)
649 diagnostic_finish (context);
650 exit (FATAL_EXIT_CODE);
651 }
652}
653
9804f5fb
ZW
654/* Take any action which is expected to happen after the diagnostic
655 is written out. This function does not always return. */
c4100eae 656void
79a490a9 657diagnostic_action_after_output (diagnostic_context *context,
c4100eae 658 diagnostic_t diag_kind)
9804f5fb 659{
c4100eae 660 switch (diag_kind)
9804f5fb
ZW
661 {
662 case DK_DEBUG:
663 case DK_NOTE:
664 case DK_ANACHRONISM:
665 case DK_WARNING:
666 break;
667
668 case DK_ERROR:
669 case DK_SORRY:
670 if (context->abort_on_error)
671 real_abort ();
243fbddd 672 if (context->fatal_errors)
c65a01af
RG
673 {
674 fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
d0b8780d 675 diagnostic_finish (context);
c65a01af
RG
676 exit (FATAL_EXIT_CODE);
677 }
9804f5fb
ZW
678 break;
679
680 case DK_ICE:
b55f40c1 681 case DK_ICE_NOBT:
d83697f4 682 {
79aaba0a
DM
683 /* Optional callback for attempting to handle ICEs gracefully. */
684 if (void (*ice_handler_cb) (diagnostic_context *)
685 = context->ice_handler_cb)
686 {
687 /* Clear the callback, to avoid potentially re-entering
688 the routine if there's a crash within the handler. */
689 context->ice_handler_cb = NULL;
690 ice_handler_cb (context);
691 }
692 /* The context might have had diagnostic_finish called on
693 it at this point. */
694
b55f40c1
JJ
695 struct backtrace_state *state = NULL;
696 if (diag_kind == DK_ICE)
697 state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
d83697f4
ILT
698 int count = 0;
699 if (state != NULL)
700 backtrace_full (state, 2, bt_callback, bt_err_callback,
701 (void *) &count);
702
703 if (context->abort_on_error)
704 real_abort ();
705
76ef38e3 706 if (context->report_bug)
3f0fcda3 707 fnotice (stderr, "Please submit a full bug report, "
76ef38e3
ML
708 "with preprocessed source.\n");
709 else
3f0fcda3 710 fnotice (stderr, "Please submit a full bug report, "
76ef38e3
ML
711 "with preprocessed source (by using -freport-bug).\n");
712
d83697f4 713 if (count > 0)
76ef38e3
ML
714 fnotice (stderr, "Please include the complete backtrace "
715 "with any bug report.\n");
d83697f4 716 fnotice (stderr, "See %s for instructions.\n", bug_report_url);
9804f5fb 717
d83697f4
ILT
718 exit (ICE_EXIT_CODE);
719 }
9804f5fb
ZW
720
721 case DK_FATAL:
722 if (context->abort_on_error)
723 real_abort ();
d0b8780d 724 diagnostic_finish (context);
9804f5fb
ZW
725 fnotice (stderr, "compilation terminated.\n");
726 exit (FATAL_EXIT_CODE);
727
728 default:
d5706a1e 729 gcc_unreachable ();
9804f5fb
ZW
730 }
731}
732
26d5ed6c
DM
733/* True if the last module or file in which a diagnostic was reported is
734 different from the current one. */
735
736static bool
737last_module_changed_p (diagnostic_context *context,
738 const line_map_ordinary *map)
739{
740 return context->last_module != map;
741}
742
743/* Remember the current module or file as being the last one in which we
744 report a diagnostic. */
745
746static void
747set_last_module (diagnostic_context *context, const line_map_ordinary *map)
748{
749 context->last_module = map;
750}
751
d3a57993
JM
752/* Only dump the "In file included from..." stack once for each file. */
753
754static bool
755includes_seen (diagnostic_context *context, const line_map_ordinary *map)
756{
757 /* No include path for main. */
758 if (MAIN_FILE_P (map))
759 return true;
760
761 /* Always identify C++ modules, at least for now. */
762 auto probe = map;
763 if (linemap_check_ordinary (map)->reason == LC_RENAME)
764 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
765 probe = linemap_included_from_linemap (line_table, map);
766 if (MAP_MODULE_P (probe))
767 return false;
768
769 if (!context->includes_seen)
770 context->includes_seen = new hash_set<location_t, false, location_hash>;
771
772 /* Hash the location of the #include directive to better handle files
773 that are included multiple times with different macros defined. */
774 return context->includes_seen->add (linemap_included_from (map));
775}
776
6ed551b4 777void
07a0b324 778diagnostic_report_current_module (diagnostic_context *context, location_t where)
6ed551b4 779{
0e50b624 780 const line_map_ordinary *map = NULL;
6ed551b4 781
b6fe0bb8 782 if (pp_needs_newline (context->printer))
59650e48 783 {
b6fe0bb8
GDR
784 pp_newline (context->printer);
785 pp_needs_newline (context->printer) = false;
59650e48 786 }
6ed551b4 787
07a0b324 788 if (where <= BUILTINS_LOCATION)
966e8f4d
TT
789 return;
790
07a0b324
TT
791 linemap_resolve_location (line_table, where,
792 LRK_MACRO_DEFINITION_LOCATION,
793 &map);
794
26d5ed6c 795 if (map && last_module_changed_p (context, map))
59650e48 796 {
26d5ed6c 797 set_last_module (context, map);
d3a57993 798 if (!includes_seen (context, map))
6773e15f 799 {
204b61b9 800 bool first = true, need_inc = true, was_module = MAP_MODULE_P (map);
004bb936 801 expanded_location s = {};
9e525f08 802 do
966e8f4d 803 {
f10a9135
NS
804 where = linemap_included_from (map);
805 map = linemap_included_from_linemap (line_table, map);
204b61b9 806 bool is_module = MAP_MODULE_P (map);
004bb936
LH
807 s.file = LINEMAP_FILE (map);
808 s.line = SOURCE_LINE (map, where);
809 int col = -1;
810 if (first && context->show_column)
811 {
812 s.column = SOURCE_COLUMN (map, where);
813 col = diagnostic_converted_column (context, s);
814 }
815 const char *line_col = maybe_line_and_column (s.line, col);
9e525f08
NS
816 static const char *const msgs[] =
817 {
204b61b9 818 NULL,
9e525f08 819 N_(" from"),
204b61b9
NS
820 N_("In file included from"), /* 2 */
821 N_(" included from"),
822 N_("In module"), /* 4 */
823 N_("of module"),
824 N_("In module imported at"), /* 6 */
825 N_("imported at"),
9e525f08 826 };
204b61b9
NS
827
828 unsigned index = (was_module ? 6 : is_module ? 4
829 : need_inc ? 2 : 0) + !first;
830
9e525f08 831 pp_verbatim (context->printer, "%s%s %r%s%s%R",
204b61b9
NS
832 first ? "" : was_module ? ", " : ",\n",
833 _(msgs[index]),
004bb936 834 "locus", s.file, line_col);
204b61b9 835 first = false, need_inc = was_module, was_module = is_module;
966e8f4d 836 }
d3a57993 837 while (!includes_seen (context, map));
966e8f4d
TT
838 pp_verbatim (context->printer, ":");
839 pp_newline (context->printer);
6773e15f 840 }
59650e48
ZW
841 }
842}
400500c4 843
4bc1899b
DM
844/* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
845 print the path. */
846
847void
848diagnostic_show_any_path (diagnostic_context *context,
849 diagnostic_info *diagnostic)
850{
851 const diagnostic_path *path = diagnostic->richloc->get_path ();
852 if (!path)
853 return;
854
855 if (context->print_path)
856 context->print_path (context, path);
857}
858
6cf276dd
DM
859/* class diagnostic_event. */
860
861/* struct diagnostic_event::meaning. */
862
863void
864diagnostic_event::meaning::dump_to_pp (pretty_printer *pp) const
865{
866 bool need_comma = false;
867 pp_character (pp, '{');
868 if (const char *verb_str = maybe_get_verb_str (m_verb))
869 {
870 pp_printf (pp, "verb: %qs", verb_str);
871 need_comma = true;
872 }
873 if (const char *noun_str = maybe_get_noun_str (m_noun))
874 {
875 if (need_comma)
876 pp_string (pp, ", ");
877 pp_printf (pp, "noun: %qs", noun_str);
878 need_comma = true;
879 }
880 if (const char *property_str = maybe_get_property_str (m_property))
881 {
882 if (need_comma)
883 pp_string (pp, ", ");
884 pp_printf (pp, "property: %qs", property_str);
885 need_comma = true;
886 }
887 pp_character (pp, '}');
888}
889
890/* Get a string (or NULL) for V suitable for use within a SARIF
891 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
892
893const char *
894diagnostic_event::meaning::maybe_get_verb_str (enum verb v)
895{
896 switch (v)
897 {
898 default:
899 gcc_unreachable ();
900 case VERB_unknown:
901 return NULL;
902 case VERB_acquire:
903 return "acquire";
904 case VERB_release:
905 return "release";
906 case VERB_enter:
907 return "enter";
908 case VERB_exit:
909 return "exit";
910 case VERB_call:
911 return "call";
912 case VERB_return:
913 return "return";
914 case VERB_branch:
915 return "branch";
916 case VERB_danger:
917 return "danger";
918 }
919}
920
921/* Get a string (or NULL) for N suitable for use within a SARIF
922 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
923
924const char *
925diagnostic_event::meaning::maybe_get_noun_str (enum noun n)
926{
927 switch (n)
928 {
929 default:
930 gcc_unreachable ();
931 case NOUN_unknown:
932 return NULL;
933 case NOUN_taint:
934 return "taint";
935 case NOUN_sensitive:
936 return "sensitive";
937 case NOUN_function:
938 return "function";
939 case NOUN_lock:
940 return "lock";
941 case NOUN_memory:
942 return "memory";
943 case NOUN_resource:
944 return "resource";
945 }
946}
947
948/* Get a string (or NULL) for P suitable for use within a SARIF
949 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
950
951const char *
952diagnostic_event::meaning::maybe_get_property_str (enum property p)
953{
954 switch (p)
955 {
956 default:
957 gcc_unreachable ();
958 case PROPERTY_unknown:
959 return NULL;
960 case PROPERTY_true:
961 return "true";
962 case PROPERTY_false:
963 return "false";
964 }
965}
966
967/* class diagnostic_path. */
968
1d86af24
DM
969/* Subroutint of diagnostic_path::interprocedural_p.
970 Look for the first event in this path that is within a function
971 i.e. has a non-NULL fndecl, and a non-zero stack depth.
972 If found, write its index to *OUT_IDX and return true.
973 Otherwise return false. */
974
975bool
976diagnostic_path::get_first_event_in_a_function (unsigned *out_idx) const
977{
978 const unsigned num = num_events ();
979 for (unsigned i = 0; i < num; i++)
980 {
981 if (!(get_event (i).get_fndecl () == NULL
982 && get_event (i).get_stack_depth () == 0))
983 {
984 *out_idx = i;
985 return true;
986 }
987 }
988 return false;
989}
990
4bc1899b
DM
991/* Return true if the events in this path involve more than one
992 function, or false if it is purely intraprocedural. */
993
994bool
995diagnostic_path::interprocedural_p () const
996{
1d86af24
DM
997 /* Ignore leading events that are outside of any function. */
998 unsigned first_fn_event_idx;
999 if (!get_first_event_in_a_function (&first_fn_event_idx))
1000 return false;
1001
1002 const diagnostic_event &first_fn_event = get_event (first_fn_event_idx);
1003 tree first_fndecl = first_fn_event.get_fndecl ();
1004 int first_fn_stack_depth = first_fn_event.get_stack_depth ();
1005
4bc1899b 1006 const unsigned num = num_events ();
1d86af24 1007 for (unsigned i = first_fn_event_idx + 1; i < num; i++)
4bc1899b 1008 {
1d86af24 1009 if (get_event (i).get_fndecl () != first_fndecl)
4bc1899b 1010 return true;
1d86af24 1011 if (get_event (i).get_stack_depth () != first_fn_stack_depth)
4bc1899b
DM
1012 return true;
1013 }
1014 return false;
1015}
1016
4537ec0c 1017void
79a490a9
AJ
1018default_diagnostic_starter (diagnostic_context *context,
1019 diagnostic_info *diagnostic)
6ed551b4 1020{
2a2703a2 1021 diagnostic_report_current_module (context, diagnostic_location (diagnostic));
243fbddd
JM
1022 pp_set_prefix (context->printer, diagnostic_build_prefix (context,
1023 diagnostic));
59650e48 1024}
6ed551b4 1025
876217ae
DM
1026void
1027default_diagnostic_start_span_fn (diagnostic_context *context,
1028 expanded_location exploc)
1029{
5c6a2bf2
DM
1030 char *text = diagnostic_get_location_text (context, exploc);
1031 pp_string (context->printer, text);
1032 free (text);
876217ae
DM
1033 pp_newline (context->printer);
1034}
1035
4537ec0c 1036void
18767f65 1037default_diagnostic_finalizer (diagnostic_context *context,
478dd60d
DM
1038 diagnostic_info *diagnostic,
1039 diagnostic_t)
59650e48 1040{
e9c9a142
DM
1041 char *saved_prefix = pp_take_prefix (context->printer);
1042 pp_set_prefix (context->printer, NULL);
d3e28653 1043 pp_newline (context->printer);
cc015f3a 1044 diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
e9c9a142 1045 pp_set_prefix (context->printer, saved_prefix);
01e1dea3 1046 pp_flush (context->printer);
6ed551b4
GDR
1047}
1048
79cf5994
DD
1049/* Interface to specify diagnostic kind overrides. Returns the
1050 previous setting, or DK_UNSPECIFIED if the parameters are out of
3c8ca1ab
EB
1051 range. If OPTION_INDEX is zero, the new setting is for all the
1052 diagnostics. */
79cf5994
DD
1053diagnostic_t
1054diagnostic_classify_diagnostic (diagnostic_context *context,
1055 int option_index,
cd7fe53b
DD
1056 diagnostic_t new_kind,
1057 location_t where)
79cf5994
DD
1058{
1059 diagnostic_t old_kind;
1060
3c8ca1ab 1061 if (option_index < 0
5f0f4a3b 1062 || option_index >= context->n_opts
79cf5994
DD
1063 || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
1064 return DK_UNSPECIFIED;
1065
1066 old_kind = context->classify_diagnostic[option_index];
cd7fe53b
DD
1067
1068 /* Handle pragmas separately, since we need to keep track of *where*
1069 the pragmas were. */
1070 if (where != UNKNOWN_LOCATION)
1071 {
1072 int i;
1073
3ba421e8
MLI
1074 /* Record the command-line status, so we can reset it back on DK_POP. */
1075 if (old_kind == DK_UNSPECIFIED)
1076 {
b32bc1ac 1077 old_kind = !context->option_enabled (option_index,
fa5baeed 1078 context->lang_mask,
b32bc1ac
MLI
1079 context->option_state)
1080 ? DK_IGNORED : (context->warning_as_error_requested
1081 ? DK_ERROR : DK_WARNING);
3ba421e8
MLI
1082 context->classify_diagnostic[option_index] = old_kind;
1083 }
1084
cd7fe53b
DD
1085 for (i = context->n_classification_history - 1; i >= 0; i --)
1086 if (context->classification_history[i].option == option_index)
1087 {
1088 old_kind = context->classification_history[i].kind;
1089 break;
1090 }
1091
1092 i = context->n_classification_history;
1093 context->classification_history =
1094 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1095 * sizeof (diagnostic_classification_change_t));
1096 context->classification_history[i].location = where;
1097 context->classification_history[i].option = option_index;
1098 context->classification_history[i].kind = new_kind;
1099 context->n_classification_history ++;
1100 }
1101 else
1102 context->classify_diagnostic[option_index] = new_kind;
1103
79cf5994
DD
1104 return old_kind;
1105}
1106
cd7fe53b
DD
1107/* Save all diagnostic classifications in a stack. */
1108void
1109diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
1110{
1111 context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
1112 context->push_list[context->n_push ++] = context->n_classification_history;
1113}
1114
1115/* Restore the topmost classification set off the stack. If the stack
1116 is empty, revert to the state based on command line parameters. */
1117void
1118diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
1119{
1120 int jump_to;
1121 int i;
1122
1123 if (context->n_push)
1124 jump_to = context->push_list [-- context->n_push];
1125 else
1126 jump_to = 0;
1127
1128 i = context->n_classification_history;
1129 context->classification_history =
1130 (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
1131 * sizeof (diagnostic_classification_change_t));
1132 context->classification_history[i].location = where;
1133 context->classification_history[i].option = jump_to;
1134 context->classification_history[i].kind = DK_POP;
1135 context->n_classification_history ++;
1136}
1137
a93eac6a
DM
1138/* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1139 escaping rules for -fdiagnostics-parseable-fixits. */
1140
1141static void
1142print_escaped_string (pretty_printer *pp, const char *text)
1143{
1144 gcc_assert (pp);
1145 gcc_assert (text);
1146
1147 pp_character (pp, '"');
1148 for (const char *ch = text; *ch; ch++)
1149 {
1150 switch (*ch)
1151 {
1152 case '\\':
1153 /* Escape backslash as two backslashes. */
1154 pp_string (pp, "\\\\");
1155 break;
1156 case '\t':
1157 /* Escape tab as "\t". */
1158 pp_string (pp, "\\t");
1159 break;
1160 case '\n':
1161 /* Escape newline as "\n". */
1162 pp_string (pp, "\\n");
1163 break;
1164 case '"':
1165 /* Escape doublequotes as \". */
1166 pp_string (pp, "\\\"");
1167 break;
1168 default:
1169 if (ISPRINT (*ch))
1170 pp_character (pp, *ch);
1171 else
1172 /* Use octal for non-printable chars. */
1173 {
1174 unsigned char c = (*ch & 0xff);
1175 pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
1176 }
1177 break;
1178 }
1179 }
1180 pp_character (pp, '"');
1181}
1182
f1096055
DM
1183/* Implementation of -fdiagnostics-parseable-fixits and
1184 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1185 Print a machine-parseable version of all fixits in RICHLOC to PP,
1186 using COLUMN_UNIT to express columns.
1187 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
a93eac6a
DM
1188
1189static void
f1096055
DM
1190print_parseable_fixits (pretty_printer *pp, rich_location *richloc,
1191 enum diagnostics_column_unit column_unit,
1192 int tabstop)
a93eac6a
DM
1193{
1194 gcc_assert (pp);
1195 gcc_assert (richloc);
1196
e9c9a142
DM
1197 char *saved_prefix = pp_take_prefix (pp);
1198 pp_set_prefix (pp, NULL);
1199
a93eac6a
DM
1200 for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
1201 {
1202 const fixit_hint *hint = richloc->get_fixit_hint (i);
620e594b 1203 location_t start_loc = hint->get_start_loc ();
a93eac6a
DM
1204 expanded_location start_exploc = expand_location (start_loc);
1205 pp_string (pp, "fix-it:");
1206 print_escaped_string (pp, start_exploc.file);
a93eac6a 1207 /* For compatibility with clang, print as a half-open range. */
620e594b 1208 location_t next_loc = hint->get_next_loc ();
338035aa 1209 expanded_location next_exploc = expand_location (next_loc);
f1096055
DM
1210 int start_col
1211 = convert_column_unit (column_unit, tabstop, start_exploc);
1212 int next_col
1213 = convert_column_unit (column_unit, tabstop, next_exploc);
338035aa 1214 pp_printf (pp, ":{%i:%i-%i:%i}:",
f1096055
DM
1215 start_exploc.line, start_col,
1216 next_exploc.line, next_col);
338035aa 1217 print_escaped_string (pp, hint->get_string ());
a93eac6a
DM
1218 pp_newline (pp);
1219 }
e9c9a142
DM
1220
1221 pp_set_prefix (pp, saved_prefix);
a93eac6a
DM
1222}
1223
6feb628a
MS
1224/* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1225
1226static void
1227get_any_inlining_info (diagnostic_context *context,
1228 diagnostic_info *diagnostic)
1229{
1230 auto &ilocs = diagnostic->m_iinfo.m_ilocs;
1231
1232 if (context->set_locations_cb)
1233 /* Retrieve the locations into which the expression about to be
1234 diagnosed has been inlined, including those of all the callers
1235 all the way down the inlining stack. */
1236 context->set_locations_cb (context, diagnostic);
1237 else
1238 {
1239 /* When there's no callback use just the one location provided
1240 by the caller of the diagnostic function. */
1241 location_t loc = diagnostic_location (diagnostic);
1242 ilocs.safe_push (loc);
1243 diagnostic->m_iinfo.m_allsyslocs = in_system_header_at (loc);
1244 }
1245}
1246
1247/* Update the kind of DIAGNOSTIC based on its location(s), including
1248 any of those in its inlining stack, relative to any
dc41c9b0
DM
1249 #pragma GCC diagnostic
1250 directives recorded within CONTEXT.
1251
6feb628a
MS
1252 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1253 otherwise. */
dc41c9b0
DM
1254
1255static diagnostic_t
1256update_effective_level_from_pragmas (diagnostic_context *context,
1257 diagnostic_info *diagnostic)
1258{
6feb628a 1259 if (diagnostic->m_iinfo.m_allsyslocs && !context->dc_warn_system_headers)
dc41c9b0 1260 {
6feb628a
MS
1261 /* Ignore the diagnostic if all the inlined locations are
1262 in system headers and -Wno-system-headers is in effect. */
1263 diagnostic->kind = DK_IGNORED;
1264 return DK_IGNORED;
1265 }
1266
1267 if (context->n_classification_history <= 0)
1268 return DK_UNSPECIFIED;
dc41c9b0 1269
6feb628a
MS
1270 /* Iterate over the locations, checking the diagnostic disposition
1271 for the diagnostic at each. If it's explicitly set as opposed
1272 to unspecified, update the disposition for this instance of
1273 the diagnostic and return it. */
1274 for (location_t loc: diagnostic->m_iinfo.m_ilocs)
1275 {
dc41c9b0
DM
1276 /* FIXME: Stupid search. Optimize later. */
1277 for (int i = context->n_classification_history - 1; i >= 0; i --)
1278 {
6feb628a
MS
1279 const diagnostic_classification_change_t &hist
1280 = context->classification_history[i];
1281
1282 location_t pragloc = hist.location;
1283 if (!linemap_location_before_p (line_table, pragloc, loc))
1284 continue;
1285
1286 if (hist.kind == (int) DK_POP)
dc41c9b0 1287 {
6feb628a
MS
1288 /* Move on to the next region. */
1289 i = hist.option;
1290 continue;
1291 }
1292
1293 int option = hist.option;
1294 /* The option 0 is for all the diagnostics. */
1295 if (option == 0 || option == diagnostic->option_index)
1296 {
1297 diagnostic_t kind = hist.kind;
1298 if (kind != DK_UNSPECIFIED)
1299 diagnostic->kind = kind;
1300 return kind;
dc41c9b0
DM
1301 }
1302 }
1303 }
1304
6feb628a 1305 return DK_UNSPECIFIED;
dc41c9b0
DM
1306}
1307
6d4a35ca
DM
1308/* Generate a URL string describing CWE. The caller is responsible for
1309 freeing the string. */
1310
6cf276dd 1311char *
6d4a35ca
DM
1312get_cwe_url (int cwe)
1313{
1314 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe);
1315}
1316
1317/* If DIAGNOSTIC has a CWE identifier, print it.
1318
1319 For example, if the diagnostic metadata associates it with CWE-119,
1320 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1321 description of the security issue. */
1322
1323static void
1324print_any_cwe (diagnostic_context *context,
1325 const diagnostic_info *diagnostic)
1326{
1327 if (diagnostic->metadata == NULL)
1328 return;
1329
1330 int cwe = diagnostic->metadata->get_cwe ();
1331 if (cwe)
1332 {
1333 pretty_printer *pp = context->printer;
1334 char *saved_prefix = pp_take_prefix (context->printer);
1335 pp_string (pp, " [");
1336 pp_string (pp, colorize_start (pp_show_color (pp),
1337 diagnostic_kind_color[diagnostic->kind]));
abb48524
DM
1338 if (pp->url_format != URL_FORMAT_NONE)
1339 {
1340 char *cwe_url = get_cwe_url (cwe);
1341 pp_begin_url (pp, cwe_url);
1342 free (cwe_url);
1343 }
6d4a35ca
DM
1344 pp_printf (pp, "CWE-%i", cwe);
1345 pp_set_prefix (context->printer, saved_prefix);
abb48524
DM
1346 if (pp->url_format != URL_FORMAT_NONE)
1347 pp_end_url (pp);
6d4a35ca
DM
1348 pp_string (pp, colorize_stop (pp_show_color (pp)));
1349 pp_character (pp, ']');
1350 }
1351}
1352
0b14f590
DM
1353/* If DIAGNOSTIC has any rules associated with it, print them.
1354
1355 For example, if the diagnostic metadata associates it with a rule
1356 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1357 with any URL provided by the rule. */
1358
1359static void
1360print_any_rules (diagnostic_context *context,
1361 const diagnostic_info *diagnostic)
1362{
1363 if (diagnostic->metadata == NULL)
1364 return;
1365
1366 for (unsigned idx = 0; idx < diagnostic->metadata->get_num_rules (); idx++)
1367 {
1368 const diagnostic_metadata::rule &rule
1369 = diagnostic->metadata->get_rule (idx);
1370 if (char *desc = rule.make_description ())
1371 {
1372 pretty_printer *pp = context->printer;
1373 char *saved_prefix = pp_take_prefix (context->printer);
1374 pp_string (pp, " [");
1375 pp_string (pp,
1376 colorize_start (pp_show_color (pp),
1377 diagnostic_kind_color[diagnostic->kind]));
1378 char *url = NULL;
1379 if (pp->url_format != URL_FORMAT_NONE)
1380 {
1381 url = rule.make_url ();
1382 if (url)
1383 pp_begin_url (pp, url);
1384 }
1385 pp_string (pp, desc);
1386 pp_set_prefix (context->printer, saved_prefix);
1387 if (pp->url_format != URL_FORMAT_NONE)
1388 if (url)
1389 pp_end_url (pp);
1390 free (url);
1391 pp_string (pp, colorize_stop (pp_show_color (pp)));
1392 pp_character (pp, ']');
1393 free (desc);
1394 }
1395 }
1396}
1397
80ceac09
DM
1398/* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1399 printer, e.g. " [-Werror=uninitialized]".
1400 Subroutine of diagnostic_report_diagnostic. */
1401
1402static void
1403print_option_information (diagnostic_context *context,
1404 const diagnostic_info *diagnostic,
1405 diagnostic_t orig_diag_kind)
1406{
1407 char *option_text;
1408
1409 option_text = context->option_name (context, diagnostic->option_index,
1410 orig_diag_kind, diagnostic->kind);
1411
1412 if (option_text)
1413 {
b4c7ca2e 1414 char *option_url = NULL;
abb48524
DM
1415 if (context->get_option_url
1416 && context->printer->url_format != URL_FORMAT_NONE)
b4c7ca2e
DM
1417 option_url = context->get_option_url (context,
1418 diagnostic->option_index);
80ceac09
DM
1419 pretty_printer *pp = context->printer;
1420 pp_string (pp, " [");
1421 pp_string (pp, colorize_start (pp_show_color (pp),
1422 diagnostic_kind_color[diagnostic->kind]));
b4c7ca2e
DM
1423 if (option_url)
1424 pp_begin_url (pp, option_url);
80ceac09 1425 pp_string (pp, option_text);
b4c7ca2e
DM
1426 if (option_url)
1427 {
1428 pp_end_url (pp);
1429 free (option_url);
1430 }
80ceac09
DM
1431 pp_string (pp, colorize_stop (pp_show_color (pp)));
1432 pp_character (pp, ']');
1433 free (option_text);
1434 }
1435}
dc41c9b0 1436
620cd786
JM
1437/* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1438 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1439
1440static bool
1441diagnostic_enabled (diagnostic_context *context,
1442 diagnostic_info *diagnostic)
1443{
6feb628a
MS
1444 /* Update the inlining stack for this diagnostic. */
1445 get_any_inlining_info (context, diagnostic);
1446
620cd786
JM
1447 /* Diagnostics with no option or -fpermissive are always enabled. */
1448 if (!diagnostic->option_index
1449 || diagnostic->option_index == permissive_error_option (context))
1450 return true;
1451
1452 /* This tests if the user provided the appropriate -Wfoo or
1453 -Wno-foo option. */
1454 if (! context->option_enabled (diagnostic->option_index,
1455 context->lang_mask,
1456 context->option_state))
1457 return false;
1458
1459 /* This tests for #pragma diagnostic changes. */
1460 diagnostic_t diag_class
1461 = update_effective_level_from_pragmas (context, diagnostic);
1462
1463 /* This tests if the user provided the appropriate -Werror=foo
1464 option. */
1465 if (diag_class == DK_UNSPECIFIED
1466 && (context->classify_diagnostic[diagnostic->option_index]
1467 != DK_UNSPECIFIED))
1468 diagnostic->kind
1469 = context->classify_diagnostic[diagnostic->option_index];
1470
1471 /* This allows for future extensions, like temporarily disabling
1472 warnings for ranges of source code. */
1473 if (diagnostic->kind == DK_IGNORED)
1474 return false;
1475
1476 return true;
1477}
1478
1479/* Returns whether warning OPT is enabled at LOC. */
1480
1481bool
1482warning_enabled_at (location_t loc, int opt)
1483{
1484 if (!diagnostic_report_warnings_p (global_dc, loc))
1485 return false;
1486
1487 rich_location richloc (line_table, loc);
1488 diagnostic_info diagnostic = {};
1489 diagnostic.option_index = opt;
1490 diagnostic.richloc = &richloc;
1491 diagnostic.message.m_richloc = &richloc;
1492 diagnostic.kind = DK_WARNING;
1493 return diagnostic_enabled (global_dc, &diagnostic);
1494}
1495
59650e48
ZW
1496/* Report a diagnostic message (an error or a warning) as specified by
1497 DC. This function is *the* subroutine in terms of which front-ends
1498 should implement their specific diagnostic handling modules. The
1499 front-end independent format specifiers are exactly those described
b8698a0f 1500 in the documentation of output_format.
71205d17 1501 Return true if a diagnostic was printed, false otherwise. */
400500c4 1502
71205d17 1503bool
79a490a9
AJ
1504diagnostic_report_diagnostic (diagnostic_context *context,
1505 diagnostic_info *diagnostic)
400500c4 1506{
2a2703a2 1507 location_t location = diagnostic_location (diagnostic);
d0b8780d 1508 diagnostic_t orig_diag_kind = diagnostic->kind;
4e2bae26
MLI
1509
1510 /* Give preference to being able to inhibit warnings, before they
1511 get reclassified to something else. */
6feb628a
MS
1512 bool report_warning_p = true;
1513 if (diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
1514 {
1515 if (context->dc_inhibit_warnings)
1516 return false;
1517 /* Remember the result of the overall system header warning setting
1518 but proceed to also check the inlining context. */
1519 report_warning_p = diagnostic_report_warnings_p (context, location);
1520 if (!report_warning_p && diagnostic->kind == DK_PEDWARN)
1521 return false;
1522 }
71205d17 1523
b8698a0f 1524 if (diagnostic->kind == DK_PEDWARN)
d0b8780d 1525 {
243fbddd 1526 diagnostic->kind = pedantic_warning_kind (context);
d0b8780d
MLI
1527 /* We do this to avoid giving the message for -pedantic-errors. */
1528 orig_diag_kind = diagnostic->kind;
1529 }
6feb628a 1530
0e94b750
MLI
1531 if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
1532 return false;
b8698a0f 1533
d5706a1e
ZW
1534 if (context->lock > 0)
1535 {
1536 /* If we're reporting an ICE in the middle of some other error,
1537 try to flush out the previous error, then let this one
1538 through. Don't do this more than once. */
b55f40c1
JJ
1539 if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
1540 && context->lock == 1)
f8923f7e 1541 pp_newline_and_flush (context->printer);
d5706a1e
ZW
1542 else
1543 error_recursion (context);
1544 }
1545
4e2bae26
MLI
1546 /* If the user requested that warnings be treated as errors, so be
1547 it. Note that we do this before the next block so that
1548 individual warnings can be overridden back to warnings with
1549 -Wno-error=*. */
1550 if (context->warning_as_error_requested
1551 && diagnostic->kind == DK_WARNING)
03fd1ef6 1552 diagnostic->kind = DK_ERROR;
b8698a0f 1553
6feb628a
MS
1554 diagnostic->message.x_data = &diagnostic->x_data;
1555
1556 /* Check to see if the diagnostic is enabled at the location and
1557 not disabled by #pragma GCC diagnostic anywhere along the inlining
1558 stack. . */
620cd786
JM
1559 if (!diagnostic_enabled (context, diagnostic))
1560 return false;
2098fe9e 1561
6feb628a
MS
1562 if (!report_warning_p && diagnostic->m_iinfo.m_allsyslocs)
1563 /* Bail if the warning is not to be reported because all locations
1564 in the inlining stack (if there is one) are in system headers. */
1565 return false;
1566
49ca22dd 1567 if (diagnostic->kind != DK_NOTE && diagnostic->kind != DK_ICE)
d0ea9f0a
NS
1568 diagnostic_check_max_errors (context);
1569
d5706a1e 1570 context->lock++;
400500c4 1571
b55f40c1 1572 if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
59650e48 1573 {
52249a2e
MLI
1574 /* When not checking, ICEs are converted to fatal errors when an
1575 error has already occurred. This is counteracted by
1576 abort_on_error. */
b2b29377
MM
1577 if (!CHECKING_P
1578 && (diagnostic_kind_count (context, DK_ERROR) > 0
1579 || diagnostic_kind_count (context, DK_SORRY) > 0)
52249a2e
MLI
1580 && !context->abort_on_error)
1581 {
2a2703a2
MLI
1582 expanded_location s
1583 = expand_location (diagnostic_location (diagnostic));
52249a2e
MLI
1584 fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1585 s.file, s.line);
1586 exit (ICE_EXIT_CODE);
1587 }
52249a2e 1588 if (context->internal_error)
a13812e2
JM
1589 (*context->internal_error) (context,
1590 diagnostic->message.format_spec,
52249a2e 1591 diagnostic->message.args_ptr);
43db5b3c 1592 }
37e99116
JJ
1593 if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
1594 ++diagnostic_kind_count (context, DK_WERROR);
1595 else
1596 ++diagnostic_kind_count (context, diagnostic->kind);
b8698a0f 1597
097f82ec
DM
1598 /* Is this the initial diagnostic within the stack of groups? */
1599 if (context->diagnostic_group_emission_count == 0)
1600 {
1601 if (context->begin_group_cb)
1602 context->begin_group_cb (context);
1603 }
1604 context->diagnostic_group_emission_count++;
1605
52249a2e
MLI
1606 pp_format (context->printer, &diagnostic->message);
1607 (*diagnostic_starter (context)) (context, diagnostic);
1608 pp_output_formatted_text (context->printer);
6d4a35ca
DM
1609 if (context->show_cwe)
1610 print_any_cwe (context, diagnostic);
0b14f590
DM
1611 if (context->show_rules)
1612 print_any_rules (context, diagnostic);
80ceac09
DM
1613 if (context->show_option_requested)
1614 print_option_information (context, diagnostic, orig_diag_kind);
478dd60d 1615 (*diagnostic_finalizer (context)) (context, diagnostic, orig_diag_kind);
f1096055 1616 switch (context->extra_output_kind)
a93eac6a 1617 {
f1096055
DM
1618 default:
1619 break;
1620 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1:
1621 print_parseable_fixits (context->printer, diagnostic->richloc,
1622 DIAGNOSTICS_COLUMN_UNIT_BYTE,
1623 context->tabstop);
1624 pp_flush (context->printer);
1625 break;
1626 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2:
1627 print_parseable_fixits (context->printer, diagnostic->richloc,
1628 DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
1629 context->tabstop);
a93eac6a 1630 pp_flush (context->printer);
f1096055 1631 break;
a93eac6a 1632 }
c4100eae 1633 diagnostic_action_after_output (context, diagnostic->kind);
cf835838 1634 diagnostic->x_data = NULL;
9804f5fb 1635
717ebe91 1636 if (context->edit_context_ptr)
b09649fd
DM
1637 if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
1638 context->edit_context_ptr->add_fixits (diagnostic->richloc);
717ebe91 1639
9804f5fb 1640 context->lock--;
71205d17 1641
4bc1899b
DM
1642 diagnostic_show_any_path (context, diagnostic);
1643
71205d17 1644 return true;
59650e48 1645}
43db5b3c 1646
bc65bad2
MG
1647/* Get the number of digits in the decimal representation of VALUE. */
1648
1649int
1650num_digits (int value)
1651{
1652 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1653 using floating point. */
1654 gcc_assert (value >= 0);
1655
1656 if (value == 0)
1657 return 1;
1658
1659 int digits = 0;
1660 while (value > 0)
1661 {
1662 digits++;
1663 value /= 10;
1664 }
1665 return digits;
1666}
1667
59650e48
ZW
1668/* Given a partial pathname as input, return another pathname that
1669 shares no directory elements with the pathname of __FILE__. This
76ef38e3
ML
1670 is used by fancy_abort() to print `internal compiler error in expr.cc'
1671 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
3a538a66 1672
59650e48 1673const char *
79a490a9 1674trim_filename (const char *name)
59650e48
ZW
1675{
1676 static const char this_file[] = __FILE__;
1677 const char *p = name, *q = this_file;
43db5b3c 1678
59650e48
ZW
1679 /* First skip any "../" in each filename. This allows us to give a proper
1680 reference to a file in a subdirectory. */
d5706a1e 1681 while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
59650e48
ZW
1682 p += 3;
1683
d5706a1e 1684 while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
59650e48
ZW
1685 q += 3;
1686
1687 /* Now skip any parts the two filenames have in common. */
1688 while (*p == *q && *p != 0 && *q != 0)
1689 p++, q++;
1690
1691 /* Now go backwards until the previous directory separator. */
ef9af077 1692 while (p > name && !IS_DIR_SEPARATOR (p[-1]))
59650e48
ZW
1693 p--;
1694
1695 return p;
6ed551b4 1696}
59650e48
ZW
1697\f
1698/* Standard error reporting routines in increasing order of severity.
1699 All of these take arguments like printf. */
6ed551b4 1700
59650e48
ZW
1701/* Text to be emitted verbatim to the error message stream; this
1702 produces no prefix and disables line-wrapping. Use rarely. */
6ed551b4 1703void
4b794eaf 1704verbatim (const char *gmsgid, ...)
59650e48
ZW
1705{
1706 text_info text;
e34d07f2 1707 va_list ap;
59650e48 1708
4b794eaf 1709 va_start (ap, gmsgid);
fa6ef813 1710 text.err_no = errno;
59650e48 1711 text.args_ptr = &ap;
4b794eaf 1712 text.format_spec = _(gmsgid);
cf835838 1713 text.x_data = NULL;
b6fe0bb8 1714 pp_format_verbatim (global_dc->printer, &text);
f8923f7e 1715 pp_newline_and_flush (global_dc->printer);
e34d07f2 1716 va_end (ap);
59650e48
ZW
1717}
1718
dfa32261
MLI
1719/* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1720void
1721diagnostic_append_note (diagnostic_context *context,
1722 location_t location,
1723 const char * gmsgid, ...)
1724{
1725 diagnostic_info diagnostic;
1726 va_list ap;
ebedc9a3 1727 rich_location richloc (line_table, location);
dfa32261
MLI
1728
1729 va_start (ap, gmsgid);
8a645150
DM
1730 diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
1731 if (context->inhibit_notes_p)
1732 {
1733 va_end (ap);
1734 return;
1735 }
653fee19 1736 char *saved_prefix = pp_take_prefix (context->printer);
8a645150
DM
1737 pp_set_prefix (context->printer,
1738 diagnostic_build_prefix (context, &diagnostic));
dfa32261
MLI
1739 pp_format (context->printer, &diagnostic.message);
1740 pp_output_formatted_text (context->printer);
1741 pp_destroy_prefix (context->printer);
4432aa6c 1742 pp_set_prefix (context->printer, saved_prefix);
d3e28653 1743 pp_newline (context->printer);
cc015f3a 1744 diagnostic_show_locus (context, &richloc, DK_NOTE);
c3284718 1745 va_end (ap);
dfa32261
MLI
1746}
1747
64a5912c
DM
1748/* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1749 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1750 and internal_error_no_backtrace, as documented and defined below. */
c3811744 1751static bool
6d4a35ca
DM
1752diagnostic_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1753 int opt, const char *gmsgid,
c3811744 1754 va_list *ap, diagnostic_t kind)
6ed551b4 1755{
47b69537 1756 diagnostic_info diagnostic;
71205d17
MLI
1757 if (kind == DK_PERMERROR)
1758 {
c3811744 1759 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
243fbddd 1760 permissive_error_kind (global_dc));
5f0f4a3b 1761 diagnostic.option_index = permissive_error_option (global_dc);
71205d17 1762 }
c3811744
PC
1763 else
1764 {
1765 diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
71205d17
MLI
1766 if (kind == DK_WARNING || kind == DK_PEDWARN)
1767 diagnostic.option_index = opt;
c3811744 1768 }
6d4a35ca 1769 diagnostic.metadata = metadata;
56d35585 1770 return diagnostic_report_diagnostic (global_dc, &diagnostic);
c3811744
PC
1771}
1772
64a5912c
DM
1773/* Implement inform_n, warning_n, and error_n, as documented and
1774 defined below. */
a5fb7ad2 1775static bool
6d4a35ca
DM
1776diagnostic_n_impl (rich_location *richloc, const diagnostic_metadata *metadata,
1777 int opt, unsigned HOST_WIDE_INT n,
64a5912c
DM
1778 const char *singular_gmsgid,
1779 const char *plural_gmsgid,
1780 va_list *ap, diagnostic_t kind)
a5fb7ad2
PK
1781{
1782 diagnostic_info diagnostic;
1c89478a
MS
1783 unsigned long gtn;
1784
1785 if (sizeof n <= sizeof gtn)
1786 gtn = n;
1787 else
1788 /* Use the largest number ngettext can handle, otherwise
1789 preserve the six least significant decimal digits for
1790 languages where the plural form depends on them. */
1791 gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
1792
1793 const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
1794 diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
a5fb7ad2
PK
1795 if (kind == DK_WARNING)
1796 diagnostic.option_index = opt;
6d4a35ca 1797 diagnostic.metadata = metadata;
56d35585 1798 return diagnostic_report_diagnostic (global_dc, &diagnostic);
c3811744 1799}
71205d17 1800
296c53ac
MP
1801/* Wrapper around diagnostic_impl taking a variable argument list. */
1802
c3811744
PC
1803bool
1804emit_diagnostic (diagnostic_t kind, location_t location, int opt,
1805 const char *gmsgid, ...)
1806{
097f82ec 1807 auto_diagnostic_group d;
c3811744
PC
1808 va_list ap;
1809 va_start (ap, gmsgid);
1810 rich_location richloc (line_table, location);
6d4a35ca 1811 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, kind);
80f24351
MM
1812 va_end (ap);
1813 return ret;
6ed551b4
GDR
1814}
1815
8ba109ce
DM
1816/* As above, but for rich_location *. */
1817
1818bool
1819emit_diagnostic (diagnostic_t kind, rich_location *richloc, int opt,
1820 const char *gmsgid, ...)
1821{
1822 auto_diagnostic_group d;
1823 va_list ap;
1824 va_start (ap, gmsgid);
6d4a35ca 1825 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, kind);
8ba109ce
DM
1826 va_end (ap);
1827 return ret;
1828}
1829
296c53ac
MP
1830/* Wrapper around diagnostic_impl taking a va_list parameter. */
1831
1832bool
1833emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
1834 const char *gmsgid, va_list *ap)
1835{
1836 rich_location richloc (line_table, location);
6d4a35ca
DM
1837 return diagnostic_impl (&richloc, NULL, opt, gmsgid, ap, kind);
1838}
1839
1f5b3869 1840/* An informative note at LOCATION. Use this for additional details on an error
71205d17 1841 message. */
6ed551b4 1842void
1f5b3869 1843inform (location_t location, const char *gmsgid, ...)
8a645150 1844{
097f82ec 1845 auto_diagnostic_group d;
8a645150 1846 va_list ap;
8a645150 1847 va_start (ap, gmsgid);
c3811744 1848 rich_location richloc (line_table, location);
6d4a35ca 1849 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
8a645150
DM
1850 va_end (ap);
1851}
1852
64a5912c 1853/* Same as "inform" above, but at RICHLOC. */
8a645150 1854void
64a5912c 1855inform (rich_location *richloc, const char *gmsgid, ...)
d4ee4d25 1856{
64a5912c
DM
1857 gcc_assert (richloc);
1858
097f82ec 1859 auto_diagnostic_group d;
d4ee4d25 1860 va_list ap;
4b794eaf 1861 va_start (ap, gmsgid);
6d4a35ca 1862 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_NOTE);
d4ee4d25
DD
1863 va_end (ap);
1864}
1865
894e2652
SZ
1866/* An informative note at LOCATION. Use this for additional details on an
1867 error message. */
1868void
1c89478a
MS
1869inform_n (location_t location, unsigned HOST_WIDE_INT n,
1870 const char *singular_gmsgid, const char *plural_gmsgid, ...)
894e2652 1871{
894e2652 1872 va_list ap;
894e2652 1873 va_start (ap, plural_gmsgid);
097f82ec 1874 auto_diagnostic_group d;
64a5912c 1875 rich_location richloc (line_table, location);
6d4a35ca 1876 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
c3811744 1877 &ap, DK_NOTE);
894e2652
SZ
1878 va_end (ap);
1879}
1880
71205d17 1881/* A warning at INPUT_LOCATION. Use this for code which is correct according
b8698a0f 1882 to the relevant language specification but is likely to be buggy anyway.
71205d17
MLI
1883 Returns true if the warning was printed, false if it was inhibited. */
1884bool
1885warning (int opt, const char *gmsgid, ...)
6ed551b4 1886{
097f82ec 1887 auto_diagnostic_group d;
e34d07f2 1888 va_list ap;
4b794eaf 1889 va_start (ap, gmsgid);
c3811744 1890 rich_location richloc (line_table, input_location);
6d4a35ca 1891 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
e34d07f2 1892 va_end (ap);
80f24351 1893 return ret;
6ed551b4
GDR
1894}
1895
aa14403d 1896/* A warning at LOCATION. Use this for code which is correct according to the
71205d17
MLI
1897 relevant language specification but is likely to be buggy anyway.
1898 Returns true if the warning was printed, false if it was inhibited. */
1899
1900bool
aa14403d 1901warning_at (location_t location, int opt, const char *gmsgid, ...)
8a645150 1902{
097f82ec 1903 auto_diagnostic_group d;
8a645150 1904 va_list ap;
8a645150 1905 va_start (ap, gmsgid);
c3811744 1906 rich_location richloc (line_table, location);
6d4a35ca 1907 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
8a645150
DM
1908 va_end (ap);
1909 return ret;
1910}
1911
64a5912c 1912/* Same as "warning at" above, but using RICHLOC. */
8a645150
DM
1913
1914bool
64a5912c 1915warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
aa14403d 1916{
64a5912c
DM
1917 gcc_assert (richloc);
1918
097f82ec 1919 auto_diagnostic_group d;
aa14403d 1920 va_list ap;
aa14403d 1921 va_start (ap, gmsgid);
6d4a35ca
DM
1922 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_WARNING);
1923 va_end (ap);
1924 return ret;
1925}
1926
1927/* Same as "warning at" above, but using METADATA. */
1928
1929bool
6c8e5844
DM
1930warning_meta (rich_location *richloc,
1931 const diagnostic_metadata &metadata,
1932 int opt, const char *gmsgid, ...)
6d4a35ca
DM
1933{
1934 gcc_assert (richloc);
1935
1936 auto_diagnostic_group d;
1937 va_list ap;
1938 va_start (ap, gmsgid);
1939 bool ret
1940 = diagnostic_impl (richloc, &metadata, opt, gmsgid, &ap,
1941 DK_WARNING);
aa14403d 1942 va_end (ap);
80f24351 1943 return ret;
aa14403d
RAE
1944}
1945
64a5912c 1946/* Same as warning_n plural variant below, but using RICHLOC. */
a5fb7ad2
PK
1947
1948bool
1c89478a 1949warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
64a5912c 1950 const char *singular_gmsgid, const char *plural_gmsgid, ...)
a5fb7ad2 1951{
64a5912c
DM
1952 gcc_assert (richloc);
1953
097f82ec 1954 auto_diagnostic_group d;
a5fb7ad2
PK
1955 va_list ap;
1956 va_start (ap, plural_gmsgid);
6d4a35ca 1957 bool ret = diagnostic_n_impl (richloc, NULL, opt, n,
64a5912c
DM
1958 singular_gmsgid, plural_gmsgid,
1959 &ap, DK_WARNING);
a5fb7ad2
PK
1960 va_end (ap);
1961 return ret;
1962}
1963
26e82579
JH
1964/* A warning at LOCATION. Use this for code which is correct according to the
1965 relevant language specification but is likely to be buggy anyway.
1966 Returns true if the warning was printed, false if it was inhibited. */
1967
1968bool
1c89478a
MS
1969warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
1970 const char *singular_gmsgid, const char *plural_gmsgid, ...)
26e82579 1971{
097f82ec 1972 auto_diagnostic_group d;
26e82579 1973 va_list ap;
26e82579 1974 va_start (ap, plural_gmsgid);
64a5912c 1975 rich_location richloc (line_table, location);
6d4a35ca 1976 bool ret = diagnostic_n_impl (&richloc, NULL, opt, n,
c3811744
PC
1977 singular_gmsgid, plural_gmsgid,
1978 &ap, DK_WARNING);
26e82579
JH
1979 va_end (ap);
1980 return ret;
1981}
1982
85790e66
MLI
1983/* A "pedantic" warning at LOCATION: issues a warning unless
1984 -pedantic-errors was given on the command line, in which case it
1985 issues an error. Use this for diagnostics required by the relevant
1986 language standard, if you have chosen not to make them errors.
9804f5fb
ZW
1987
1988 Note that these diagnostics are issued independent of the setting
c1771a20 1989 of the -Wpedantic command-line switch. To get a warning enabled
fcf73884 1990 only with that switch, use either "if (pedantic) pedwarn
c1771a20
MLI
1991 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1992 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
fcf73884 1993
71205d17
MLI
1994 Returns true if the warning was printed, false if it was inhibited. */
1995
85790e66 1996bool
509c9d60 1997pedwarn (location_t location, int opt, const char *gmsgid, ...)
85790e66 1998{
097f82ec 1999 auto_diagnostic_group d;
85790e66 2000 va_list ap;
85790e66 2001 va_start (ap, gmsgid);
c3811744 2002 rich_location richloc (line_table, location);
6d4a35ca 2003 bool ret = diagnostic_impl (&richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
85790e66 2004 va_end (ap);
80f24351 2005 return ret;
85790e66
MLI
2006}
2007
64a5912c 2008/* Same as pedwarn above, but using RICHLOC. */
1a4f11c8
DM
2009
2010bool
64a5912c 2011pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
1a4f11c8 2012{
64a5912c
DM
2013 gcc_assert (richloc);
2014
097f82ec 2015 auto_diagnostic_group d;
1a4f11c8
DM
2016 va_list ap;
2017 va_start (ap, gmsgid);
6d4a35ca 2018 bool ret = diagnostic_impl (richloc, NULL, opt, gmsgid, &ap, DK_PEDWARN);
1a4f11c8
DM
2019 va_end (ap);
2020 return ret;
2021}
2022
7e99f74b
MLI
2023/* A "permissive" error at LOCATION: issues an error unless
2024 -fpermissive was given on the command line, in which case it issues
2025 a warning. Use this for things that really should be errors but we
71205d17 2026 want to support legacy code.
7e99f74b 2027
71205d17
MLI
2028 Returns true if the warning was printed, false if it was inhibited. */
2029
2030bool
cbe5f3b3 2031permerror (location_t location, const char *gmsgid, ...)
7e99f74b 2032{
097f82ec 2033 auto_diagnostic_group d;
7e99f74b 2034 va_list ap;
7e99f74b 2035 va_start (ap, gmsgid);
c3811744 2036 rich_location richloc (line_table, location);
6d4a35ca 2037 bool ret = diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
8a645150
DM
2038 va_end (ap);
2039 return ret;
2040}
2041
64a5912c 2042/* Same as "permerror" above, but at RICHLOC. */
8a645150
DM
2043
2044bool
64a5912c 2045permerror (rich_location *richloc, const char *gmsgid, ...)
8a645150 2046{
64a5912c
DM
2047 gcc_assert (richloc);
2048
097f82ec 2049 auto_diagnostic_group d;
8a645150 2050 va_list ap;
8a645150 2051 va_start (ap, gmsgid);
6d4a35ca 2052 bool ret = diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_PERMERROR);
7e99f74b 2053 va_end (ap);
80f24351 2054 return ret;
7e99f74b
MLI
2055}
2056
59650e48
ZW
2057/* A hard error: the code is definitely ill-formed, and an object file
2058 will not be produced. */
8514e318 2059void
4b794eaf 2060error (const char *gmsgid, ...)
8514e318 2061{
097f82ec 2062 auto_diagnostic_group d;
e34d07f2 2063 va_list ap;
4b794eaf 2064 va_start (ap, gmsgid);
c3811744 2065 rich_location richloc (line_table, input_location);
6d4a35ca 2066 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
e34d07f2 2067 va_end (ap);
93d87cb1
GDR
2068}
2069
894e2652
SZ
2070/* A hard error: the code is definitely ill-formed, and an object file
2071 will not be produced. */
2072void
1c89478a
MS
2073error_n (location_t location, unsigned HOST_WIDE_INT n,
2074 const char *singular_gmsgid, const char *plural_gmsgid, ...)
894e2652 2075{
097f82ec 2076 auto_diagnostic_group d;
894e2652 2077 va_list ap;
894e2652 2078 va_start (ap, plural_gmsgid);
64a5912c 2079 rich_location richloc (line_table, location);
6d4a35ca 2080 diagnostic_n_impl (&richloc, NULL, -1, n, singular_gmsgid, plural_gmsgid,
c3811744 2081 &ap, DK_ERROR);
894e2652
SZ
2082 va_end (ap);
2083}
2084
c3811744 2085/* Same as above, but use location LOC instead of input_location. */
a63068b6
AH
2086void
2087error_at (location_t loc, const char *gmsgid, ...)
2088{
097f82ec 2089 auto_diagnostic_group d;
a63068b6 2090 va_list ap;
a63068b6 2091 va_start (ap, gmsgid);
c3811744 2092 rich_location richloc (line_table, loc);
6d4a35ca 2093 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
8a645150
DM
2094 va_end (ap);
2095}
2096
2097/* Same as above, but use RICH_LOC. */
2098
2099void
64a5912c 2100error_at (rich_location *richloc, const char *gmsgid, ...)
8a645150 2101{
64a5912c
DM
2102 gcc_assert (richloc);
2103
097f82ec 2104 auto_diagnostic_group d;
8a645150 2105 va_list ap;
8a645150 2106 va_start (ap, gmsgid);
6d4a35ca 2107 diagnostic_impl (richloc, NULL, -1, gmsgid, &ap, DK_ERROR);
a63068b6
AH
2108 va_end (ap);
2109}
2110
1ad5ae5a
DM
2111/* Same as above, but with metadata. */
2112
2113void
2114error_meta (rich_location *richloc, const diagnostic_metadata &metadata,
2115 const char *gmsgid, ...)
2116{
2117 gcc_assert (richloc);
2118
2119 auto_diagnostic_group d;
2120 va_list ap;
2121 va_start (ap, gmsgid);
2122 diagnostic_impl (richloc, &metadata, -1, gmsgid, &ap, DK_ERROR);
2123 va_end (ap);
2124}
2125
59650e48
ZW
2126/* "Sorry, not implemented." Use for a language feature which is
2127 required by the relevant specification but not implemented by GCC.
2128 An object file will not be produced. */
93d87cb1 2129void
4b794eaf 2130sorry (const char *gmsgid, ...)
93d87cb1 2131{
097f82ec 2132 auto_diagnostic_group d;
e34d07f2 2133 va_list ap;
4b794eaf 2134 va_start (ap, gmsgid);
c3811744 2135 rich_location richloc (line_table, input_location);
6d4a35ca 2136 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
e34d07f2 2137 va_end (ap);
59650e48 2138}
43db5b3c 2139
ad172f72
AS
2140/* Same as above, but use location LOC instead of input_location. */
2141void
2142sorry_at (location_t loc, const char *gmsgid, ...)
2143{
2144 auto_diagnostic_group d;
2145 va_list ap;
2146 va_start (ap, gmsgid);
2147 rich_location richloc (line_table, loc);
6d4a35ca 2148 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_SORRY);
ad172f72
AS
2149 va_end (ap);
2150}
2151
1da2ed5f
JM
2152/* Return true if an error or a "sorry" has been seen. Various
2153 processing is disabled after errors. */
2154bool
2155seen_error (void)
2156{
2157 return errorcount || sorrycount;
2158}
2159
3d00119c
AB
2160/* An error which is severe enough that we make no attempt to
2161 continue. Do not use this for internal consistency checks; that's
2162 internal_error. Use of this function should be rare. */
2163void
2164fatal_error (location_t loc, const char *gmsgid, ...)
2165{
097f82ec 2166 auto_diagnostic_group d;
3d00119c 2167 va_list ap;
3d00119c 2168 va_start (ap, gmsgid);
c3811744 2169 rich_location richloc (line_table, loc);
6d4a35ca 2170 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_FATAL);
3d00119c
AB
2171 va_end (ap);
2172
2173 gcc_unreachable ();
2174}
2175
59650e48 2176/* An internal consistency check has failed. We make no attempt to
cd4a0ddc 2177 continue. */
59650e48 2178void
4b794eaf 2179internal_error (const char *gmsgid, ...)
fbfc1192 2180{
097f82ec 2181 auto_diagnostic_group d;
e34d07f2 2182 va_list ap;
4b794eaf 2183 va_start (ap, gmsgid);
c3811744 2184 rich_location richloc (line_table, input_location);
6d4a35ca 2185 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE);
e34d07f2 2186 va_end (ap);
fbfc1192 2187
d5706a1e 2188 gcc_unreachable ();
fbfc1192 2189}
b55f40c1
JJ
2190
2191/* Like internal_error, but no backtrace will be printed. Used when
2192 the internal error does not happen at the current location, but happened
2193 somewhere else. */
2194void
2195internal_error_no_backtrace (const char *gmsgid, ...)
2196{
097f82ec 2197 auto_diagnostic_group d;
b55f40c1 2198 va_list ap;
b55f40c1 2199 va_start (ap, gmsgid);
c3811744 2200 rich_location richloc (line_table, input_location);
6d4a35ca 2201 diagnostic_impl (&richloc, NULL, -1, gmsgid, &ap, DK_ICE_NOBT);
b55f40c1
JJ
2202 va_end (ap);
2203
2204 gcc_unreachable ();
2205}
4f01ae37
DM
2206
2207/* Emit DIAGRAM to CONTEXT, respecting the output format. */
2208
2209void
2210diagnostic_emit_diagram (diagnostic_context *context,
2211 const diagnostic_diagram &diagram)
2212{
2213 if (context->m_diagrams.m_theme == nullptr)
2214 return;
2215
2216 if (context->m_diagrams.m_emission_cb)
2217 {
2218 context->m_diagrams.m_emission_cb (context, diagram);
2219 return;
2220 }
2221
2222 /* Default implementation. */
2223 char *saved_prefix = pp_take_prefix (context->printer);
2224 pp_set_prefix (context->printer, NULL);
2225 /* Use a newline before and after and a two-space indent
2226 to make the diagram stand out a little from the wall of text. */
2227 pp_newline (context->printer);
2228 diagram.get_canvas ().print_to_pp (context->printer, " ");
2229 pp_newline (context->printer);
2230 pp_set_prefix (context->printer, saved_prefix);
2231 pp_flush (context->printer);
2232}
59650e48 2233\f
59650e48
ZW
2234/* Special case error functions. Most are implemented in terms of the
2235 above, or should be. */
e23bd218 2236
59650e48
ZW
2237/* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2238 runs its second argument through gettext. */
04c1334c 2239void
4b794eaf 2240fnotice (FILE *file, const char *cmsgid, ...)
04c1334c 2241{
e34d07f2 2242 va_list ap;
04c1334c 2243
4b794eaf
JJ
2244 va_start (ap, cmsgid);
2245 vfprintf (file, _(cmsgid), ap);
e34d07f2 2246 va_end (ap);
04c1334c
GDR
2247}
2248
59650e48
ZW
2249/* Inform the user that an error occurred while trying to report some
2250 other error. This indicates catastrophic internal inconsistencies,
2251 so give up now. But do try to flush out the previous error.
2252 This mustn't use internal_error, that will cause infinite recursion. */
2253
2254static void
79a490a9 2255error_recursion (diagnostic_context *context)
59650e48
ZW
2256{
2257 if (context->lock < 3)
f8923f7e 2258 pp_newline_and_flush (context->printer);
59650e48
ZW
2259
2260 fnotice (stderr,
76ef38e3 2261 "internal compiler error: error reporting routines re-entered.\n");
d5706a1e
ZW
2262
2263 /* Call diagnostic_action_after_output to get the "please submit a bug
c4100eae
MLI
2264 report" message. */
2265 diagnostic_action_after_output (context, DK_ICE);
d5706a1e
ZW
2266
2267 /* Do not use gcc_unreachable here; that goes through internal_error
2268 and therefore would cause infinite recursion. */
2269 real_abort ();
59650e48
ZW
2270}
2271
2272/* Report an internal compiler error in a friendly manner. This is
2273 the function that gets called upon use of abort() in the source
2274 code generally, thanks to a special macro. */
2275
2276void
79a490a9 2277fancy_abort (const char *file, int line, const char *function)
59650e48 2278{
387f6c15
DM
2279 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2280 internal_error will crash internally in a way that prevents a
2281 useful message reaching the user.
2282 This can happen with libgccjit in the case of gcc_assert failures
2283 that occur outside of the libgccjit mutex that guards the rest of
2284 gcc's state, including global_dc (when global_dc may not be
2285 initialized yet, or might be in use by another thread).
2286 Handle such cases as gracefully as possible by falling back to a
2287 minimal abort handler that only relies on i18n. */
2288 if (global_dc->printer == NULL)
2289 {
2290 /* Print the error message. */
2291 fnotice (stderr, diagnostic_kind_text[DK_ICE]);
2292 fnotice (stderr, "in %s, at %s:%d", function, trim_filename (file), line);
2293 fputc ('\n', stderr);
2294
2295 /* Attempt to print a backtrace. */
2296 struct backtrace_state *state
2297 = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
2298 int count = 0;
2299 if (state != NULL)
2300 backtrace_full (state, 2, bt_callback, bt_err_callback,
2301 (void *) &count);
2302
2303 /* We can't call warn_if_plugins or emergency_dump_function as these
2304 rely on GCC state that might not be initialized, or might be in
2305 use by another thread. */
2306
2307 /* Abort the process. */
2308 real_abort ();
2309 }
2310
59650e48
ZW
2311 internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
2312}
2313
097f82ec
DM
2314/* class auto_diagnostic_group. */
2315
2316/* Constructor: "push" this group into global_dc. */
2317
2318auto_diagnostic_group::auto_diagnostic_group ()
2319{
2320 global_dc->diagnostic_group_nesting_depth++;
2321}
2322
2323/* Destructor: "pop" this group from global_dc. */
2324
2325auto_diagnostic_group::~auto_diagnostic_group ()
2326{
2327 if (--global_dc->diagnostic_group_nesting_depth == 0)
2328 {
2329 /* Handle the case where we've popped the final diagnostic group.
2330 If any diagnostics were emitted, give the context a chance
2331 to do something. */
2332 if (global_dc->diagnostic_group_emission_count > 0)
2333 {
2334 if (global_dc->end_group_cb)
2335 global_dc->end_group_cb (global_dc);
2336 }
2337 global_dc->diagnostic_group_emission_count = 0;
2338 }
2339}
2340
5ab73173
DM
2341/* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2342 file-based output formats. */
2343
2344void
2345diagnostic_output_format_init (diagnostic_context *context,
2346 const char *base_file_name,
2347 enum diagnostics_output_format format)
2348{
2349 switch (format)
2350 {
2351 default:
2352 gcc_unreachable ();
2353 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT:
2354 /* The default; do nothing. */
2355 break;
2356
2357 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR:
2358 diagnostic_output_format_init_json_stderr (context);
2359 break;
2360
2361 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE:
2362 diagnostic_output_format_init_json_file (context, base_file_name);
2363 break;
6cf276dd
DM
2364
2365 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR:
2366 diagnostic_output_format_init_sarif_stderr (context);
2367 break;
2368
2369 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE:
2370 diagnostic_output_format_init_sarif_file (context, base_file_name);
2371 break;
5ab73173
DM
2372 }
2373}
2374
4f01ae37
DM
2375/* Initialize CONTEXT->m_diagrams based on CHARSET.
2376 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2377 (or NULL for "no diagrams"). */
2378
2379void
2380diagnostics_text_art_charset_init (diagnostic_context *context,
2381 enum diagnostic_text_art_charset charset)
2382{
2383 delete context->m_diagrams.m_theme;
2384 switch (charset)
2385 {
2386 default:
2387 gcc_unreachable ();
2388
2389 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE:
2390 context->m_diagrams.m_theme = NULL;
2391 break;
2392
2393 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII:
2394 context->m_diagrams.m_theme = new text_art::ascii_theme ();
2395 break;
2396
2397 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE:
2398 context->m_diagrams.m_theme = new text_art::unicode_theme ();
2399 break;
2400
2401 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI:
2402 context->m_diagrams.m_theme = new text_art::emoji_theme ();
2403 break;
2404 }
2405}
2406
3a1e9f3e
DM
2407/* class simple_diagnostic_path : public diagnostic_path. */
2408
2409simple_diagnostic_path::simple_diagnostic_path (pretty_printer *event_pp)
2410 : m_event_pp (event_pp)
2411{
2412 add_thread ("main");
2413}
2414
4bc1899b
DM
2415/* Implementation of diagnostic_path::num_events vfunc for
2416 simple_diagnostic_path: simply get the number of events in the vec. */
2417
2418unsigned
2419simple_diagnostic_path::num_events () const
2420{
2421 return m_events.length ();
2422}
2423
2424/* Implementation of diagnostic_path::get_event vfunc for
2425 simple_diagnostic_path: simply return the event in the vec. */
2426
2427const diagnostic_event &
2428simple_diagnostic_path::get_event (int idx) const
2429{
2430 return *m_events[idx];
2431}
2432
3a1e9f3e
DM
2433unsigned
2434simple_diagnostic_path::num_threads () const
2435{
2436 return m_threads.length ();
2437}
2438
2439const diagnostic_thread &
2440simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx) const
2441{
2442 return *m_threads[idx];
2443}
2444
2445diagnostic_thread_id_t
2446simple_diagnostic_path::add_thread (const char *name)
2447{
2448 m_threads.safe_push (new simple_diagnostic_thread (name));
2449 return m_threads.length () - 1;
2450}
2451
4bc1899b
DM
2452/* Add an event to this path at LOC within function FNDECL at
2453 stack depth DEPTH.
2454
2455 Use m_context's printer to format FMT, as the text of the new
2456 event.
2457
2458 Return the id of the new event. */
2459
2460diagnostic_event_id_t
2461simple_diagnostic_path::add_event (location_t loc, tree fndecl, int depth,
2462 const char *fmt, ...)
2463{
2464 pretty_printer *pp = m_event_pp;
2465 pp_clear_output_area (pp);
2466
2467 text_info ti;
2468 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2469
2470 va_list ap;
2471
2472 va_start (ap, fmt);
2473
2474 ti.format_spec = _(fmt);
2475 ti.args_ptr = &ap;
2476 ti.err_no = 0;
2477 ti.x_data = NULL;
2478 ti.m_richloc = &rich_loc;
2479
2480 pp_format (pp, &ti);
2481 pp_output_formatted_text (pp);
2482
2483 va_end (ap);
2484
2485 simple_diagnostic_event *new_event
2486 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp));
2487 m_events.safe_push (new_event);
2488
2489 pp_clear_output_area (pp);
2490
2491 return diagnostic_event_id_t (m_events.length () - 1);
2492}
2493
3a1e9f3e
DM
2494diagnostic_event_id_t
2495simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id,
2496 location_t loc,
2497 tree fndecl,
2498 int depth,
2499 const char *fmt, ...)
2500{
2501 pretty_printer *pp = m_event_pp;
2502 pp_clear_output_area (pp);
2503
2504 text_info ti;
2505 rich_location rich_loc (line_table, UNKNOWN_LOCATION);
2506
2507 va_list ap;
2508
2509 va_start (ap, fmt);
2510
2511 ti.format_spec = _(fmt);
2512 ti.args_ptr = &ap;
2513 ti.err_no = 0;
2514 ti.x_data = NULL;
2515 ti.m_richloc = &rich_loc;
2516
2517 pp_format (pp, &ti);
2518 pp_output_formatted_text (pp);
2519
2520 va_end (ap);
2521
2522 simple_diagnostic_event *new_event
2523 = new simple_diagnostic_event (loc, fndecl, depth, pp_formatted_text (pp),
2524 thread_id);
2525 m_events.safe_push (new_event);
2526
2527 pp_clear_output_area (pp);
2528
2529 return diagnostic_event_id_t (m_events.length () - 1);
2530}
2531
4bc1899b
DM
2532/* struct simple_diagnostic_event. */
2533
2534/* simple_diagnostic_event's ctor. */
2535
3a1e9f3e
DM
2536simple_diagnostic_event::
2537simple_diagnostic_event (location_t loc,
2538 tree fndecl,
2539 int depth,
2540 const char *desc,
2541 diagnostic_thread_id_t thread_id)
2542: m_loc (loc), m_fndecl (fndecl), m_depth (depth), m_desc (xstrdup (desc)),
2543 m_thread_id (thread_id)
4bc1899b
DM
2544{
2545}
2546
2547/* simple_diagnostic_event's dtor. */
2548
2549simple_diagnostic_event::~simple_diagnostic_event ()
2550{
2551 free (m_desc);
2552}
2553
2554/* Print PATH by emitting a dummy "note" associated with it. */
2555
2556DEBUG_FUNCTION
2557void debug (diagnostic_path *path)
2558{
2559 rich_location richloc (line_table, UNKNOWN_LOCATION);
2560 richloc.set_path (path);
2561 inform (&richloc, "debug path");
2562}
2563
886e0865
GK
2564/* Really call the system 'abort'. This has to go right at the end of
2565 this file, so that there are no functions after it that call abort
2566 and get the system abort instead of our macro. */
2567#undef abort
79a490a9
AJ
2568static void
2569real_abort (void)
886e0865
GK
2570{
2571 abort ();
2572}
a93eac6a
DM
2573
2574#if CHECKING_P
2575
2576namespace selftest {
2577
2578/* Helper function for test_print_escaped_string. */
2579
2580static void
2581assert_print_escaped_string (const location &loc, const char *expected_output,
2582 const char *input)
2583{
2584 pretty_printer pp;
2585 print_escaped_string (&pp, input);
2586 ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
2587}
2588
2589#define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2590 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2591
2592/* Tests of print_escaped_string. */
2593
2594static void
2595test_print_escaped_string ()
2596{
2597 /* Empty string. */
2598 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2599
2600 /* Non-empty string. */
2601 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2602
2603 /* Various things that need to be escaped: */
2604 /* Backslash. */
2605 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2606 "before\\after");
2607 /* Tab. */
2608 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2609 "before\tafter");
2610 /* Newline. */
2611 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2612 "before\nafter");
2613 /* Double quote. */
2614 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2615 "before\"after");
2616
2617 /* Non-printable characters: BEL: '\a': 0x07 */
2618 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2619 "before\aafter");
2620 /* Non-printable characters: vertical tab: '\v': 0x0b */
2621 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2622 "before\vafter");
2623}
2624
2625/* Tests of print_parseable_fixits. */
2626
2627/* Verify that print_parseable_fixits emits the empty string if there
2628 are no fixits. */
2629
2630static void
2631test_print_parseable_fixits_none ()
2632{
2633 pretty_printer pp;
2634 rich_location richloc (line_table, UNKNOWN_LOCATION);
2635
f1096055 2636 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
a93eac6a
DM
2637 ASSERT_STREQ ("", pp_formatted_text (&pp));
2638}
2639
2640/* Verify that print_parseable_fixits does the right thing if there
2641 is an insertion fixit hint. */
2642
2643static void
2644test_print_parseable_fixits_insert ()
2645{
2646 pretty_printer pp;
2647 rich_location richloc (line_table, UNKNOWN_LOCATION);
2648
2649 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2650 linemap_line_start (line_table, 5, 100);
2651 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2652 location_t where = linemap_position_for_column (line_table, 10);
254830ba 2653 richloc.add_fixit_insert_before (where, "added content");
a93eac6a 2654
f1096055 2655 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
a93eac6a
DM
2656 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2657 pp_formatted_text (&pp));
2658}
2659
2660/* Verify that print_parseable_fixits does the right thing if there
2661 is an removal fixit hint. */
2662
2663static void
2664test_print_parseable_fixits_remove ()
2665{
2666 pretty_printer pp;
2667 rich_location richloc (line_table, UNKNOWN_LOCATION);
2668
2669 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2670 linemap_line_start (line_table, 5, 100);
2671 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2672 source_range where;
2673 where.m_start = linemap_position_for_column (line_table, 10);
2674 where.m_finish = linemap_position_for_column (line_table, 20);
2675 richloc.add_fixit_remove (where);
2676
f1096055 2677 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
a93eac6a
DM
2678 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2679 pp_formatted_text (&pp));
2680}
2681
2682/* Verify that print_parseable_fixits does the right thing if there
2683 is an replacement fixit hint. */
2684
2685static void
2686test_print_parseable_fixits_replace ()
2687{
2688 pretty_printer pp;
2689 rich_location richloc (line_table, UNKNOWN_LOCATION);
2690
2691 linemap_add (line_table, LC_ENTER, false, "test.c", 0);
2692 linemap_line_start (line_table, 5, 100);
2693 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2694 source_range where;
2695 where.m_start = linemap_position_for_column (line_table, 10);
2696 where.m_finish = linemap_position_for_column (line_table, 20);
2697 richloc.add_fixit_replace (where, "replacement");
2698
f1096055 2699 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE, 8);
a93eac6a
DM
2700 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2701 pp_formatted_text (&pp));
2702}
2703
f1096055
DM
2704/* Verify that print_parseable_fixits correctly handles
2705 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2706
2707static void
2708test_print_parseable_fixits_bytes_vs_display_columns ()
2709{
2710 line_table_test ltt;
2711 rich_location richloc (line_table, UNKNOWN_LOCATION);
2712
2713 /* 1-based byte offsets: 12345677778888999900001234567. */
2714 const char *const content = "smile \xf0\x9f\x98\x82 colour\n";
2715 /* 1-based display cols: 123456[......7-8.....]9012345. */
2716 const int tabstop = 8;
2717
2718 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2719 const char *const fname = tmp.get_filename ();
2720
2721 linemap_add (line_table, LC_ENTER, false, fname, 0);
2722 linemap_line_start (line_table, 1, 100);
2723 linemap_add (line_table, LC_LEAVE, false, NULL, 0);
2724 source_range where;
2725 where.m_start = linemap_position_for_column (line_table, 12);
2726 where.m_finish = linemap_position_for_column (line_table, 17);
2727 richloc.add_fixit_replace (where, "color");
2728
a3128bf0
DM
2729 /* Escape fname. */
2730 pretty_printer tmp_pp;
2731 print_escaped_string (&tmp_pp, fname);
2732 char *escaped_fname = xstrdup (pp_formatted_text (&tmp_pp));
2733
2734 const int buf_len = strlen (escaped_fname) + 100;
f1096055
DM
2735 char *const expected = XNEWVEC (char, buf_len);
2736
2737 {
2738 pretty_printer pp;
2739 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_BYTE,
2740 tabstop);
2741 snprintf (expected, buf_len,
a3128bf0 2742 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname);
f1096055
DM
2743 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2744 }
2745 {
2746 pretty_printer pp;
2747 print_parseable_fixits (&pp, &richloc, DIAGNOSTICS_COLUMN_UNIT_DISPLAY,
2748 tabstop);
2749 snprintf (expected, buf_len,
a3128bf0 2750 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname);
f1096055
DM
2751 ASSERT_STREQ (expected, pp_formatted_text (&pp));
2752 }
2753
2754 XDELETEVEC (expected);
a3128bf0 2755 free (escaped_fname);
f1096055
DM
2756}
2757
ace72598
DM
2758/* Verify that
2759 diagnostic_get_location_text (..., SHOW_COLUMN)
2760 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2761 colorization disabled. */
2762
2763static void
2764assert_location_text (const char *expected_loc_text,
2765 const char *filename, int line, int column,
004bb936
LH
2766 bool show_column,
2767 int origin = 1,
2768 enum diagnostics_column_unit column_unit
2769 = DIAGNOSTICS_COLUMN_UNIT_BYTE)
ace72598
DM
2770{
2771 test_diagnostic_context dc;
2772 dc.show_column = show_column;
004bb936
LH
2773 dc.column_unit = column_unit;
2774 dc.column_origin = origin;
ace72598
DM
2775
2776 expanded_location xloc;
2777 xloc.file = filename;
2778 xloc.line = line;
2779 xloc.column = column;
2780 xloc.data = NULL;
2781 xloc.sysp = false;
2782
2783 char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
2784 ASSERT_STREQ (expected_loc_text, actual_loc_text);
2785 free (actual_loc_text);
2786}
2787
2788/* Verify that diagnostic_get_location_text works as expected. */
2789
2790static void
2791test_diagnostic_get_location_text ()
2792{
2793 const char *old_progname = progname;
2794 progname = "PROGNAME";
2795 assert_location_text ("PROGNAME:", NULL, 0, 0, true);
d6017088
JJ
2796 char *built_in_colon = concat (special_fname_builtin (), ":", (char *) 0);
2797 assert_location_text (built_in_colon, special_fname_builtin (),
2798 42, 10, true);
2799 free (built_in_colon);
ace72598 2800 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
004bb936
LH
2801 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2802 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2803 for (int origin = 0; origin != 2; ++origin)
2804 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin);
101e910b 2805 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
ace72598 2806 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
101e910b
NS
2807 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2808
2809 maybe_line_and_column (INT_MAX, INT_MAX);
2810 maybe_line_and_column (INT_MIN, INT_MIN);
2811
004bb936
LH
2812 {
2813 /* In order to test display columns vs byte columns, we need to create a
2814 file for location_get_source_line() to read. */
2815
2816 const char *const content = "smile \xf0\x9f\x98\x82\n";
2817 const int line_bytes = strlen (content) - 1;
2818 const int def_tabstop = 8;
bd5e882c
DM
2819 const cpp_char_column_policy policy (def_tabstop, cpp_wcwidth);
2820 const int display_width = cpp_display_width (content, line_bytes, policy);
004bb936
LH
2821 ASSERT_EQ (line_bytes - 2, display_width);
2822 temp_source_file tmp (SELFTEST_LOCATION, ".c", content);
2823 const char *const fname = tmp.get_filename ();
2824 const int buf_len = strlen (fname) + 16;
2825 char *const expected = XNEWVEC (char, buf_len);
2826
2827 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes);
2828 assert_location_text (expected, fname, 1, line_bytes, true,
2829 1, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2830
2831 snprintf (expected, buf_len, "%s:1:%d:", fname, line_bytes - 1);
2832 assert_location_text (expected, fname, 1, line_bytes, true,
2833 0, DIAGNOSTICS_COLUMN_UNIT_BYTE);
2834
2835 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width);
2836 assert_location_text (expected, fname, 1, line_bytes, true,
2837 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2838
2839 snprintf (expected, buf_len, "%s:1:%d:", fname, display_width - 1);
2840 assert_location_text (expected, fname, 1, line_bytes, true,
2841 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY);
2842
2843 XDELETEVEC (expected);
2844 }
2845
2846
ace72598
DM
2847 progname = old_progname;
2848}
2849
bc65bad2
MG
2850/* Selftest for num_digits. */
2851
2852static void
2853test_num_digits ()
2854{
2855 ASSERT_EQ (1, num_digits (0));
2856 ASSERT_EQ (1, num_digits (9));
2857 ASSERT_EQ (2, num_digits (10));
2858 ASSERT_EQ (2, num_digits (99));
2859 ASSERT_EQ (3, num_digits (100));
2860 ASSERT_EQ (3, num_digits (999));
2861 ASSERT_EQ (4, num_digits (1000));
2862 ASSERT_EQ (4, num_digits (9999));
2863 ASSERT_EQ (5, num_digits (10000));
2864 ASSERT_EQ (5, num_digits (99999));
2865 ASSERT_EQ (6, num_digits (100000));
2866 ASSERT_EQ (6, num_digits (999999));
2867 ASSERT_EQ (7, num_digits (1000000));
2868 ASSERT_EQ (7, num_digits (9999999));
2869 ASSERT_EQ (8, num_digits (10000000));
2870 ASSERT_EQ (8, num_digits (99999999));
2871}
2872
a93eac6a
DM
2873/* Run all of the selftests within this file. */
2874
2875void
98152442 2876c_diagnostic_cc_tests ()
a93eac6a
DM
2877{
2878 test_print_escaped_string ();
2879 test_print_parseable_fixits_none ();
2880 test_print_parseable_fixits_insert ();
2881 test_print_parseable_fixits_remove ();
2882 test_print_parseable_fixits_replace ();
f1096055 2883 test_print_parseable_fixits_bytes_vs_display_columns ();
ace72598 2884 test_diagnostic_get_location_text ();
bc65bad2
MG
2885 test_num_digits ();
2886
a93eac6a
DM
2887}
2888
2889} // namespace selftest
2890
2891#endif /* #if CHECKING_P */
0ecf545c
MS
2892
2893#if __GNUC__ >= 10
2894# pragma GCC diagnostic pop
2895#endif