1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2023 Free Software Foundation, Inc.
3 Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
22 /* This file implements the language independent aspect of diagnostic
26 #define INCLUDE_VECTOR
28 #include "coretypes.h"
32 #include "backtrace.h"
33 #include "diagnostic.h"
34 #include "diagnostic-color.h"
35 #include "diagnostic-url.h"
36 #include "diagnostic-metadata.h"
37 #include "diagnostic-path.h"
38 #include "diagnostic-client-data-hooks.h"
39 #include "diagnostic-diagram.h"
40 #include "edit-context.h"
42 #include "selftest-diagnostic.h"
45 #include "text-art/theme.h"
46 #include "pretty-print-urlifier.h"
52 #ifdef GWINSZ_IN_SYS_IOCTL
53 # include <sys/ioctl.h>
56 /* Disable warnings about quoting issues in the pp_xxx calls below
57 that (intentionally) don't follow GCC diagnostic conventions. */
59 # pragma GCC diagnostic push
60 # pragma GCC diagnostic ignored "-Wformat-diag"
63 #define pedantic_warning_kind(DC) \
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)
69 static bool diagnostic_impl (rich_location
*, const diagnostic_metadata
*,
71 va_list *, diagnostic_t
) ATTRIBUTE_GCC_DIAG(4,0);
72 static bool diagnostic_n_impl (rich_location
*, const diagnostic_metadata
*,
73 int, unsigned HOST_WIDE_INT
,
74 const char *, const char *, va_list *,
75 diagnostic_t
) ATTRIBUTE_GCC_DIAG(6,0);
77 static void real_abort (void) ATTRIBUTE_NORETURN
;
79 /* Name of program invoked, sans directories. */
83 /* A diagnostic_context surrogate for stderr. */
84 static diagnostic_context global_diagnostic_context
;
85 diagnostic_context
*global_dc
= &global_diagnostic_context
;
87 /* Return a malloc'd string containing MSG formatted a la printf. The
88 caller is responsible for freeing the memory. */
90 build_message_string (const char *msg
, ...)
96 str
= xvasprintf (msg
, ap
);
102 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
104 file_name_as_prefix (diagnostic_context
*context
, const char *f
)
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
);
114 /* Return the value of the getenv("COLUMNS") as an integer. If the
115 value is not set to a positive integer, use ioctl to get the
116 terminal width. If it fails, return INT_MAX. */
118 get_terminal_width (void)
120 const char * s
= getenv ("COLUMNS");
130 if (ioctl (0, TIOCGWINSZ
, &w
) == 0 && w
.ws_col
> 0)
137 /* Set caret_max_width to value. */
139 diagnostic_set_caret_max_width (diagnostic_context
*context
, int value
)
141 /* One minus to account for the leading empty space. */
142 value
= value
? value
- 1
143 : (isatty (fileno (pp_buffer (context
->printer
)->stream
))
144 ? get_terminal_width () - 1: INT_MAX
);
149 context
->m_source_printing
.max_width
= value
;
153 diagnostic_option_classifier::init (int 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;
164 diagnostic_option_classifier::fini ()
166 XDELETEVEC (m_classify_diagnostic
);
167 m_classify_diagnostic
= nullptr;
172 /* Save all diagnostic classifications in a stack. */
175 diagnostic_option_classifier::push ()
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
;
181 /* Restore the topmost classification set off the stack. If the stack
182 is empty, revert to the state based on command line parameters. */
185 diagnostic_option_classifier::pop (location_t where
)
190 jump_to
= m_push_list
[-- m_n_push
];
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
++;
204 /* Initialize the diagnostic message outputting machinery. */
207 diagnostic_context::initialize (int n_opts
)
209 /* Allocate a basic pretty-printer. Clients will replace this a
210 much more elaborated pretty-printer if they wish. */
211 this->printer
= XNEW (pretty_printer
);
212 new (this->printer
) pretty_printer ();
214 m_file_cache
= new file_cache ();
215 memset (m_diagnostic_count
, 0, sizeof m_diagnostic_count
);
216 m_warning_as_error_requested
= false;
218 m_option_classifier
.init (n_opts
);
219 m_source_printing
.enabled
= false;
220 diagnostic_set_caret_max_width (this, pp_line_cutoff (this->printer
));
221 for (int i
= 0; i
< rich_location::STATICALLY_ALLOCATED_RANGES
; i
++)
222 m_source_printing
.caret_chars
[i
] = '^';
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;
237 m_internal_error
= nullptr;
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
;
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;
245 m_urlifier
= nullptr;
246 m_last_location
= UNKNOWN_LOCATION
;
247 m_last_module
= nullptr;
248 m_client_aux_data
= nullptr;
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
;
258 if (const char *var
= getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
260 if (!strcmp (var
, "fixits-v1"))
261 m_extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
;
262 else if (!strcmp (var
, "fixits-v2"))
263 m_extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
;
264 /* Silently ignore unrecognized values. */
266 m_column_unit
= DIAGNOSTICS_COLUMN_UNIT_DISPLAY
;
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;
280 enum diagnostic_text_art_charset text_art_charset
281 = DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
;
282 if (const char *lang
= getenv ("LANG"))
284 /* For LANG=C, don't assume the terminal supports anything
286 if (!strcmp (lang
, "C"))
287 text_art_charset
= DIAGNOSTICS_TEXT_ART_CHARSET_ASCII
;
289 set_text_art_charset (text_art_charset
);
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. */
297 diagnostic_context::color_init (int value
)
299 /* value == -1 is the default value. */
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)
309 if (!getenv ("GCC_COLORS"))
311 value
= DIAGNOSTICS_COLOR_AUTO
;
314 value
= DIAGNOSTICS_COLOR_DEFAULT
;
316 pp_show_color (this->printer
)
317 = colorize_init ((diagnostic_color_rule_t
) value
);
320 /* Initialize URL support within this context based on VALUE,
324 diagnostic_context::urls_init (int value
)
326 /* value == -1 is the default value. */
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)
336 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
338 value
= DIAGNOSTICS_URL_AUTO
;
341 value
= DIAGNOSTICS_URLS_DEFAULT
;
344 this->printer
->url_format
345 = determine_url_format ((diagnostic_url_rule_t
) value
);
348 /* Create the file_cache, if not already created, and tell it how to
349 translate files on input. */
352 initialize_input_context (diagnostic_input_charset_callback ccb
,
353 bool should_skip_bom
)
355 m_file_cache
->initialize_input_context (ccb
, should_skip_bom
);
358 /* Do any cleaning up required after the last diagnostic is emitted. */
361 diagnostic_context::finish ()
363 delete m_output_format
;
364 m_output_format
= nullptr;
366 if (m_diagrams
.m_theme
)
368 delete m_diagrams
.m_theme
;
369 m_diagrams
.m_theme
= nullptr;
373 m_file_cache
= nullptr;
375 m_option_classifier
.fini ();
377 /* diagnostic_context::initialize allocates this->printer using XNEW
378 and placement-new. */
379 this->printer
->~pretty_printer ();
380 XDELETE (this->printer
);
381 this->printer
= nullptr;
383 if (m_edit_context_ptr
)
385 delete m_edit_context_ptr
;
386 m_edit_context_ptr
= nullptr;
391 delete m_includes_seen
;
392 m_includes_seen
= nullptr;
395 if (m_client_data_hooks
)
397 delete m_client_data_hooks
;
398 m_client_data_hooks
= nullptr;
402 m_urlifier
= nullptr;
406 diagnostic_context::set_output_format (diagnostic_output_format
*output_format
)
408 /* Ideally we'd use a std::unique_ptr here. */
409 delete m_output_format
;
410 m_output_format
= output_format
;
414 diagnostic_context::set_client_data_hooks (diagnostic_client_data_hooks
*hooks
)
416 /* Ideally we'd use a std::unique_ptr here. */
417 delete m_client_data_hooks
;
418 m_client_data_hooks
= hooks
;
423 set_option_hooks (diagnostic_option_enabled_cb option_enabled_cb
,
425 diagnostic_make_option_name_cb make_option_name_cb
,
426 diagnostic_make_option_url_cb make_option_url_cb
,
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
;
433 m_option_callbacks
.m_lang_mask
= lang_mask
;
437 diagnostic_context::set_urlifier (urlifier
*urlifier
)
439 /* Ideally we'd use a std::unique_ptr here. */
441 m_urlifier
= urlifier
;
445 diagnostic_context::create_edit_context ()
447 delete m_edit_context_ptr
;
448 gcc_assert (m_file_cache
);
449 m_edit_context_ptr
= new edit_context (*m_file_cache
);
452 /* Initialize DIAGNOSTIC, where the message MSG has already been
455 diagnostic_set_info_translated (diagnostic_info
*diagnostic
, const char *msg
,
456 va_list *args
, rich_location
*richloc
,
459 gcc_assert (richloc
);
460 diagnostic
->message
.m_err_no
= errno
;
461 diagnostic
->message
.m_args_ptr
= args
;
462 diagnostic
->message
.m_format_spec
= msg
;
463 diagnostic
->message
.m_richloc
= richloc
;
464 diagnostic
->richloc
= richloc
;
465 diagnostic
->metadata
= NULL
;
466 diagnostic
->kind
= kind
;
467 diagnostic
->option_index
= 0;
470 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
473 diagnostic_set_info (diagnostic_info
*diagnostic
, const char *gmsgid
,
474 va_list *args
, rich_location
*richloc
,
477 gcc_assert (richloc
);
478 diagnostic_set_info_translated (diagnostic
, _(gmsgid
), args
, richloc
, kind
);
481 static const char *const diagnostic_kind_color
[] = {
482 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
483 #include "diagnostic.def"
484 #undef DEFINE_DIAGNOSTIC_KIND
488 /* Get a color name for diagnostics of type KIND
489 Result could be NULL. */
492 diagnostic_get_color_for_kind (diagnostic_t kind
)
494 return diagnostic_kind_color
[kind
];
497 /* Given an expanded_location, convert the column (which is in 1-based bytes)
498 to the requested units, without converting the origin.
499 Return -1 if the column is invalid (<= 0). */
502 convert_column_unit (file_cache
&fc
,
503 enum diagnostics_column_unit column_unit
,
515 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY
:
517 cpp_char_column_policy
policy (tabstop
, cpp_wcwidth
);
518 return location_compute_display_column (fc
, s
, policy
);
521 case DIAGNOSTICS_COLUMN_UNIT_BYTE
:
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
530 diagnostic_context::converted_column (expanded_location s
) const
532 int one_based_col
= convert_column_unit (get_file_cache (),
533 m_column_unit
, m_tabstop
, s
);
534 if (one_based_col
<= 0)
536 return one_based_col
+ (m_column_origin
- 1);
539 /* Return a formatted line and column ':%line:%column'. Elided if
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. */
545 maybe_line_and_column (int line
, int col
)
547 static char result
[32];
552 = snprintf (result
, sizeof (result
),
553 col
>= 0 ? ":%d:%d" : ":%d", line
, col
);
554 gcc_checking_assert (l
< sizeof (result
));
561 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
562 The caller is responsible for freeing the memory. */
565 diagnostic_get_location_text (diagnostic_context
*context
,
568 pretty_printer
*pp
= context
->printer
;
569 const char *locus_cs
= colorize_start (pp_show_color (pp
), "locus");
570 const char *locus_ce
= colorize_stop (pp_show_color (pp
));
571 const char *file
= s
.file
? s
.file
: progname
;
574 if (strcmp (file
, special_fname_builtin ()))
577 if (context
->m_show_column
)
578 col
= context
->converted_column (s
);
581 const char *line_col
= maybe_line_and_column (line
, col
);
582 return build_message_string ("%s%s%s:%s", locus_cs
, file
,
586 static const char *const diagnostic_kind_text
[] = {
587 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
588 #include "diagnostic.def"
589 #undef DEFINE_DIAGNOSTIC_KIND
593 /* Return a malloc'd string describing a location and the severity of the
594 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
595 freeing the memory. */
597 diagnostic_build_prefix (diagnostic_context
*context
,
598 const diagnostic_info
*diagnostic
)
600 gcc_assert (diagnostic
->kind
< DK_LAST_DIAGNOSTIC_KIND
);
602 const char *text
= _(diagnostic_kind_text
[diagnostic
->kind
]);
603 const char *text_cs
= "", *text_ce
= "";
604 pretty_printer
*pp
= context
->printer
;
606 if (diagnostic_kind_color
[diagnostic
->kind
])
608 text_cs
= colorize_start (pp_show_color (pp
),
609 diagnostic_kind_color
[diagnostic
->kind
]);
610 text_ce
= colorize_stop (pp_show_color (pp
));
613 expanded_location s
= diagnostic_expand_location (diagnostic
);
614 char *location_text
= diagnostic_get_location_text (context
, s
);
616 char *result
= build_message_string ("%s %s%s%s", location_text
,
617 text_cs
, text
, text_ce
);
618 free (location_text
);
622 /* Functions at which to stop the backtrace print. It's not
623 particularly helpful to print the callers of these functions. */
625 static const char * const bt_stop
[] =
633 /* A callback function passed to the backtrace_full function. */
636 bt_callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
637 const char *function
)
639 int *pcount
= (int *) data
;
641 /* If we don't have any useful information, don't print
643 if (filename
== NULL
&& function
== NULL
)
646 /* Skip functions in diagnostic.cc. */
649 && strcmp (lbasename (filename
), "diagnostic.cc") == 0)
652 /* Print up to 20 functions. We could make this a --param, but
653 since this is only for debugging just use a constant for now. */
656 /* Returning a non-zero value stops the backtrace. */
662 if (function
!= NULL
)
664 char *str
= cplus_demangle_v3 (function
,
665 (DMGL_VERBOSE
| DMGL_ANSI
666 | DMGL_GNU_V3
| DMGL_PARAMS
));
673 for (size_t i
= 0; i
< ARRAY_SIZE (bt_stop
); ++i
)
675 size_t len
= strlen (bt_stop
[i
]);
676 if (strncmp (function
, bt_stop
[i
], len
) == 0
677 && (function
[len
] == '\0' || function
[len
] == '('))
681 /* Returning a non-zero value stops the backtrace. */
687 fprintf (stderr
, "0x%lx %s\n\t%s:%d\n",
689 function
== NULL
? "???" : function
,
690 filename
== NULL
? "???" : filename
,
699 /* A callback function passed to the backtrace_full function. This is
700 called if backtrace_full has an error. */
703 bt_err_callback (void *data ATTRIBUTE_UNUSED
, const char *msg
, int errnum
)
707 /* This means that no debug info was available. Just quietly
708 skip printing backtrace info. */
711 fprintf (stderr
, "%s%s%s\n", msg
, errnum
== 0 ? "" : ": ",
712 errnum
== 0 ? "" : xstrerror (errnum
));
715 /* Check if we've met the maximum error limit, and if so fatally exit
717 FLUSH indicates whether a diagnostic_context::finish call is needed. */
720 diagnostic_context::check_max_errors (bool flush
)
725 int count
= (m_diagnostic_count
[DK_ERROR
]
726 + m_diagnostic_count
[DK_SORRY
]
727 + m_diagnostic_count
[DK_WERROR
]);
729 if (count
>= m_max_errors
)
732 "compilation terminated due to -fmax-errors=%u.\n",
736 exit (FATAL_EXIT_CODE
);
740 /* Take any action which is expected to happen after the diagnostic
741 is written out. This function does not always return. */
743 diagnostic_context::action_after_output (diagnostic_t diag_kind
)
755 if (m_abort_on_error
)
759 fnotice (stderr
, "compilation terminated due to -Wfatal-errors.\n");
761 exit (FATAL_EXIT_CODE
);
768 /* Optional callback for attempting to handle ICEs gracefully. */
769 if (void (*ice_handler_cb
) (diagnostic_context
*) = m_ice_handler_cb
)
771 /* Clear the callback, to avoid potentially re-entering
772 the routine if there's a crash within the handler. */
773 m_ice_handler_cb
= NULL
;
774 ice_handler_cb (this);
776 /* The context might have had diagnostic_finish called on
779 struct backtrace_state
*state
= NULL
;
780 if (diag_kind
== DK_ICE
)
781 state
= backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
784 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
787 if (m_abort_on_error
)
791 fnotice (stderr
, "Please submit a full bug report, "
792 "with preprocessed source.\n");
794 fnotice (stderr
, "Please submit a full bug report, "
795 "with preprocessed source (by using -freport-bug).\n");
798 fnotice (stderr
, "Please include the complete backtrace "
799 "with any bug report.\n");
800 fnotice (stderr
, "See %s for instructions.\n", bug_report_url
);
802 exit (ICE_EXIT_CODE
);
806 if (m_abort_on_error
)
809 fnotice (stderr
, "compilation terminated.\n");
810 exit (FATAL_EXIT_CODE
);
817 /* Only dump the "In file included from..." stack once for each file. */
820 diagnostic_context::includes_seen_p (const line_map_ordinary
*map
)
822 /* No include path for main. */
823 if (MAIN_FILE_P (map
))
826 /* Always identify C++ modules, at least for now. */
828 if (linemap_check_ordinary (map
)->reason
== LC_RENAME
)
829 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
830 probe
= linemap_included_from_linemap (line_table
, map
);
831 if (MAP_MODULE_P (probe
))
834 if (!m_includes_seen
)
835 m_includes_seen
= new hash_set
<location_t
, false, location_hash
>;
837 /* Hash the location of the #include directive to better handle files
838 that are included multiple times with different macros defined. */
839 return m_includes_seen
->add (linemap_included_from (map
));
843 diagnostic_context::report_current_module (location_t where
)
845 const line_map_ordinary
*map
= NULL
;
847 if (pp_needs_newline (this->printer
))
849 pp_newline (this->printer
);
850 pp_needs_newline (this->printer
) = false;
853 if (where
<= BUILTINS_LOCATION
)
856 linemap_resolve_location (line_table
, where
,
857 LRK_MACRO_DEFINITION_LOCATION
,
860 if (map
&& m_last_module
!= map
)
863 if (!includes_seen_p (map
))
865 bool first
= true, need_inc
= true, was_module
= MAP_MODULE_P (map
);
866 expanded_location s
= {};
869 where
= linemap_included_from (map
);
870 map
= linemap_included_from_linemap (line_table
, map
);
871 bool is_module
= MAP_MODULE_P (map
);
872 s
.file
= LINEMAP_FILE (map
);
873 s
.line
= SOURCE_LINE (map
, where
);
875 if (first
&& m_show_column
)
877 s
.column
= SOURCE_COLUMN (map
, where
);
878 col
= converted_column (s
);
880 const char *line_col
= maybe_line_and_column (s
.line
, col
);
881 static const char *const msgs
[] =
885 N_("In file included from"), /* 2 */
886 N_(" included from"),
887 N_("In module"), /* 4 */
889 N_("In module imported at"), /* 6 */
893 unsigned index
= (was_module
? 6 : is_module
? 4
894 : need_inc
? 2 : 0) + !first
;
896 pp_verbatim (this->printer
, "%s%s %r%s%s%R",
897 first
? "" : was_module
? ", " : ",\n",
899 "locus", s
.file
, line_col
);
900 first
= false, need_inc
= was_module
, was_module
= is_module
;
902 while (!includes_seen_p (map
));
903 pp_verbatim (this->printer
, ":");
904 pp_newline (this->printer
);
909 /* If DIAGNOSTIC has a diagnostic_path and this context supports
910 printing paths, print the path. */
913 diagnostic_context::show_any_path (const diagnostic_info
&diagnostic
)
915 const diagnostic_path
*path
= diagnostic
.richloc
->get_path ();
920 m_print_path (this, path
);
923 /* class diagnostic_event. */
925 /* struct diagnostic_event::meaning. */
928 diagnostic_event::meaning::dump_to_pp (pretty_printer
*pp
) const
930 bool need_comma
= false;
931 pp_character (pp
, '{');
932 if (const char *verb_str
= maybe_get_verb_str (m_verb
))
934 pp_printf (pp
, "verb: %qs", verb_str
);
937 if (const char *noun_str
= maybe_get_noun_str (m_noun
))
940 pp_string (pp
, ", ");
941 pp_printf (pp
, "noun: %qs", noun_str
);
944 if (const char *property_str
= maybe_get_property_str (m_property
))
947 pp_string (pp
, ", ");
948 pp_printf (pp
, "property: %qs", property_str
);
951 pp_character (pp
, '}');
954 /* Get a string (or NULL) for V suitable for use within a SARIF
955 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
958 diagnostic_event::meaning::maybe_get_verb_str (enum verb v
)
985 /* Get a string (or NULL) for N suitable for use within a SARIF
986 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
989 diagnostic_event::meaning::maybe_get_noun_str (enum noun n
)
1012 /* Get a string (or NULL) for P suitable for use within a SARIF
1013 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
1016 diagnostic_event::meaning::maybe_get_property_str (enum property p
)
1022 case PROPERTY_unknown
:
1026 case PROPERTY_false
:
1031 /* class diagnostic_path. */
1033 /* Subroutint of diagnostic_path::interprocedural_p.
1034 Look for the first event in this path that is within a function
1035 i.e. has a non-NULL fndecl, and a non-zero stack depth.
1036 If found, write its index to *OUT_IDX and return true.
1037 Otherwise return false. */
1040 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx
) const
1042 const unsigned num
= num_events ();
1043 for (unsigned i
= 0; i
< num
; i
++)
1045 if (!(get_event (i
).get_fndecl () == NULL
1046 && get_event (i
).get_stack_depth () == 0))
1055 /* Return true if the events in this path involve more than one
1056 function, or false if it is purely intraprocedural. */
1059 diagnostic_path::interprocedural_p () const
1061 /* Ignore leading events that are outside of any function. */
1062 unsigned first_fn_event_idx
;
1063 if (!get_first_event_in_a_function (&first_fn_event_idx
))
1066 const diagnostic_event
&first_fn_event
= get_event (first_fn_event_idx
);
1067 tree first_fndecl
= first_fn_event
.get_fndecl ();
1068 int first_fn_stack_depth
= first_fn_event
.get_stack_depth ();
1070 const unsigned num
= num_events ();
1071 for (unsigned i
= first_fn_event_idx
+ 1; i
< num
; i
++)
1073 if (get_event (i
).get_fndecl () != first_fndecl
)
1075 if (get_event (i
).get_stack_depth () != first_fn_stack_depth
)
1082 default_diagnostic_starter (diagnostic_context
*context
,
1083 diagnostic_info
*diagnostic
)
1085 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
1086 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
1091 default_diagnostic_start_span_fn (diagnostic_context
*context
,
1092 expanded_location exploc
)
1094 char *text
= diagnostic_get_location_text (context
, exploc
);
1095 pp_string (context
->printer
, text
);
1097 pp_newline (context
->printer
);
1101 default_diagnostic_finalizer (diagnostic_context
*context
,
1102 diagnostic_info
*diagnostic
,
1105 char *saved_prefix
= pp_take_prefix (context
->printer
);
1106 pp_set_prefix (context
->printer
, NULL
);
1107 pp_newline (context
->printer
);
1108 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
1109 pp_set_prefix (context
->printer
, saved_prefix
);
1110 pp_flush (context
->printer
);
1113 /* Interface to specify diagnostic kind overrides. Returns the
1114 previous setting, or DK_UNSPECIFIED if the parameters are out of
1115 range. If OPTION_INDEX is zero, the new setting is for all the
1118 diagnostic_option_classifier::
1119 classify_diagnostic (const diagnostic_context
*context
,
1121 diagnostic_t new_kind
,
1124 diagnostic_t old_kind
;
1126 if (option_index
< 0
1127 || option_index
>= m_n_opts
1128 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
1129 return DK_UNSPECIFIED
;
1131 old_kind
= m_classify_diagnostic
[option_index
];
1133 /* Handle pragmas separately, since we need to keep track of *where*
1134 the pragmas were. */
1135 if (where
!= UNKNOWN_LOCATION
)
1139 /* Record the command-line status, so we can reset it back on DK_POP. */
1140 if (old_kind
== DK_UNSPECIFIED
)
1142 old_kind
= !context
->option_enabled_p (option_index
)
1143 ? DK_IGNORED
: (context
->warning_as_error_requested_p ()
1144 ? DK_ERROR
: DK_WARNING
);
1145 m_classify_diagnostic
[option_index
] = old_kind
;
1148 for (i
= m_n_classification_history
- 1; i
>= 0; i
--)
1149 if (m_classification_history
[i
].option
== option_index
)
1151 old_kind
= m_classification_history
[i
].kind
;
1155 i
= m_n_classification_history
;
1156 m_classification_history
=
1157 (diagnostic_classification_change_t
*) xrealloc (m_classification_history
, (i
+ 1)
1158 * sizeof (diagnostic_classification_change_t
));
1159 m_classification_history
[i
].location
= where
;
1160 m_classification_history
[i
].option
= option_index
;
1161 m_classification_history
[i
].kind
= new_kind
;
1162 m_n_classification_history
++;
1165 m_classify_diagnostic
[option_index
] = new_kind
;
1170 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1171 escaping rules for -fdiagnostics-parseable-fixits. */
1174 print_escaped_string (pretty_printer
*pp
, const char *text
)
1179 pp_character (pp
, '"');
1180 for (const char *ch
= text
; *ch
; ch
++)
1185 /* Escape backslash as two backslashes. */
1186 pp_string (pp
, "\\\\");
1189 /* Escape tab as "\t". */
1190 pp_string (pp
, "\\t");
1193 /* Escape newline as "\n". */
1194 pp_string (pp
, "\\n");
1197 /* Escape doublequotes as \". */
1198 pp_string (pp
, "\\\"");
1202 pp_character (pp
, *ch
);
1204 /* Use octal for non-printable chars. */
1206 unsigned char c
= (*ch
& 0xff);
1207 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
1212 pp_character (pp
, '"');
1215 /* Implementation of -fdiagnostics-parseable-fixits and
1216 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1217 Print a machine-parseable version of all fixits in RICHLOC to PP,
1218 using COLUMN_UNIT to express columns.
1219 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1222 print_parseable_fixits (file_cache
&fc
,
1223 pretty_printer
*pp
, rich_location
*richloc
,
1224 enum diagnostics_column_unit column_unit
,
1228 gcc_assert (richloc
);
1230 char *saved_prefix
= pp_take_prefix (pp
);
1231 pp_set_prefix (pp
, NULL
);
1233 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
1235 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
1236 location_t start_loc
= hint
->get_start_loc ();
1237 expanded_location start_exploc
= expand_location (start_loc
);
1238 pp_string (pp
, "fix-it:");
1239 print_escaped_string (pp
, start_exploc
.file
);
1240 /* For compatibility with clang, print as a half-open range. */
1241 location_t next_loc
= hint
->get_next_loc ();
1242 expanded_location next_exploc
= expand_location (next_loc
);
1244 = convert_column_unit (fc
, column_unit
, tabstop
, start_exploc
);
1246 = convert_column_unit (fc
, column_unit
, tabstop
, next_exploc
);
1247 pp_printf (pp
, ":{%i:%i-%i:%i}:",
1248 start_exploc
.line
, start_col
,
1249 next_exploc
.line
, next_col
);
1250 print_escaped_string (pp
, hint
->get_string ());
1254 pp_set_prefix (pp
, saved_prefix
);
1257 /* Update the inlining info in this context for a DIAGNOSTIC. */
1260 diagnostic_context::get_any_inlining_info (diagnostic_info
*diagnostic
)
1262 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1264 if (m_set_locations_cb
)
1265 /* Retrieve the locations into which the expression about to be
1266 diagnosed has been inlined, including those of all the callers
1267 all the way down the inlining stack. */
1268 m_set_locations_cb (this, diagnostic
);
1271 /* When there's no callback use just the one location provided
1272 by the caller of the diagnostic function. */
1273 location_t loc
= diagnostic_location (diagnostic
);
1274 ilocs
.safe_push (loc
);
1275 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1279 /* Update the kind of DIAGNOSTIC based on its location(s), including
1280 any of those in its inlining stack, relative to any
1281 #pragma GCC diagnostic
1282 directives recorded within this object.
1284 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1288 diagnostic_option_classifier::
1289 update_effective_level_from_pragmas (diagnostic_info
*diagnostic
) const
1291 if (m_n_classification_history
<= 0)
1292 return DK_UNSPECIFIED
;
1294 /* Iterate over the locations, checking the diagnostic disposition
1295 for the diagnostic at each. If it's explicitly set as opposed
1296 to unspecified, update the disposition for this instance of
1297 the diagnostic and return it. */
1298 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1300 /* FIXME: Stupid search. Optimize later. */
1301 for (int i
= m_n_classification_history
- 1; i
>= 0; i
--)
1303 const diagnostic_classification_change_t
&hist
1304 = m_classification_history
[i
];
1306 location_t pragloc
= hist
.location
;
1307 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1310 if (hist
.kind
== (int) DK_POP
)
1312 /* Move on to the next region. */
1317 int option
= hist
.option
;
1318 /* The option 0 is for all the diagnostics. */
1319 if (option
== 0 || option
== diagnostic
->option_index
)
1321 diagnostic_t kind
= hist
.kind
;
1322 if (kind
!= DK_UNSPECIFIED
)
1323 diagnostic
->kind
= kind
;
1329 return DK_UNSPECIFIED
;
1332 /* Generate a URL string describing CWE. The caller is responsible for
1333 freeing the string. */
1336 get_cwe_url (int cwe
)
1338 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1341 /* If DIAGNOSTIC has a CWE identifier, print it.
1343 For example, if the diagnostic metadata associates it with CWE-119,
1344 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1345 description of the security issue. */
1348 diagnostic_context::print_any_cwe (const diagnostic_info
&diagnostic
)
1350 if (diagnostic
.metadata
== NULL
)
1353 int cwe
= diagnostic
.metadata
->get_cwe ();
1356 pretty_printer
* const pp
= this->printer
;
1357 char *saved_prefix
= pp_take_prefix (pp
);
1358 pp_string (pp
, " [");
1359 pp_string (pp
, colorize_start (pp_show_color (pp
),
1360 diagnostic_kind_color
[diagnostic
.kind
]));
1361 if (pp
->url_format
!= URL_FORMAT_NONE
)
1363 char *cwe_url
= get_cwe_url (cwe
);
1364 pp_begin_url (pp
, cwe_url
);
1367 pp_printf (pp
, "CWE-%i", cwe
);
1368 pp_set_prefix (pp
, saved_prefix
);
1369 if (pp
->url_format
!= URL_FORMAT_NONE
)
1371 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1372 pp_character (pp
, ']');
1376 /* If DIAGNOSTIC has any rules associated with it, print them.
1378 For example, if the diagnostic metadata associates it with a rule
1379 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1380 with any URL provided by the rule. */
1383 diagnostic_context::print_any_rules (const diagnostic_info
&diagnostic
)
1385 if (diagnostic
.metadata
== NULL
)
1388 for (unsigned idx
= 0; idx
< diagnostic
.metadata
->get_num_rules (); idx
++)
1390 const diagnostic_metadata::rule
&rule
1391 = diagnostic
.metadata
->get_rule (idx
);
1392 if (char *desc
= rule
.make_description ())
1394 pretty_printer
* const pp
= this->printer
;
1395 char *saved_prefix
= pp_take_prefix (pp
);
1396 pp_string (pp
, " [");
1398 colorize_start (pp_show_color (pp
),
1399 diagnostic_kind_color
[diagnostic
.kind
]));
1401 if (pp
->url_format
!= URL_FORMAT_NONE
)
1403 url
= rule
.make_url ();
1405 pp_begin_url (pp
, url
);
1407 pp_string (pp
, desc
);
1408 pp_set_prefix (pp
, saved_prefix
);
1409 if (pp
->url_format
!= URL_FORMAT_NONE
)
1413 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1414 pp_character (pp
, ']');
1420 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1421 printer, e.g. " [-Werror=uninitialized]".
1422 Subroutine of diagnostic_context::report_diagnostic. */
1425 diagnostic_context::print_option_information (const diagnostic_info
&diagnostic
,
1426 diagnostic_t orig_diag_kind
)
1428 if (char *option_text
= make_option_name (diagnostic
.option_index
,
1429 orig_diag_kind
, diagnostic
.kind
))
1431 char *option_url
= nullptr;
1432 if (this->printer
->url_format
!= URL_FORMAT_NONE
)
1433 option_url
= make_option_url (diagnostic
.option_index
);
1434 pretty_printer
* const pp
= this->printer
;
1435 pp_string (pp
, " [");
1436 pp_string (pp
, colorize_start (pp_show_color (pp
),
1437 diagnostic_kind_color
[diagnostic
.kind
]));
1439 pp_begin_url (pp
, option_url
);
1440 pp_string (pp
, option_text
);
1446 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1447 pp_character (pp
, ']');
1452 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1453 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1456 diagnostic_context::diagnostic_enabled (diagnostic_info
*diagnostic
)
1458 /* Update the inlining stack for this diagnostic. */
1459 get_any_inlining_info (diagnostic
);
1461 /* Diagnostics with no option or -fpermissive are always enabled. */
1462 if (!diagnostic
->option_index
1463 || diagnostic
->option_index
== permissive_error_option (this))
1466 /* This tests if the user provided the appropriate -Wfoo or
1468 if (!option_enabled_p (diagnostic
->option_index
))
1471 /* This tests for #pragma diagnostic changes. */
1472 diagnostic_t diag_class
1473 = m_option_classifier
.update_effective_level_from_pragmas (diagnostic
);
1475 /* This tests if the user provided the appropriate -Werror=foo
1477 if (diag_class
== DK_UNSPECIFIED
1478 && !option_unspecified_p (diagnostic
->option_index
))
1479 diagnostic
->kind
= m_option_classifier
.get_current_override (diagnostic
->option_index
);
1481 /* This allows for future extensions, like temporarily disabling
1482 warnings for ranges of source code. */
1483 if (diagnostic
->kind
== DK_IGNORED
)
1489 /* Returns whether warning OPT is enabled at LOC. */
1492 diagnostic_context::warning_enabled_at (location_t loc
, int opt
)
1494 if (!diagnostic_report_warnings_p (this, loc
))
1497 rich_location
richloc (line_table
, loc
);
1498 diagnostic_info diagnostic
= {};
1499 diagnostic
.option_index
= opt
;
1500 diagnostic
.richloc
= &richloc
;
1501 diagnostic
.message
.m_richloc
= &richloc
;
1502 diagnostic
.kind
= DK_WARNING
;
1503 return diagnostic_enabled (&diagnostic
);
1506 /* Report a diagnostic message (an error or a warning) as specified by
1507 this diagnostic_context.
1508 front-end independent format specifiers are exactly those described
1509 in the documentation of output_format.
1510 Return true if a diagnostic was printed, false otherwise. */
1513 diagnostic_context::report_diagnostic (diagnostic_info
*diagnostic
)
1515 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1517 gcc_assert (m_output_format
);
1519 /* Give preference to being able to inhibit warnings, before they
1520 get reclassified to something else. */
1521 bool was_warning
= (diagnostic
->kind
== DK_WARNING
1522 || diagnostic
->kind
== DK_PEDWARN
);
1523 if (was_warning
&& m_inhibit_warnings
)
1526 if (diagnostic
->kind
== DK_PEDWARN
)
1528 diagnostic
->kind
= pedantic_warning_kind (this);
1529 /* We do this to avoid giving the message for -pedantic-errors. */
1530 orig_diag_kind
= diagnostic
->kind
;
1533 if (diagnostic
->kind
== DK_NOTE
&& m_inhibit_notes_p
)
1538 /* If we're reporting an ICE in the middle of some other error,
1539 try to flush out the previous error, then let this one
1540 through. Don't do this more than once. */
1541 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1543 pp_newline_and_flush (this->printer
);
1548 /* If the user requested that warnings be treated as errors, so be
1549 it. Note that we do this before the next block so that
1550 individual warnings can be overridden back to warnings with
1552 if (m_warning_as_error_requested
1553 && diagnostic
->kind
== DK_WARNING
)
1554 diagnostic
->kind
= DK_ERROR
;
1556 diagnostic
->message
.m_data
= &diagnostic
->x_data
;
1558 /* Check to see if the diagnostic is enabled at the location and
1559 not disabled by #pragma GCC diagnostic anywhere along the inlining
1561 if (!diagnostic_enabled (diagnostic
))
1564 if ((was_warning
|| diagnostic
->kind
== DK_WARNING
)
1565 && ((!m_warn_system_headers
1566 && diagnostic
->m_iinfo
.m_allsyslocs
)
1567 || m_inhibit_warnings
))
1568 /* Bail if the warning is not to be reported because all locations in the
1569 inlining stack (if there is one) are in system headers. */
1572 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1573 diagnostic_check_max_errors (this);
1577 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1579 /* When not checking, ICEs are converted to fatal errors when an
1580 error has already occurred. This is counteracted by
1583 && (m_diagnostic_count
[DK_ERROR
] > 0
1584 || m_diagnostic_count
[DK_SORRY
] > 0)
1585 && !m_abort_on_error
)
1588 = expand_location (diagnostic_location (diagnostic
));
1589 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1591 exit (ICE_EXIT_CODE
);
1593 if (m_internal_error
)
1594 (*m_internal_error
) (this,
1595 diagnostic
->message
.m_format_spec
,
1596 diagnostic
->message
.m_args_ptr
);
1598 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1599 ++m_diagnostic_count
[DK_WERROR
];
1601 ++m_diagnostic_count
[diagnostic
->kind
];
1603 /* Is this the initial diagnostic within the stack of groups? */
1604 if (m_diagnostic_groups
.m_emission_count
== 0)
1605 m_output_format
->on_begin_group ();
1606 m_diagnostic_groups
.m_emission_count
++;
1608 pp_format (this->printer
, &diagnostic
->message
, m_urlifier
);
1609 m_output_format
->on_begin_diagnostic (diagnostic
);
1610 pp_output_formatted_text (this->printer
);
1612 print_any_cwe (*diagnostic
);
1614 print_any_rules (*diagnostic
);
1615 if (m_show_option_requested
)
1616 print_option_information (*diagnostic
, orig_diag_kind
);
1617 m_output_format
->on_end_diagnostic (diagnostic
, orig_diag_kind
);
1618 switch (m_extra_output_kind
)
1622 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1623 print_parseable_fixits (get_file_cache (),
1624 this->printer
, diagnostic
->richloc
,
1625 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1627 pp_flush (this->printer
);
1629 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1630 print_parseable_fixits (get_file_cache (),
1631 this->printer
, diagnostic
->richloc
,
1632 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1634 pp_flush (this->printer
);
1637 diagnostic_action_after_output (this, diagnostic
->kind
);
1638 diagnostic
->x_data
= NULL
;
1640 if (m_edit_context_ptr
)
1641 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1642 m_edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1646 show_any_path (*diagnostic
);
1651 /* Get the number of digits in the decimal representation of VALUE. */
1654 num_digits (int value
)
1656 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1657 using floating point. */
1658 gcc_assert (value
>= 0);
1672 /* Given a partial pathname as input, return another pathname that
1673 shares no directory elements with the pathname of __FILE__. This
1674 is used by fancy_abort() to print `internal compiler error in expr.cc'
1675 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1678 trim_filename (const char *name
)
1680 static const char this_file
[] = __FILE__
;
1681 const char *p
= name
, *q
= this_file
;
1683 /* First skip any "../" in each filename. This allows us to give a proper
1684 reference to a file in a subdirectory. */
1685 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1688 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1691 /* Now skip any parts the two filenames have in common. */
1692 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1695 /* Now go backwards until the previous directory separator. */
1696 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1702 /* Standard error reporting routines in increasing order of severity.
1703 All of these take arguments like printf. */
1705 /* Text to be emitted verbatim to the error message stream; this
1706 produces no prefix and disables line-wrapping. Use rarely. */
1708 verbatim (const char *gmsgid
, ...)
1712 va_start (ap
, gmsgid
);
1713 text_info
text (_(gmsgid
), &ap
, errno
);
1714 pp_format_verbatim (global_dc
->printer
, &text
);
1715 pp_newline_and_flush (global_dc
->printer
);
1719 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1721 diagnostic_append_note (diagnostic_context
*context
,
1722 location_t location
,
1723 const char * gmsgid
, ...)
1725 diagnostic_info diagnostic
;
1727 rich_location
richloc (line_table
, location
);
1729 va_start (ap
, gmsgid
);
1730 diagnostic_set_info (&diagnostic
, gmsgid
, &ap
, &richloc
, DK_NOTE
);
1731 if (context
->m_inhibit_notes_p
)
1736 char *saved_prefix
= pp_take_prefix (context
->printer
);
1737 pp_set_prefix (context
->printer
,
1738 diagnostic_build_prefix (context
, &diagnostic
));
1739 pp_format (context
->printer
, &diagnostic
.message
);
1740 pp_output_formatted_text (context
->printer
);
1741 pp_destroy_prefix (context
->printer
);
1742 pp_set_prefix (context
->printer
, saved_prefix
);
1743 pp_newline (context
->printer
);
1744 diagnostic_show_locus (context
, &richloc
, DK_NOTE
);
1748 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1749 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1750 and internal_error_no_backtrace, as documented and defined below. */
1752 diagnostic_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1753 int opt
, const char *gmsgid
,
1754 va_list *ap
, diagnostic_t kind
)
1756 diagnostic_info diagnostic
;
1757 if (kind
== DK_PERMERROR
)
1759 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
,
1760 permissive_error_kind (global_dc
));
1761 diagnostic
.option_index
= (opt
!= -1 ? opt
1762 : permissive_error_option (global_dc
));
1766 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1767 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1768 diagnostic
.option_index
= opt
;
1770 diagnostic
.metadata
= metadata
;
1771 return global_dc
->report_diagnostic (&diagnostic
);
1774 /* Implement inform_n, warning_n, and error_n, as documented and
1777 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1778 int opt
, unsigned HOST_WIDE_INT n
,
1779 const char *singular_gmsgid
,
1780 const char *plural_gmsgid
,
1781 va_list *ap
, diagnostic_t kind
)
1783 diagnostic_info diagnostic
;
1786 if (sizeof n
<= sizeof gtn
)
1789 /* Use the largest number ngettext can handle, otherwise
1790 preserve the six least significant decimal digits for
1791 languages where the plural form depends on them. */
1792 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1794 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1795 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1796 if (kind
== DK_WARNING
)
1797 diagnostic
.option_index
= opt
;
1798 diagnostic
.metadata
= metadata
;
1799 return global_dc
->report_diagnostic (&diagnostic
);
1802 /* Wrapper around diagnostic_impl taking a variable argument list. */
1805 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1806 const char *gmsgid
, ...)
1808 auto_diagnostic_group d
;
1810 va_start (ap
, gmsgid
);
1811 rich_location
richloc (line_table
, location
);
1812 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1817 /* As above, but for rich_location *. */
1820 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1821 const char *gmsgid
, ...)
1823 auto_diagnostic_group d
;
1825 va_start (ap
, gmsgid
);
1826 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1831 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1834 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1835 const char *gmsgid
, va_list *ap
)
1837 rich_location
richloc (line_table
, location
);
1838 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1841 /* An informative note at LOCATION. Use this for additional details on an error
1844 inform (location_t location
, const char *gmsgid
, ...)
1846 auto_diagnostic_group d
;
1848 va_start (ap
, gmsgid
);
1849 rich_location
richloc (line_table
, location
);
1850 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1854 /* Same as "inform" above, but at RICHLOC. */
1856 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1858 gcc_assert (richloc
);
1860 auto_diagnostic_group d
;
1862 va_start (ap
, gmsgid
);
1863 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1867 /* An informative note at LOCATION. Use this for additional details on an
1870 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1871 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1874 va_start (ap
, plural_gmsgid
);
1875 auto_diagnostic_group d
;
1876 rich_location
richloc (line_table
, location
);
1877 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1882 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1883 to the relevant language specification but is likely to be buggy anyway.
1884 Returns true if the warning was printed, false if it was inhibited. */
1886 warning (int opt
, const char *gmsgid
, ...)
1888 auto_diagnostic_group d
;
1890 va_start (ap
, gmsgid
);
1891 rich_location
richloc (line_table
, input_location
);
1892 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1897 /* A warning at LOCATION. Use this for code which is correct according to the
1898 relevant language specification but is likely to be buggy anyway.
1899 Returns true if the warning was printed, false if it was inhibited. */
1902 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1904 auto_diagnostic_group d
;
1906 va_start (ap
, gmsgid
);
1907 rich_location
richloc (line_table
, location
);
1908 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1913 /* Same as "warning at" above, but using RICHLOC. */
1916 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1918 gcc_assert (richloc
);
1920 auto_diagnostic_group d
;
1922 va_start (ap
, gmsgid
);
1923 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1928 /* Same as "warning at" above, but using METADATA. */
1931 warning_meta (rich_location
*richloc
,
1932 const diagnostic_metadata
&metadata
,
1933 int opt
, const char *gmsgid
, ...)
1935 gcc_assert (richloc
);
1937 auto_diagnostic_group d
;
1939 va_start (ap
, gmsgid
);
1941 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1947 /* Same as warning_n plural variant below, but using RICHLOC. */
1950 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1951 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1953 gcc_assert (richloc
);
1955 auto_diagnostic_group d
;
1957 va_start (ap
, plural_gmsgid
);
1958 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1959 singular_gmsgid
, plural_gmsgid
,
1965 /* A warning at LOCATION. Use this for code which is correct according to the
1966 relevant language specification but is likely to be buggy anyway.
1967 Returns true if the warning was printed, false if it was inhibited. */
1970 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1971 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1973 auto_diagnostic_group d
;
1975 va_start (ap
, plural_gmsgid
);
1976 rich_location
richloc (line_table
, location
);
1977 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1978 singular_gmsgid
, plural_gmsgid
,
1984 /* A "pedantic" warning at LOCATION: issues a warning unless
1985 -pedantic-errors was given on the command line, in which case it
1986 issues an error. Use this for diagnostics required by the relevant
1987 language standard, if you have chosen not to make them errors.
1989 Note that these diagnostics are issued independent of the setting
1990 of the -Wpedantic command-line switch. To get a warning enabled
1991 only with that switch, use either "if (pedantic) pedwarn
1992 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1993 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1995 Returns true if the warning was printed, false if it was inhibited. */
1998 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
2000 auto_diagnostic_group d
;
2002 va_start (ap
, gmsgid
);
2003 rich_location
richloc (line_table
, location
);
2004 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
2009 /* Same as pedwarn above, but using RICHLOC. */
2012 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
2014 gcc_assert (richloc
);
2016 auto_diagnostic_group d
;
2018 va_start (ap
, gmsgid
);
2019 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
2024 /* A "permissive" error at LOCATION: issues an error unless
2025 -fpermissive was given on the command line, in which case it issues
2026 a warning. Use this for things that really should be errors but we
2027 want to support legacy code.
2029 Returns true if the warning was printed, false if it was inhibited. */
2032 permerror (location_t location
, const char *gmsgid
, ...)
2034 auto_diagnostic_group d
;
2036 va_start (ap
, gmsgid
);
2037 rich_location
richloc (line_table
, location
);
2038 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2043 /* Same as "permerror" above, but at RICHLOC. */
2046 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
2048 gcc_assert (richloc
);
2050 auto_diagnostic_group d
;
2052 va_start (ap
, gmsgid
);
2053 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2058 /* Similar to the above, but controlled by a flag other than -fpermissive.
2059 As above, an error by default or a warning with -fpermissive, but this
2060 diagnostic can also be downgraded by -Wno-error=opt. */
2063 permerror_opt (location_t location
, int opt
, const char *gmsgid
, ...)
2065 auto_diagnostic_group d
;
2067 va_start (ap
, gmsgid
);
2068 rich_location
richloc (line_table
, location
);
2069 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PERMERROR
);
2074 /* Same as "permerror" above, but at RICHLOC. */
2077 permerror_opt (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
2079 gcc_assert (richloc
);
2081 auto_diagnostic_group d
;
2083 va_start (ap
, gmsgid
);
2084 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PERMERROR
);
2089 /* A hard error: the code is definitely ill-formed, and an object file
2090 will not be produced. */
2092 error (const char *gmsgid
, ...)
2094 auto_diagnostic_group d
;
2096 va_start (ap
, gmsgid
);
2097 rich_location
richloc (line_table
, input_location
);
2098 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2102 /* A hard error: the code is definitely ill-formed, and an object file
2103 will not be produced. */
2105 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
2106 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
2108 auto_diagnostic_group d
;
2110 va_start (ap
, plural_gmsgid
);
2111 rich_location
richloc (line_table
, location
);
2112 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
2117 /* Same as above, but use location LOC instead of input_location. */
2119 error_at (location_t loc
, const char *gmsgid
, ...)
2121 auto_diagnostic_group d
;
2123 va_start (ap
, gmsgid
);
2124 rich_location
richloc (line_table
, loc
);
2125 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2129 /* Same as above, but use RICH_LOC. */
2132 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
2134 gcc_assert (richloc
);
2136 auto_diagnostic_group d
;
2138 va_start (ap
, gmsgid
);
2139 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2143 /* Same as above, but with metadata. */
2146 error_meta (rich_location
*richloc
, const diagnostic_metadata
&metadata
,
2147 const char *gmsgid
, ...)
2149 gcc_assert (richloc
);
2151 auto_diagnostic_group d
;
2153 va_start (ap
, gmsgid
);
2154 diagnostic_impl (richloc
, &metadata
, -1, gmsgid
, &ap
, DK_ERROR
);
2158 /* "Sorry, not implemented." Use for a language feature which is
2159 required by the relevant specification but not implemented by GCC.
2160 An object file will not be produced. */
2162 sorry (const char *gmsgid
, ...)
2164 auto_diagnostic_group d
;
2166 va_start (ap
, gmsgid
);
2167 rich_location
richloc (line_table
, input_location
);
2168 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2172 /* Same as above, but use location LOC instead of input_location. */
2174 sorry_at (location_t loc
, const char *gmsgid
, ...)
2176 auto_diagnostic_group d
;
2178 va_start (ap
, gmsgid
);
2179 rich_location
richloc (line_table
, loc
);
2180 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2184 /* Return true if an error or a "sorry" has been seen. Various
2185 processing is disabled after errors. */
2189 return errorcount
|| sorrycount
;
2192 /* An error which is severe enough that we make no attempt to
2193 continue. Do not use this for internal consistency checks; that's
2194 internal_error. Use of this function should be rare. */
2196 fatal_error (location_t loc
, const char *gmsgid
, ...)
2198 auto_diagnostic_group d
;
2200 va_start (ap
, gmsgid
);
2201 rich_location
richloc (line_table
, loc
);
2202 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
2208 /* An internal consistency check has failed. We make no attempt to
2211 internal_error (const char *gmsgid
, ...)
2213 auto_diagnostic_group d
;
2215 va_start (ap
, gmsgid
);
2216 rich_location
richloc (line_table
, input_location
);
2217 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
2223 /* Like internal_error, but no backtrace will be printed. Used when
2224 the internal error does not happen at the current location, but happened
2227 internal_error_no_backtrace (const char *gmsgid
, ...)
2229 auto_diagnostic_group d
;
2231 va_start (ap
, gmsgid
);
2232 rich_location
richloc (line_table
, input_location
);
2233 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
2239 /* Emit DIAGRAM to this context, respecting the output format. */
2242 diagnostic_context::emit_diagram (const diagnostic_diagram
&diagram
)
2244 if (m_diagrams
.m_theme
== nullptr)
2247 gcc_assert (m_output_format
);
2248 m_output_format
->on_diagram (diagram
);
2251 /* Special case error functions. Most are implemented in terms of the
2252 above, or should be. */
2254 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2255 runs its second argument through gettext. */
2257 fnotice (FILE *file
, const char *cmsgid
, ...)
2261 va_start (ap
, cmsgid
);
2262 vfprintf (file
, _(cmsgid
), ap
);
2266 /* Inform the user that an error occurred while trying to report some
2267 other error. This indicates catastrophic internal inconsistencies,
2268 so give up now. But do try to flush out the previous error.
2269 This mustn't use internal_error, that will cause infinite recursion. */
2272 diagnostic_context::error_recursion ()
2275 pp_newline_and_flush (this->printer
);
2278 "internal compiler error: error reporting routines re-entered.\n");
2280 /* Call diagnostic_action_after_output to get the "please submit a bug
2282 diagnostic_action_after_output (this, DK_ICE
);
2284 /* Do not use gcc_unreachable here; that goes through internal_error
2285 and therefore would cause infinite recursion. */
2289 /* Report an internal compiler error in a friendly manner. This is
2290 the function that gets called upon use of abort() in the source
2291 code generally, thanks to a special macro. */
2294 fancy_abort (const char *file
, int line
, const char *function
)
2296 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2297 internal_error will crash internally in a way that prevents a
2298 useful message reaching the user.
2299 This can happen with libgccjit in the case of gcc_assert failures
2300 that occur outside of the libgccjit mutex that guards the rest of
2301 gcc's state, including global_dc (when global_dc may not be
2302 initialized yet, or might be in use by another thread).
2303 Handle such cases as gracefully as possible by falling back to a
2304 minimal abort handler that only relies on i18n. */
2305 if (global_dc
->printer
== NULL
)
2307 /* Print the error message. */
2308 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
2309 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
2310 fputc ('\n', stderr
);
2312 /* Attempt to print a backtrace. */
2313 struct backtrace_state
*state
2314 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
2317 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
2320 /* We can't call warn_if_plugins or emergency_dump_function as these
2321 rely on GCC state that might not be initialized, or might be in
2322 use by another thread. */
2324 /* Abort the process. */
2328 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2331 /* class diagnostic_context. */
2334 diagnostic_context::begin_group ()
2336 m_diagnostic_groups
.m_nesting_depth
++;
2340 diagnostic_context::end_group ()
2342 if (--m_diagnostic_groups
.m_nesting_depth
== 0)
2344 /* Handle the case where we've popped the final diagnostic group.
2345 If any diagnostics were emitted, give the context a chance
2347 if (m_diagnostic_groups
.m_emission_count
> 0)
2348 m_output_format
->on_end_group ();
2349 m_diagnostic_groups
.m_emission_count
= 0;
2353 /* class auto_diagnostic_group. */
2355 /* Constructor: "push" this group into global_dc. */
2357 auto_diagnostic_group::auto_diagnostic_group ()
2359 global_dc
->begin_group ();
2362 /* Destructor: "pop" this group from global_dc. */
2364 auto_diagnostic_group::~auto_diagnostic_group ()
2366 global_dc
->end_group ();
2369 /* class diagnostic_text_output_format : public diagnostic_output_format. */
2371 diagnostic_text_output_format::~diagnostic_text_output_format ()
2373 /* Some of the errors may actually have been warnings. */
2374 if (m_context
.diagnostic_count (DK_WERROR
))
2376 /* -Werror was given. */
2377 if (m_context
.warning_as_error_requested_p ())
2378 pp_verbatim (m_context
.printer
,
2379 _("%s: all warnings being treated as errors"),
2381 /* At least one -Werror= was given. */
2383 pp_verbatim (m_context
.printer
,
2384 _("%s: some warnings being treated as errors"),
2386 pp_newline_and_flush (m_context
.printer
);
2391 diagnostic_text_output_format::on_begin_diagnostic (diagnostic_info
*diagnostic
)
2393 (*diagnostic_starter (&m_context
)) (&m_context
, diagnostic
);
2397 diagnostic_text_output_format::on_end_diagnostic (diagnostic_info
*diagnostic
,
2398 diagnostic_t orig_diag_kind
)
2400 (*diagnostic_finalizer (&m_context
)) (&m_context
, diagnostic
, orig_diag_kind
);
2404 diagnostic_text_output_format::on_diagram (const diagnostic_diagram
&diagram
)
2406 char *saved_prefix
= pp_take_prefix (m_context
.printer
);
2407 pp_set_prefix (m_context
.printer
, NULL
);
2408 /* Use a newline before and after and a two-space indent
2409 to make the diagram stand out a little from the wall of text. */
2410 pp_newline (m_context
.printer
);
2411 diagram
.get_canvas ().print_to_pp (m_context
.printer
, " ");
2412 pp_newline (m_context
.printer
);
2413 pp_set_prefix (m_context
.printer
, saved_prefix
);
2414 pp_flush (m_context
.printer
);
2417 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2418 file-based output formats. */
2421 diagnostic_output_format_init (diagnostic_context
*context
,
2422 const char *base_file_name
,
2423 enum diagnostics_output_format format
)
2429 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT
:
2430 /* The default; do nothing. */
2433 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR
:
2434 diagnostic_output_format_init_json_stderr (context
);
2437 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
:
2438 diagnostic_output_format_init_json_file (context
, base_file_name
);
2441 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR
:
2442 diagnostic_output_format_init_sarif_stderr (context
);
2445 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
:
2446 diagnostic_output_format_init_sarif_file (context
, base_file_name
);
2451 /* Initialize this context's m_diagrams based on CHARSET.
2452 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2453 (or NULL for "no diagrams"). */
2456 diagnostic_context::
2457 set_text_art_charset (enum diagnostic_text_art_charset charset
)
2459 delete m_diagrams
.m_theme
;
2465 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE
:
2466 m_diagrams
.m_theme
= nullptr;
2469 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII
:
2470 m_diagrams
.m_theme
= new text_art::ascii_theme ();
2473 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE
:
2474 m_diagrams
.m_theme
= new text_art::unicode_theme ();
2477 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
:
2478 m_diagrams
.m_theme
= new text_art::emoji_theme ();
2483 /* class simple_diagnostic_path : public diagnostic_path. */
2485 simple_diagnostic_path::simple_diagnostic_path (pretty_printer
*event_pp
)
2486 : m_event_pp (event_pp
)
2488 add_thread ("main");
2491 /* Implementation of diagnostic_path::num_events vfunc for
2492 simple_diagnostic_path: simply get the number of events in the vec. */
2495 simple_diagnostic_path::num_events () const
2497 return m_events
.length ();
2500 /* Implementation of diagnostic_path::get_event vfunc for
2501 simple_diagnostic_path: simply return the event in the vec. */
2503 const diagnostic_event
&
2504 simple_diagnostic_path::get_event (int idx
) const
2506 return *m_events
[idx
];
2510 simple_diagnostic_path::num_threads () const
2512 return m_threads
.length ();
2515 const diagnostic_thread
&
2516 simple_diagnostic_path::get_thread (diagnostic_thread_id_t idx
) const
2518 return *m_threads
[idx
];
2521 diagnostic_thread_id_t
2522 simple_diagnostic_path::add_thread (const char *name
)
2524 m_threads
.safe_push (new simple_diagnostic_thread (name
));
2525 return m_threads
.length () - 1;
2528 /* Add an event to this path at LOC within function FNDECL at
2531 Use m_context's printer to format FMT, as the text of the new
2534 Return the id of the new event. */
2536 diagnostic_event_id_t
2537 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2538 const char *fmt
, ...)
2540 pretty_printer
*pp
= m_event_pp
;
2541 pp_clear_output_area (pp
);
2543 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2549 text_info
ti (_(fmt
), &ap
, 0, nullptr, &rich_loc
);
2550 pp_format (pp
, &ti
);
2551 pp_output_formatted_text (pp
);
2555 simple_diagnostic_event
*new_event
2556 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2557 m_events
.safe_push (new_event
);
2559 pp_clear_output_area (pp
);
2561 return diagnostic_event_id_t (m_events
.length () - 1);
2564 diagnostic_event_id_t
2565 simple_diagnostic_path::add_thread_event (diagnostic_thread_id_t thread_id
,
2569 const char *fmt
, ...)
2571 pretty_printer
*pp
= m_event_pp
;
2572 pp_clear_output_area (pp
);
2574 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2580 text_info
ti (_(fmt
), &ap
, 0, nullptr, &rich_loc
);
2582 pp_format (pp
, &ti
);
2583 pp_output_formatted_text (pp
);
2587 simple_diagnostic_event
*new_event
2588 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
),
2590 m_events
.safe_push (new_event
);
2592 pp_clear_output_area (pp
);
2594 return diagnostic_event_id_t (m_events
.length () - 1);
2597 /* struct simple_diagnostic_event. */
2599 /* simple_diagnostic_event's ctor. */
2601 simple_diagnostic_event::
2602 simple_diagnostic_event (location_t loc
,
2606 diagnostic_thread_id_t thread_id
)
2607 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
)),
2608 m_thread_id (thread_id
)
2612 /* simple_diagnostic_event's dtor. */
2614 simple_diagnostic_event::~simple_diagnostic_event ()
2619 /* Print PATH by emitting a dummy "note" associated with it. */
2622 void debug (diagnostic_path
*path
)
2624 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2625 richloc
.set_path (path
);
2626 inform (&richloc
, "debug path");
2629 /* Really call the system 'abort'. This has to go right at the end of
2630 this file, so that there are no functions after it that call abort
2631 and get the system abort instead of our macro. */
2641 namespace selftest
{
2643 /* Helper function for test_print_escaped_string. */
2646 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2650 print_escaped_string (&pp
, input
);
2651 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2654 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2655 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2657 /* Tests of print_escaped_string. */
2660 test_print_escaped_string ()
2663 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2665 /* Non-empty string. */
2666 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2668 /* Various things that need to be escaped: */
2670 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2673 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2676 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2679 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2682 /* Non-printable characters: BEL: '\a': 0x07 */
2683 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2685 /* Non-printable characters: vertical tab: '\v': 0x0b */
2686 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2690 /* Tests of print_parseable_fixits. */
2692 /* Verify that print_parseable_fixits emits the empty string if there
2696 test_print_parseable_fixits_none ()
2700 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2702 print_parseable_fixits (fc
, &pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2703 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2706 /* Verify that print_parseable_fixits does the right thing if there
2707 is an insertion fixit hint. */
2710 test_print_parseable_fixits_insert ()
2714 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2716 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2717 linemap_line_start (line_table
, 5, 100);
2718 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2719 location_t where
= linemap_position_for_column (line_table
, 10);
2720 richloc
.add_fixit_insert_before (where
, "added content");
2722 print_parseable_fixits (fc
, &pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2723 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2724 pp_formatted_text (&pp
));
2727 /* Verify that print_parseable_fixits does the right thing if there
2728 is an removal fixit hint. */
2731 test_print_parseable_fixits_remove ()
2735 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2737 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2738 linemap_line_start (line_table
, 5, 100);
2739 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2741 where
.m_start
= linemap_position_for_column (line_table
, 10);
2742 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2743 richloc
.add_fixit_remove (where
);
2745 print_parseable_fixits (fc
, &pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2746 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2747 pp_formatted_text (&pp
));
2750 /* Verify that print_parseable_fixits does the right thing if there
2751 is an replacement fixit hint. */
2754 test_print_parseable_fixits_replace ()
2758 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2760 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2761 linemap_line_start (line_table
, 5, 100);
2762 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2764 where
.m_start
= linemap_position_for_column (line_table
, 10);
2765 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2766 richloc
.add_fixit_replace (where
, "replacement");
2768 print_parseable_fixits (fc
, &pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2769 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2770 pp_formatted_text (&pp
));
2773 /* Verify that print_parseable_fixits correctly handles
2774 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2777 test_print_parseable_fixits_bytes_vs_display_columns ()
2779 line_table_test ltt
;
2780 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2782 /* 1-based byte offsets: 12345677778888999900001234567. */
2783 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2784 /* 1-based display cols: 123456[......7-8.....]9012345. */
2785 const int tabstop
= 8;
2787 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2789 const char *const fname
= tmp
.get_filename ();
2791 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2792 linemap_line_start (line_table
, 1, 100);
2793 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2795 where
.m_start
= linemap_position_for_column (line_table
, 12);
2796 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2797 richloc
.add_fixit_replace (where
, "color");
2800 pretty_printer tmp_pp
;
2801 print_escaped_string (&tmp_pp
, fname
);
2802 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2804 const int buf_len
= strlen (escaped_fname
) + 100;
2805 char *const expected
= XNEWVEC (char, buf_len
);
2809 print_parseable_fixits (fc
, &pp
, &richloc
,
2810 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2812 snprintf (expected
, buf_len
,
2813 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2814 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2818 print_parseable_fixits (fc
, &pp
, &richloc
,
2819 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2821 snprintf (expected
, buf_len
,
2822 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2823 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2826 XDELETEVEC (expected
);
2827 free (escaped_fname
);
2831 diagnostic_get_location_text (..., SHOW_COLUMN)
2832 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2833 colorization disabled. */
2836 assert_location_text (const char *expected_loc_text
,
2837 const char *filename
, int line
, int column
,
2840 enum diagnostics_column_unit column_unit
2841 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2843 test_diagnostic_context dc
;
2844 dc
.m_show_column
= show_column
;
2845 dc
.m_column_unit
= column_unit
;
2846 dc
.m_column_origin
= origin
;
2848 expanded_location xloc
;
2849 xloc
.file
= filename
;
2851 xloc
.column
= column
;
2855 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2856 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2857 free (actual_loc_text
);
2860 /* Verify that diagnostic_get_location_text works as expected. */
2863 test_diagnostic_get_location_text ()
2865 const char *old_progname
= progname
;
2866 progname
= "PROGNAME";
2867 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2868 char *built_in_colon
= concat (special_fname_builtin (), ":", (char *) 0);
2869 assert_location_text (built_in_colon
, special_fname_builtin (),
2871 free (built_in_colon
);
2872 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2873 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2874 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2875 for (int origin
= 0; origin
!= 2; ++origin
)
2876 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2877 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2878 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2879 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2881 maybe_line_and_column (INT_MAX
, INT_MAX
);
2882 maybe_line_and_column (INT_MIN
, INT_MIN
);
2885 /* In order to test display columns vs byte columns, we need to create a
2886 file for location_get_source_line() to read. */
2888 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2889 const int line_bytes
= strlen (content
) - 1;
2890 const int def_tabstop
= 8;
2891 const cpp_char_column_policy
policy (def_tabstop
, cpp_wcwidth
);
2892 const int display_width
= cpp_display_width (content
, line_bytes
, policy
);
2893 ASSERT_EQ (line_bytes
- 2, display_width
);
2894 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2895 const char *const fname
= tmp
.get_filename ();
2896 const int buf_len
= strlen (fname
) + 16;
2897 char *const expected
= XNEWVEC (char, buf_len
);
2899 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2900 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2901 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2903 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2904 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2905 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2907 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2908 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2909 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2911 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2912 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2913 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2915 XDELETEVEC (expected
);
2919 progname
= old_progname
;
2922 /* Selftest for num_digits. */
2927 ASSERT_EQ (1, num_digits (0));
2928 ASSERT_EQ (1, num_digits (9));
2929 ASSERT_EQ (2, num_digits (10));
2930 ASSERT_EQ (2, num_digits (99));
2931 ASSERT_EQ (3, num_digits (100));
2932 ASSERT_EQ (3, num_digits (999));
2933 ASSERT_EQ (4, num_digits (1000));
2934 ASSERT_EQ (4, num_digits (9999));
2935 ASSERT_EQ (5, num_digits (10000));
2936 ASSERT_EQ (5, num_digits (99999));
2937 ASSERT_EQ (6, num_digits (100000));
2938 ASSERT_EQ (6, num_digits (999999));
2939 ASSERT_EQ (7, num_digits (1000000));
2940 ASSERT_EQ (7, num_digits (9999999));
2941 ASSERT_EQ (8, num_digits (10000000));
2942 ASSERT_EQ (8, num_digits (99999999));
2945 /* Run all of the selftests within this file. */
2948 c_diagnostic_cc_tests ()
2950 test_print_escaped_string ();
2951 test_print_parseable_fixits_none ();
2952 test_print_parseable_fixits_insert ();
2953 test_print_parseable_fixits_remove ();
2954 test_print_parseable_fixits_replace ();
2955 test_print_parseable_fixits_bytes_vs_display_columns ();
2956 test_diagnostic_get_location_text ();
2961 } // namespace selftest
2963 #endif /* #if CHECKING_P */
2966 # pragma GCC diagnostic pop