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