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-text-art.h"
40 #include "diagnostic-diagram.h"
41 #include "edit-context.h"
43 #include "selftest-diagnostic.h"
46 #include "text-art/theme.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)->pedantic_errors ? DK_ERROR : DK_WARNING)
65 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
66 #define permissive_error_option(DC) ((DC)->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 error_recursion (diagnostic_context
*) ATTRIBUTE_NORETURN
;
78 static void real_abort (void) ATTRIBUTE_NORETURN
;
80 /* Name of program invoked, sans directories. */
84 /* A diagnostic_context surrogate for stderr. */
85 static diagnostic_context global_diagnostic_context
;
86 diagnostic_context
*global_dc
= &global_diagnostic_context
;
88 /* Return a malloc'd string containing MSG formatted a la printf. The
89 caller is responsible for freeing the memory. */
91 build_message_string (const char *msg
, ...)
97 str
= xvasprintf (msg
, ap
);
103 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
105 file_name_as_prefix (diagnostic_context
*context
, const char *f
)
108 = colorize_start (pp_show_color (context
->printer
), "locus");
109 const char *locus_ce
= colorize_stop (pp_show_color (context
->printer
));
110 return build_message_string ("%s%s:%s ", locus_cs
, f
, locus_ce
);
115 /* Return the value of the getenv("COLUMNS") as an integer. If the
116 value is not set to a positive integer, use ioctl to get the
117 terminal width. If it fails, return INT_MAX. */
119 get_terminal_width (void)
121 const char * s
= getenv ("COLUMNS");
131 if (ioctl (0, TIOCGWINSZ
, &w
) == 0 && w
.ws_col
> 0)
138 /* Set caret_max_width to value. */
140 diagnostic_set_caret_max_width (diagnostic_context
*context
, int value
)
142 /* One minus to account for the leading empty space. */
143 value
= value
? value
- 1
144 : (isatty (fileno (pp_buffer (context
->printer
)->stream
))
145 ? get_terminal_width () - 1: INT_MAX
);
150 context
->caret_max_width
= value
;
153 /* Default implementation of final_cb. */
156 default_diagnostic_final_cb (diagnostic_context
*context
)
158 /* Some of the errors may actually have been warnings. */
159 if (diagnostic_kind_count (context
, DK_WERROR
))
161 /* -Werror was given. */
162 if (context
->warning_as_error_requested
)
163 pp_verbatim (context
->printer
,
164 _("%s: all warnings being treated as errors"),
166 /* At least one -Werror= was given. */
168 pp_verbatim (context
->printer
,
169 _("%s: some warnings being treated as errors"),
171 pp_newline_and_flush (context
->printer
);
175 /* Initialize the diagnostic message outputting machinery. */
177 diagnostic_initialize (diagnostic_context
*context
, int n_opts
)
181 /* Allocate a basic pretty-printer. Clients will replace this a
182 much more elaborated pretty-printer if they wish. */
183 context
->printer
= XNEW (pretty_printer
);
184 new (context
->printer
) pretty_printer ();
186 memset (context
->diagnostic_count
, 0, sizeof context
->diagnostic_count
);
187 context
->warning_as_error_requested
= false;
188 context
->n_opts
= n_opts
;
189 context
->classify_diagnostic
= XNEWVEC (diagnostic_t
, n_opts
);
190 for (i
= 0; i
< n_opts
; i
++)
191 context
->classify_diagnostic
[i
] = DK_UNSPECIFIED
;
192 context
->show_caret
= false;
193 diagnostic_set_caret_max_width (context
, pp_line_cutoff (context
->printer
));
194 for (i
= 0; i
< rich_location::STATICALLY_ALLOCATED_RANGES
; i
++)
195 context
->caret_chars
[i
] = '^';
196 context
->show_cwe
= false;
197 context
->show_rules
= false;
198 context
->path_format
= DPF_NONE
;
199 context
->show_path_depths
= false;
200 context
->show_option_requested
= false;
201 context
->abort_on_error
= false;
202 context
->show_column
= false;
203 context
->pedantic_errors
= false;
204 context
->permissive
= false;
205 context
->opt_permissive
= 0;
206 context
->fatal_errors
= false;
207 context
->dc_inhibit_warnings
= false;
208 context
->dc_warn_system_headers
= false;
209 context
->max_errors
= 0;
210 context
->internal_error
= NULL
;
211 diagnostic_starter (context
) = default_diagnostic_starter
;
212 context
->start_span
= default_diagnostic_start_span_fn
;
213 diagnostic_finalizer (context
) = default_diagnostic_finalizer
;
214 context
->option_enabled
= NULL
;
215 context
->option_state
= NULL
;
216 context
->option_name
= NULL
;
217 context
->get_option_url
= NULL
;
218 context
->last_location
= UNKNOWN_LOCATION
;
219 context
->last_module
= 0;
220 context
->x_data
= NULL
;
222 context
->inhibit_notes_p
= false;
223 context
->colorize_source_p
= false;
224 context
->show_labels_p
= false;
225 context
->show_line_numbers_p
= false;
226 context
->min_margin_width
= 0;
227 context
->show_ruler_p
= false;
228 context
->report_bug
= false;
230 if (const char *var
= getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
232 if (!strcmp (var
, "fixits-v1"))
233 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
;
234 else if (!strcmp (var
, "fixits-v2"))
235 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
;
236 /* Silently ignore unrecognized values. */
238 context
->column_unit
= DIAGNOSTICS_COLUMN_UNIT_DISPLAY
;
239 context
->column_origin
= 1;
240 context
->tabstop
= 8;
241 context
->escape_format
= DIAGNOSTICS_ESCAPE_FORMAT_UNICODE
;
242 context
->edit_context_ptr
= NULL
;
243 context
->diagnostic_group_nesting_depth
= 0;
244 context
->diagnostic_group_emission_count
= 0;
245 context
->begin_group_cb
= NULL
;
246 context
->end_group_cb
= NULL
;
247 context
->final_cb
= default_diagnostic_final_cb
;
248 context
->ice_handler_cb
= NULL
;
249 context
->includes_seen
= NULL
;
250 context
->m_client_data_hooks
= NULL
;
251 context
->m_diagrams
.m_theme
= NULL
;
252 context
->m_diagrams
.m_emission_cb
= NULL
;
253 diagnostics_text_art_charset_init (context
,
254 DIAGNOSTICS_TEXT_ART_CHARSET_DEFAULT
);
257 /* Maybe initialize the color support. We require clients to do this
258 explicitly, since most clients don't want color. When called
259 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
262 diagnostic_color_init (diagnostic_context
*context
, int value
/*= -1 */)
264 /* value == -1 is the default value. */
267 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
268 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
269 otherwise default to -fdiagnostics-color=never, for other
270 values default to that
271 -fdiagnostics-color={never,auto,always}. */
272 if (DIAGNOSTICS_COLOR_DEFAULT
== -1)
274 if (!getenv ("GCC_COLORS"))
276 value
= DIAGNOSTICS_COLOR_AUTO
;
279 value
= DIAGNOSTICS_COLOR_DEFAULT
;
281 pp_show_color (context
->printer
)
282 = colorize_init ((diagnostic_color_rule_t
) value
);
285 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
288 diagnostic_urls_init (diagnostic_context
*context
, int value
/*= -1 */)
290 /* value == -1 is the default value. */
293 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
294 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
295 environment, otherwise default to -fdiagnostics-urls=never,
296 for other values default to that
297 -fdiagnostics-urls={never,auto,always}. */
298 if (DIAGNOSTICS_URLS_DEFAULT
== -1)
300 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
302 value
= DIAGNOSTICS_URL_AUTO
;
305 value
= DIAGNOSTICS_URLS_DEFAULT
;
308 context
->printer
->url_format
309 = determine_url_format ((diagnostic_url_rule_t
) value
);
312 /* Create the file_cache, if not already created, and tell it how to
313 translate files on input. */
314 void diagnostic_initialize_input_context (diagnostic_context
*context
,
315 diagnostic_input_charset_callback ccb
,
316 bool should_skip_bom
)
318 if (!context
->m_file_cache
)
319 context
->m_file_cache
= new file_cache
;
320 context
->m_file_cache
->initialize_input_context (ccb
, should_skip_bom
);
323 /* Do any cleaning up required after the last diagnostic is emitted. */
326 diagnostic_finish (diagnostic_context
*context
)
328 if (context
->final_cb
)
329 context
->final_cb (context
);
331 if (context
->m_diagrams
.m_theme
)
333 delete context
->m_diagrams
.m_theme
;
334 context
->m_diagrams
.m_theme
= NULL
;
337 diagnostic_file_cache_fini ();
339 XDELETEVEC (context
->classify_diagnostic
);
340 context
->classify_diagnostic
= NULL
;
342 /* diagnostic_initialize allocates context->printer using XNEW
343 and placement-new. */
344 context
->printer
->~pretty_printer ();
345 XDELETE (context
->printer
);
346 context
->printer
= NULL
;
348 if (context
->edit_context_ptr
)
350 delete context
->edit_context_ptr
;
351 context
->edit_context_ptr
= NULL
;
354 if (context
->includes_seen
)
356 delete context
->includes_seen
;
357 context
->includes_seen
= nullptr;
360 if (context
->m_client_data_hooks
)
362 delete context
->m_client_data_hooks
;
363 context
->m_client_data_hooks
= NULL
;
367 /* Initialize DIAGNOSTIC, where the message MSG has already been
370 diagnostic_set_info_translated (diagnostic_info
*diagnostic
, const char *msg
,
371 va_list *args
, rich_location
*richloc
,
374 gcc_assert (richloc
);
375 diagnostic
->message
.err_no
= errno
;
376 diagnostic
->message
.args_ptr
= args
;
377 diagnostic
->message
.format_spec
= msg
;
378 diagnostic
->message
.m_richloc
= richloc
;
379 diagnostic
->richloc
= richloc
;
380 diagnostic
->metadata
= NULL
;
381 diagnostic
->kind
= kind
;
382 diagnostic
->option_index
= 0;
385 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
388 diagnostic_set_info (diagnostic_info
*diagnostic
, const char *gmsgid
,
389 va_list *args
, rich_location
*richloc
,
392 gcc_assert (richloc
);
393 diagnostic_set_info_translated (diagnostic
, _(gmsgid
), args
, richloc
, kind
);
396 static const char *const diagnostic_kind_color
[] = {
397 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
398 #include "diagnostic.def"
399 #undef DEFINE_DIAGNOSTIC_KIND
403 /* Get a color name for diagnostics of type KIND
404 Result could be NULL. */
407 diagnostic_get_color_for_kind (diagnostic_t kind
)
409 return diagnostic_kind_color
[kind
];
412 /* Given an expanded_location, convert the column (which is in 1-based bytes)
413 to the requested units, without converting the origin.
414 Return -1 if the column is invalid (<= 0). */
417 convert_column_unit (enum diagnostics_column_unit column_unit
,
429 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY
:
431 cpp_char_column_policy
policy (tabstop
, cpp_wcwidth
);
432 return location_compute_display_column (s
, policy
);
435 case DIAGNOSTICS_COLUMN_UNIT_BYTE
:
440 /* Given an expanded_location, convert the column (which is in 1-based bytes)
441 to the requested units and origin. Return -1 if the column is
444 diagnostic_converted_column (diagnostic_context
*context
, expanded_location s
)
447 = convert_column_unit (context
->column_unit
, context
->tabstop
, s
);
448 if (one_based_col
<= 0)
450 return one_based_col
+ (context
->column_origin
- 1);
453 /* Return a formatted line and column ':%line:%column'. Elided if
454 line == 0 or col < 0. (A column of 0 may be valid due to the
455 -fdiagnostics-column-origin option.)
456 The result is a statically allocated buffer. */
459 maybe_line_and_column (int line
, int col
)
461 static char result
[32];
466 = snprintf (result
, sizeof (result
),
467 col
>= 0 ? ":%d:%d" : ":%d", line
, col
);
468 gcc_checking_assert (l
< sizeof (result
));
475 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
476 The caller is responsible for freeing the memory. */
479 diagnostic_get_location_text (diagnostic_context
*context
,
482 pretty_printer
*pp
= context
->printer
;
483 const char *locus_cs
= colorize_start (pp_show_color (pp
), "locus");
484 const char *locus_ce
= colorize_stop (pp_show_color (pp
));
485 const char *file
= s
.file
? s
.file
: progname
;
488 if (strcmp (file
, special_fname_builtin ()))
491 if (context
->show_column
)
492 col
= diagnostic_converted_column (context
, s
);
495 const char *line_col
= maybe_line_and_column (line
, col
);
496 return build_message_string ("%s%s%s:%s", locus_cs
, file
,
500 static const char *const diagnostic_kind_text
[] = {
501 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
502 #include "diagnostic.def"
503 #undef DEFINE_DIAGNOSTIC_KIND
507 /* Return a malloc'd string describing a location and the severity of the
508 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
509 freeing the memory. */
511 diagnostic_build_prefix (diagnostic_context
*context
,
512 const diagnostic_info
*diagnostic
)
514 gcc_assert (diagnostic
->kind
< DK_LAST_DIAGNOSTIC_KIND
);
516 const char *text
= _(diagnostic_kind_text
[diagnostic
->kind
]);
517 const char *text_cs
= "", *text_ce
= "";
518 pretty_printer
*pp
= context
->printer
;
520 if (diagnostic_kind_color
[diagnostic
->kind
])
522 text_cs
= colorize_start (pp_show_color (pp
),
523 diagnostic_kind_color
[diagnostic
->kind
]);
524 text_ce
= colorize_stop (pp_show_color (pp
));
527 expanded_location s
= diagnostic_expand_location (diagnostic
);
528 char *location_text
= diagnostic_get_location_text (context
, s
);
530 char *result
= build_message_string ("%s %s%s%s", location_text
,
531 text_cs
, text
, text_ce
);
532 free (location_text
);
536 /* Functions at which to stop the backtrace print. It's not
537 particularly helpful to print the callers of these functions. */
539 static const char * const bt_stop
[] =
547 /* A callback function passed to the backtrace_full function. */
550 bt_callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
551 const char *function
)
553 int *pcount
= (int *) data
;
555 /* If we don't have any useful information, don't print
557 if (filename
== NULL
&& function
== NULL
)
560 /* Skip functions in diagnostic.cc. */
563 && strcmp (lbasename (filename
), "diagnostic.cc") == 0)
566 /* Print up to 20 functions. We could make this a --param, but
567 since this is only for debugging just use a constant for now. */
570 /* Returning a non-zero value stops the backtrace. */
576 if (function
!= NULL
)
578 char *str
= cplus_demangle_v3 (function
,
579 (DMGL_VERBOSE
| DMGL_ANSI
580 | DMGL_GNU_V3
| DMGL_PARAMS
));
587 for (size_t i
= 0; i
< ARRAY_SIZE (bt_stop
); ++i
)
589 size_t len
= strlen (bt_stop
[i
]);
590 if (strncmp (function
, bt_stop
[i
], len
) == 0
591 && (function
[len
] == '\0' || function
[len
] == '('))
595 /* Returning a non-zero value stops the backtrace. */
601 fprintf (stderr
, "0x%lx %s\n\t%s:%d\n",
603 function
== NULL
? "???" : function
,
604 filename
== NULL
? "???" : filename
,
613 /* A callback function passed to the backtrace_full function. This is
614 called if backtrace_full has an error. */
617 bt_err_callback (void *data ATTRIBUTE_UNUSED
, const char *msg
, int errnum
)
621 /* This means that no debug info was available. Just quietly
622 skip printing backtrace info. */
625 fprintf (stderr
, "%s%s%s\n", msg
, errnum
== 0 ? "" : ": ",
626 errnum
== 0 ? "" : xstrerror (errnum
));
629 /* Check if we've met the maximum error limit, and if so fatally exit
630 with a message. CONTEXT is the context to check, and FLUSH
631 indicates whether a diagnostic_finish call is needed. */
634 diagnostic_check_max_errors (diagnostic_context
*context
, bool flush
)
636 if (!context
->max_errors
)
639 int count
= (diagnostic_kind_count (context
, DK_ERROR
)
640 + diagnostic_kind_count (context
, DK_SORRY
)
641 + diagnostic_kind_count (context
, DK_WERROR
));
643 if (count
>= context
->max_errors
)
646 "compilation terminated due to -fmax-errors=%u.\n",
647 context
->max_errors
);
649 diagnostic_finish (context
);
650 exit (FATAL_EXIT_CODE
);
654 /* Take any action which is expected to happen after the diagnostic
655 is written out. This function does not always return. */
657 diagnostic_action_after_output (diagnostic_context
*context
,
658 diagnostic_t diag_kind
)
670 if (context
->abort_on_error
)
672 if (context
->fatal_errors
)
674 fnotice (stderr
, "compilation terminated due to -Wfatal-errors.\n");
675 diagnostic_finish (context
);
676 exit (FATAL_EXIT_CODE
);
683 /* Optional callback for attempting to handle ICEs gracefully. */
684 if (void (*ice_handler_cb
) (diagnostic_context
*)
685 = context
->ice_handler_cb
)
687 /* Clear the callback, to avoid potentially re-entering
688 the routine if there's a crash within the handler. */
689 context
->ice_handler_cb
= NULL
;
690 ice_handler_cb (context
);
692 /* The context might have had diagnostic_finish called on
695 struct backtrace_state
*state
= NULL
;
696 if (diag_kind
== DK_ICE
)
697 state
= backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
700 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
703 if (context
->abort_on_error
)
706 if (context
->report_bug
)
707 fnotice (stderr
, "Please submit a full bug report, "
708 "with preprocessed source.\n");
710 fnotice (stderr
, "Please submit a full bug report, "
711 "with preprocessed source (by using -freport-bug).\n");
714 fnotice (stderr
, "Please include the complete backtrace "
715 "with any bug report.\n");
716 fnotice (stderr
, "See %s for instructions.\n", bug_report_url
);
718 exit (ICE_EXIT_CODE
);
722 if (context
->abort_on_error
)
724 diagnostic_finish (context
);
725 fnotice (stderr
, "compilation terminated.\n");
726 exit (FATAL_EXIT_CODE
);
733 /* True if the last module or file in which a diagnostic was reported is
734 different from the current one. */
737 last_module_changed_p (diagnostic_context
*context
,
738 const line_map_ordinary
*map
)
740 return context
->last_module
!= map
;
743 /* Remember the current module or file as being the last one in which we
744 report a diagnostic. */
747 set_last_module (diagnostic_context
*context
, const line_map_ordinary
*map
)
749 context
->last_module
= map
;
752 /* Only dump the "In file included from..." stack once for each file. */
755 includes_seen (diagnostic_context
*context
, const line_map_ordinary
*map
)
757 /* No include path for main. */
758 if (MAIN_FILE_P (map
))
761 /* Always identify C++ modules, at least for now. */
763 if (linemap_check_ordinary (map
)->reason
== LC_RENAME
)
764 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
765 probe
= linemap_included_from_linemap (line_table
, map
);
766 if (MAP_MODULE_P (probe
))
769 if (!context
->includes_seen
)
770 context
->includes_seen
= new hash_set
<location_t
, false, location_hash
>;
772 /* Hash the location of the #include directive to better handle files
773 that are included multiple times with different macros defined. */
774 return context
->includes_seen
->add (linemap_included_from (map
));
778 diagnostic_report_current_module (diagnostic_context
*context
, location_t where
)
780 const line_map_ordinary
*map
= NULL
;
782 if (pp_needs_newline (context
->printer
))
784 pp_newline (context
->printer
);
785 pp_needs_newline (context
->printer
) = false;
788 if (where
<= BUILTINS_LOCATION
)
791 linemap_resolve_location (line_table
, where
,
792 LRK_MACRO_DEFINITION_LOCATION
,
795 if (map
&& last_module_changed_p (context
, map
))
797 set_last_module (context
, map
);
798 if (!includes_seen (context
, map
))
800 bool first
= true, need_inc
= true, was_module
= MAP_MODULE_P (map
);
801 expanded_location s
= {};
804 where
= linemap_included_from (map
);
805 map
= linemap_included_from_linemap (line_table
, map
);
806 bool is_module
= MAP_MODULE_P (map
);
807 s
.file
= LINEMAP_FILE (map
);
808 s
.line
= SOURCE_LINE (map
, where
);
810 if (first
&& context
->show_column
)
812 s
.column
= SOURCE_COLUMN (map
, where
);
813 col
= diagnostic_converted_column (context
, s
);
815 const char *line_col
= maybe_line_and_column (s
.line
, col
);
816 static const char *const msgs
[] =
820 N_("In file included from"), /* 2 */
821 N_(" included from"),
822 N_("In module"), /* 4 */
824 N_("In module imported at"), /* 6 */
828 unsigned index
= (was_module
? 6 : is_module
? 4
829 : need_inc
? 2 : 0) + !first
;
831 pp_verbatim (context
->printer
, "%s%s %r%s%s%R",
832 first
? "" : was_module
? ", " : ",\n",
834 "locus", s
.file
, line_col
);
835 first
= false, need_inc
= was_module
, was_module
= is_module
;
837 while (!includes_seen (context
, map
));
838 pp_verbatim (context
->printer
, ":");
839 pp_newline (context
->printer
);
844 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
848 diagnostic_show_any_path (diagnostic_context
*context
,
849 diagnostic_info
*diagnostic
)
851 const diagnostic_path
*path
= diagnostic
->richloc
->get_path ();
855 if (context
->print_path
)
856 context
->print_path (context
, path
);
859 /* class diagnostic_event. */
861 /* struct diagnostic_event::meaning. */
864 diagnostic_event::meaning::dump_to_pp (pretty_printer
*pp
) const
866 bool need_comma
= false;
867 pp_character (pp
, '{');
868 if (const char *verb_str
= maybe_get_verb_str (m_verb
))
870 pp_printf (pp
, "verb: %qs", verb_str
);
873 if (const char *noun_str
= maybe_get_noun_str (m_noun
))
876 pp_string (pp
, ", ");
877 pp_printf (pp
, "noun: %qs", noun_str
);
880 if (const char *property_str
= maybe_get_property_str (m_property
))
883 pp_string (pp
, ", ");
884 pp_printf (pp
, "property: %qs", property_str
);
887 pp_character (pp
, '}');
890 /* Get a string (or NULL) for V suitable for use within a SARIF
891 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
894 diagnostic_event::meaning::maybe_get_verb_str (enum verb v
)
921 /* Get a string (or NULL) for N suitable for use within a SARIF
922 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
925 diagnostic_event::meaning::maybe_get_noun_str (enum noun n
)
948 /* Get a string (or NULL) for P suitable for use within a SARIF
949 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
952 diagnostic_event::meaning::maybe_get_property_str (enum property p
)
958 case PROPERTY_unknown
:
967 /* class diagnostic_path. */
969 /* Subroutint of diagnostic_path::interprocedural_p.
970 Look for the first event in this path that is within a function
971 i.e. has a non-NULL fndecl, and a non-zero stack depth.
972 If found, write its index to *OUT_IDX and return true.
973 Otherwise return false. */
976 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx
) const
978 const unsigned num
= num_events ();
979 for (unsigned i
= 0; i
< num
; i
++)
981 if (!(get_event (i
).get_fndecl () == NULL
982 && get_event (i
).get_stack_depth () == 0))
991 /* Return true if the events in this path involve more than one
992 function, or false if it is purely intraprocedural. */
995 diagnostic_path::interprocedural_p () const
997 /* Ignore leading events that are outside of any function. */
998 unsigned first_fn_event_idx
;
999 if (!get_first_event_in_a_function (&first_fn_event_idx
))
1002 const diagnostic_event
&first_fn_event
= get_event (first_fn_event_idx
);
1003 tree first_fndecl
= first_fn_event
.get_fndecl ();
1004 int first_fn_stack_depth
= first_fn_event
.get_stack_depth ();
1006 const unsigned num
= num_events ();
1007 for (unsigned i
= first_fn_event_idx
+ 1; i
< num
; i
++)
1009 if (get_event (i
).get_fndecl () != first_fndecl
)
1011 if (get_event (i
).get_stack_depth () != first_fn_stack_depth
)
1018 default_diagnostic_starter (diagnostic_context
*context
,
1019 diagnostic_info
*diagnostic
)
1021 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
1022 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
1027 default_diagnostic_start_span_fn (diagnostic_context
*context
,
1028 expanded_location exploc
)
1030 char *text
= diagnostic_get_location_text (context
, exploc
);
1031 pp_string (context
->printer
, text
);
1033 pp_newline (context
->printer
);
1037 default_diagnostic_finalizer (diagnostic_context
*context
,
1038 diagnostic_info
*diagnostic
,
1041 char *saved_prefix
= pp_take_prefix (context
->printer
);
1042 pp_set_prefix (context
->printer
, NULL
);
1043 pp_newline (context
->printer
);
1044 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
1045 pp_set_prefix (context
->printer
, saved_prefix
);
1046 pp_flush (context
->printer
);
1049 /* Interface to specify diagnostic kind overrides. Returns the
1050 previous setting, or DK_UNSPECIFIED if the parameters are out of
1051 range. If OPTION_INDEX is zero, the new setting is for all the
1054 diagnostic_classify_diagnostic (diagnostic_context
*context
,
1056 diagnostic_t new_kind
,
1059 diagnostic_t old_kind
;
1061 if (option_index
< 0
1062 || option_index
>= context
->n_opts
1063 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
1064 return DK_UNSPECIFIED
;
1066 old_kind
= context
->classify_diagnostic
[option_index
];
1068 /* Handle pragmas separately, since we need to keep track of *where*
1069 the pragmas were. */
1070 if (where
!= UNKNOWN_LOCATION
)
1074 /* Record the command-line status, so we can reset it back on DK_POP. */
1075 if (old_kind
== DK_UNSPECIFIED
)
1077 old_kind
= !context
->option_enabled (option_index
,
1079 context
->option_state
)
1080 ? DK_IGNORED
: (context
->warning_as_error_requested
1081 ? DK_ERROR
: DK_WARNING
);
1082 context
->classify_diagnostic
[option_index
] = old_kind
;
1085 for (i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1086 if (context
->classification_history
[i
].option
== option_index
)
1088 old_kind
= context
->classification_history
[i
].kind
;
1092 i
= context
->n_classification_history
;
1093 context
->classification_history
=
1094 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1095 * sizeof (diagnostic_classification_change_t
));
1096 context
->classification_history
[i
].location
= where
;
1097 context
->classification_history
[i
].option
= option_index
;
1098 context
->classification_history
[i
].kind
= new_kind
;
1099 context
->n_classification_history
++;
1102 context
->classify_diagnostic
[option_index
] = new_kind
;
1107 /* Save all diagnostic classifications in a stack. */
1109 diagnostic_push_diagnostics (diagnostic_context
*context
, location_t where ATTRIBUTE_UNUSED
)
1111 context
->push_list
= (int *) xrealloc (context
->push_list
, (context
->n_push
+ 1) * sizeof (int));
1112 context
->push_list
[context
->n_push
++] = context
->n_classification_history
;
1115 /* Restore the topmost classification set off the stack. If the stack
1116 is empty, revert to the state based on command line parameters. */
1118 diagnostic_pop_diagnostics (diagnostic_context
*context
, location_t where
)
1123 if (context
->n_push
)
1124 jump_to
= context
->push_list
[-- context
->n_push
];
1128 i
= context
->n_classification_history
;
1129 context
->classification_history
=
1130 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1131 * sizeof (diagnostic_classification_change_t
));
1132 context
->classification_history
[i
].location
= where
;
1133 context
->classification_history
[i
].option
= jump_to
;
1134 context
->classification_history
[i
].kind
= DK_POP
;
1135 context
->n_classification_history
++;
1138 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1139 escaping rules for -fdiagnostics-parseable-fixits. */
1142 print_escaped_string (pretty_printer
*pp
, const char *text
)
1147 pp_character (pp
, '"');
1148 for (const char *ch
= text
; *ch
; ch
++)
1153 /* Escape backslash as two backslashes. */
1154 pp_string (pp
, "\\\\");
1157 /* Escape tab as "\t". */
1158 pp_string (pp
, "\\t");
1161 /* Escape newline as "\n". */
1162 pp_string (pp
, "\\n");
1165 /* Escape doublequotes as \". */
1166 pp_string (pp
, "\\\"");
1170 pp_character (pp
, *ch
);
1172 /* Use octal for non-printable chars. */
1174 unsigned char c
= (*ch
& 0xff);
1175 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
1180 pp_character (pp
, '"');
1183 /* Implementation of -fdiagnostics-parseable-fixits and
1184 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1185 Print a machine-parseable version of all fixits in RICHLOC to PP,
1186 using COLUMN_UNIT to express columns.
1187 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1190 print_parseable_fixits (pretty_printer
*pp
, rich_location
*richloc
,
1191 enum diagnostics_column_unit column_unit
,
1195 gcc_assert (richloc
);
1197 char *saved_prefix
= pp_take_prefix (pp
);
1198 pp_set_prefix (pp
, NULL
);
1200 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
1202 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
1203 location_t start_loc
= hint
->get_start_loc ();
1204 expanded_location start_exploc
= expand_location (start_loc
);
1205 pp_string (pp
, "fix-it:");
1206 print_escaped_string (pp
, start_exploc
.file
);
1207 /* For compatibility with clang, print as a half-open range. */
1208 location_t next_loc
= hint
->get_next_loc ();
1209 expanded_location next_exploc
= expand_location (next_loc
);
1211 = convert_column_unit (column_unit
, tabstop
, start_exploc
);
1213 = convert_column_unit (column_unit
, tabstop
, next_exploc
);
1214 pp_printf (pp
, ":{%i:%i-%i:%i}:",
1215 start_exploc
.line
, start_col
,
1216 next_exploc
.line
, next_col
);
1217 print_escaped_string (pp
, hint
->get_string ());
1221 pp_set_prefix (pp
, saved_prefix
);
1224 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1227 get_any_inlining_info (diagnostic_context
*context
,
1228 diagnostic_info
*diagnostic
)
1230 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1232 if (context
->set_locations_cb
)
1233 /* Retrieve the locations into which the expression about to be
1234 diagnosed has been inlined, including those of all the callers
1235 all the way down the inlining stack. */
1236 context
->set_locations_cb (context
, diagnostic
);
1239 /* When there's no callback use just the one location provided
1240 by the caller of the diagnostic function. */
1241 location_t loc
= diagnostic_location (diagnostic
);
1242 ilocs
.safe_push (loc
);
1243 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1247 /* Update the kind of DIAGNOSTIC based on its location(s), including
1248 any of those in its inlining stack, relative to any
1249 #pragma GCC diagnostic
1250 directives recorded within CONTEXT.
1252 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1256 update_effective_level_from_pragmas (diagnostic_context
*context
,
1257 diagnostic_info
*diagnostic
)
1259 if (diagnostic
->m_iinfo
.m_allsyslocs
&& !context
->dc_warn_system_headers
)
1261 /* Ignore the diagnostic if all the inlined locations are
1262 in system headers and -Wno-system-headers is in effect. */
1263 diagnostic
->kind
= DK_IGNORED
;
1267 if (context
->n_classification_history
<= 0)
1268 return DK_UNSPECIFIED
;
1270 /* Iterate over the locations, checking the diagnostic disposition
1271 for the diagnostic at each. If it's explicitly set as opposed
1272 to unspecified, update the disposition for this instance of
1273 the diagnostic and return it. */
1274 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1276 /* FIXME: Stupid search. Optimize later. */
1277 for (int i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1279 const diagnostic_classification_change_t
&hist
1280 = context
->classification_history
[i
];
1282 location_t pragloc
= hist
.location
;
1283 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1286 if (hist
.kind
== (int) DK_POP
)
1288 /* Move on to the next region. */
1293 int option
= hist
.option
;
1294 /* The option 0 is for all the diagnostics. */
1295 if (option
== 0 || option
== diagnostic
->option_index
)
1297 diagnostic_t kind
= hist
.kind
;
1298 if (kind
!= DK_UNSPECIFIED
)
1299 diagnostic
->kind
= kind
;
1305 return DK_UNSPECIFIED
;
1308 /* Generate a URL string describing CWE. The caller is responsible for
1309 freeing the string. */
1312 get_cwe_url (int cwe
)
1314 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1317 /* If DIAGNOSTIC has a CWE identifier, print it.
1319 For example, if the diagnostic metadata associates it with CWE-119,
1320 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1321 description of the security issue. */
1324 print_any_cwe (diagnostic_context
*context
,
1325 const diagnostic_info
*diagnostic
)
1327 if (diagnostic
->metadata
== NULL
)
1330 int cwe
= diagnostic
->metadata
->get_cwe ();
1333 pretty_printer
*pp
= context
->printer
;
1334 char *saved_prefix
= pp_take_prefix (context
->printer
);
1335 pp_string (pp
, " [");
1336 pp_string (pp
, colorize_start (pp_show_color (pp
),
1337 diagnostic_kind_color
[diagnostic
->kind
]));
1338 if (pp
->url_format
!= URL_FORMAT_NONE
)
1340 char *cwe_url
= get_cwe_url (cwe
);
1341 pp_begin_url (pp
, cwe_url
);
1344 pp_printf (pp
, "CWE-%i", cwe
);
1345 pp_set_prefix (context
->printer
, saved_prefix
);
1346 if (pp
->url_format
!= URL_FORMAT_NONE
)
1348 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1349 pp_character (pp
, ']');
1353 /* If DIAGNOSTIC has any rules associated with it, print them.
1355 For example, if the diagnostic metadata associates it with a rule
1356 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1357 with any URL provided by the rule. */
1360 print_any_rules (diagnostic_context
*context
,
1361 const diagnostic_info
*diagnostic
)
1363 if (diagnostic
->metadata
== NULL
)
1366 for (unsigned idx
= 0; idx
< diagnostic
->metadata
->get_num_rules (); idx
++)
1368 const diagnostic_metadata::rule
&rule
1369 = diagnostic
->metadata
->get_rule (idx
);
1370 if (char *desc
= rule
.make_description ())
1372 pretty_printer
*pp
= context
->printer
;
1373 char *saved_prefix
= pp_take_prefix (context
->printer
);
1374 pp_string (pp
, " [");
1376 colorize_start (pp_show_color (pp
),
1377 diagnostic_kind_color
[diagnostic
->kind
]));
1379 if (pp
->url_format
!= URL_FORMAT_NONE
)
1381 url
= rule
.make_url ();
1383 pp_begin_url (pp
, url
);
1385 pp_string (pp
, desc
);
1386 pp_set_prefix (context
->printer
, saved_prefix
);
1387 if (pp
->url_format
!= URL_FORMAT_NONE
)
1391 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1392 pp_character (pp
, ']');
1398 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1399 printer, e.g. " [-Werror=uninitialized]".
1400 Subroutine of diagnostic_report_diagnostic. */
1403 print_option_information (diagnostic_context
*context
,
1404 const diagnostic_info
*diagnostic
,
1405 diagnostic_t orig_diag_kind
)
1409 option_text
= context
->option_name (context
, diagnostic
->option_index
,
1410 orig_diag_kind
, diagnostic
->kind
);
1414 char *option_url
= NULL
;
1415 if (context
->get_option_url
1416 && context
->printer
->url_format
!= URL_FORMAT_NONE
)
1417 option_url
= context
->get_option_url (context
,
1418 diagnostic
->option_index
);
1419 pretty_printer
*pp
= context
->printer
;
1420 pp_string (pp
, " [");
1421 pp_string (pp
, colorize_start (pp_show_color (pp
),
1422 diagnostic_kind_color
[diagnostic
->kind
]));
1424 pp_begin_url (pp
, option_url
);
1425 pp_string (pp
, option_text
);
1431 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1432 pp_character (pp
, ']');
1437 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1438 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1441 diagnostic_enabled (diagnostic_context
*context
,
1442 diagnostic_info
*diagnostic
)
1444 /* Update the inlining stack for this diagnostic. */
1445 get_any_inlining_info (context
, diagnostic
);
1447 /* Diagnostics with no option or -fpermissive are always enabled. */
1448 if (!diagnostic
->option_index
1449 || diagnostic
->option_index
== permissive_error_option (context
))
1452 /* This tests if the user provided the appropriate -Wfoo or
1454 if (! context
->option_enabled (diagnostic
->option_index
,
1456 context
->option_state
))
1459 /* This tests for #pragma diagnostic changes. */
1460 diagnostic_t diag_class
1461 = update_effective_level_from_pragmas (context
, diagnostic
);
1463 /* This tests if the user provided the appropriate -Werror=foo
1465 if (diag_class
== DK_UNSPECIFIED
1466 && (context
->classify_diagnostic
[diagnostic
->option_index
]
1469 = context
->classify_diagnostic
[diagnostic
->option_index
];
1471 /* This allows for future extensions, like temporarily disabling
1472 warnings for ranges of source code. */
1473 if (diagnostic
->kind
== DK_IGNORED
)
1479 /* Returns whether warning OPT is enabled at LOC. */
1482 warning_enabled_at (location_t loc
, int opt
)
1484 if (!diagnostic_report_warnings_p (global_dc
, loc
))
1487 rich_location
richloc (line_table
, loc
);
1488 diagnostic_info diagnostic
= {};
1489 diagnostic
.option_index
= opt
;
1490 diagnostic
.richloc
= &richloc
;
1491 diagnostic
.message
.m_richloc
= &richloc
;
1492 diagnostic
.kind
= DK_WARNING
;
1493 return diagnostic_enabled (global_dc
, &diagnostic
);
1496 /* Report a diagnostic message (an error or a warning) as specified by
1497 DC. This function is *the* subroutine in terms of which front-ends
1498 should implement their specific diagnostic handling modules. The
1499 front-end independent format specifiers are exactly those described
1500 in the documentation of output_format.
1501 Return true if a diagnostic was printed, false otherwise. */
1504 diagnostic_report_diagnostic (diagnostic_context
*context
,
1505 diagnostic_info
*diagnostic
)
1507 location_t location
= diagnostic_location (diagnostic
);
1508 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1510 /* Give preference to being able to inhibit warnings, before they
1511 get reclassified to something else. */
1512 bool report_warning_p
= true;
1513 if (diagnostic
->kind
== DK_WARNING
|| diagnostic
->kind
== DK_PEDWARN
)
1515 if (context
->dc_inhibit_warnings
)
1517 /* Remember the result of the overall system header warning setting
1518 but proceed to also check the inlining context. */
1519 report_warning_p
= diagnostic_report_warnings_p (context
, location
);
1520 if (!report_warning_p
&& diagnostic
->kind
== DK_PEDWARN
)
1524 if (diagnostic
->kind
== DK_PEDWARN
)
1526 diagnostic
->kind
= pedantic_warning_kind (context
);
1527 /* We do this to avoid giving the message for -pedantic-errors. */
1528 orig_diag_kind
= diagnostic
->kind
;
1531 if (diagnostic
->kind
== DK_NOTE
&& context
->inhibit_notes_p
)
1534 if (context
->lock
> 0)
1536 /* If we're reporting an ICE in the middle of some other error,
1537 try to flush out the previous error, then let this one
1538 through. Don't do this more than once. */
1539 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1540 && context
->lock
== 1)
1541 pp_newline_and_flush (context
->printer
);
1543 error_recursion (context
);
1546 /* If the user requested that warnings be treated as errors, so be
1547 it. Note that we do this before the next block so that
1548 individual warnings can be overridden back to warnings with
1550 if (context
->warning_as_error_requested
1551 && diagnostic
->kind
== DK_WARNING
)
1552 diagnostic
->kind
= DK_ERROR
;
1554 diagnostic
->message
.x_data
= &diagnostic
->x_data
;
1556 /* Check to see if the diagnostic is enabled at the location and
1557 not disabled by #pragma GCC diagnostic anywhere along the inlining
1559 if (!diagnostic_enabled (context
, diagnostic
))
1562 if (!report_warning_p
&& diagnostic
->m_iinfo
.m_allsyslocs
)
1563 /* Bail if the warning is not to be reported because all locations
1564 in the inlining stack (if there is one) are in system headers. */
1567 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1568 diagnostic_check_max_errors (context
);
1572 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1574 /* When not checking, ICEs are converted to fatal errors when an
1575 error has already occurred. This is counteracted by
1578 && (diagnostic_kind_count (context
, DK_ERROR
) > 0
1579 || diagnostic_kind_count (context
, DK_SORRY
) > 0)
1580 && !context
->abort_on_error
)
1583 = expand_location (diagnostic_location (diagnostic
));
1584 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1586 exit (ICE_EXIT_CODE
);
1588 if (context
->internal_error
)
1589 (*context
->internal_error
) (context
,
1590 diagnostic
->message
.format_spec
,
1591 diagnostic
->message
.args_ptr
);
1593 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1594 ++diagnostic_kind_count (context
, DK_WERROR
);
1596 ++diagnostic_kind_count (context
, diagnostic
->kind
);
1598 /* Is this the initial diagnostic within the stack of groups? */
1599 if (context
->diagnostic_group_emission_count
== 0)
1601 if (context
->begin_group_cb
)
1602 context
->begin_group_cb (context
);
1604 context
->diagnostic_group_emission_count
++;
1606 pp_format (context
->printer
, &diagnostic
->message
);
1607 (*diagnostic_starter (context
)) (context
, diagnostic
);
1608 pp_output_formatted_text (context
->printer
);
1609 if (context
->show_cwe
)
1610 print_any_cwe (context
, diagnostic
);
1611 if (context
->show_rules
)
1612 print_any_rules (context
, diagnostic
);
1613 if (context
->show_option_requested
)
1614 print_option_information (context
, diagnostic
, orig_diag_kind
);
1615 (*diagnostic_finalizer (context
)) (context
, diagnostic
, orig_diag_kind
);
1616 switch (context
->extra_output_kind
)
1620 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1621 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1622 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1624 pp_flush (context
->printer
);
1626 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1627 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1628 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1630 pp_flush (context
->printer
);
1633 diagnostic_action_after_output (context
, diagnostic
->kind
);
1634 diagnostic
->x_data
= NULL
;
1636 if (context
->edit_context_ptr
)
1637 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1638 context
->edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1642 diagnostic_show_any_path (context
, diagnostic
);
1647 /* Get the number of digits in the decimal representation of VALUE. */
1650 num_digits (int value
)
1652 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1653 using floating point. */
1654 gcc_assert (value
>= 0);
1668 /* Given a partial pathname as input, return another pathname that
1669 shares no directory elements with the pathname of __FILE__. This
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'. */
1674 trim_filename (const char *name
)
1676 static const char this_file
[] = __FILE__
;
1677 const char *p
= name
, *q
= this_file
;
1679 /* First skip any "../" in each filename. This allows us to give a proper
1680 reference to a file in a subdirectory. */
1681 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1684 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1687 /* Now skip any parts the two filenames have in common. */
1688 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1691 /* Now go backwards until the previous directory separator. */
1692 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1698 /* Standard error reporting routines in increasing order of severity.
1699 All of these take arguments like printf. */
1701 /* Text to be emitted verbatim to the error message stream; this
1702 produces no prefix and disables line-wrapping. Use rarely. */
1704 verbatim (const char *gmsgid
, ...)
1709 va_start (ap
, gmsgid
);
1710 text
.err_no
= errno
;
1711 text
.args_ptr
= &ap
;
1712 text
.format_spec
= _(gmsgid
);
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
->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
= permissive_error_option (global_dc
);
1765 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1766 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1767 diagnostic
.option_index
= opt
;
1769 diagnostic
.metadata
= metadata
;
1770 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1773 /* Implement inform_n, warning_n, and error_n, as documented and
1776 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1777 int opt
, unsigned HOST_WIDE_INT n
,
1778 const char *singular_gmsgid
,
1779 const char *plural_gmsgid
,
1780 va_list *ap
, diagnostic_t kind
)
1782 diagnostic_info diagnostic
;
1785 if (sizeof n
<= sizeof gtn
)
1788 /* Use the largest number ngettext can handle, otherwise
1789 preserve the six least significant decimal digits for
1790 languages where the plural form depends on them. */
1791 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1793 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1794 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1795 if (kind
== DK_WARNING
)
1796 diagnostic
.option_index
= opt
;
1797 diagnostic
.metadata
= metadata
;
1798 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1801 /* Wrapper around diagnostic_impl taking a variable argument list. */
1804 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1805 const char *gmsgid
, ...)
1807 auto_diagnostic_group d
;
1809 va_start (ap
, gmsgid
);
1810 rich_location
richloc (line_table
, location
);
1811 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1816 /* As above, but for rich_location *. */
1819 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1820 const char *gmsgid
, ...)
1822 auto_diagnostic_group d
;
1824 va_start (ap
, gmsgid
);
1825 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1830 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1833 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1834 const char *gmsgid
, va_list *ap
)
1836 rich_location
richloc (line_table
, location
);
1837 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1840 /* An informative note at LOCATION. Use this for additional details on an error
1843 inform (location_t location
, const char *gmsgid
, ...)
1845 auto_diagnostic_group d
;
1847 va_start (ap
, gmsgid
);
1848 rich_location
richloc (line_table
, location
);
1849 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1853 /* Same as "inform" above, but at RICHLOC. */
1855 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1857 gcc_assert (richloc
);
1859 auto_diagnostic_group d
;
1861 va_start (ap
, gmsgid
);
1862 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1866 /* An informative note at LOCATION. Use this for additional details on an
1869 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1870 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1873 va_start (ap
, plural_gmsgid
);
1874 auto_diagnostic_group d
;
1875 rich_location
richloc (line_table
, location
);
1876 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1881 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1882 to the relevant language specification but is likely to be buggy anyway.
1883 Returns true if the warning was printed, false if it was inhibited. */
1885 warning (int opt
, const char *gmsgid
, ...)
1887 auto_diagnostic_group d
;
1889 va_start (ap
, gmsgid
);
1890 rich_location
richloc (line_table
, input_location
);
1891 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1896 /* A warning at LOCATION. Use this for code which is correct according to the
1897 relevant language specification but is likely to be buggy anyway.
1898 Returns true if the warning was printed, false if it was inhibited. */
1901 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1903 auto_diagnostic_group d
;
1905 va_start (ap
, gmsgid
);
1906 rich_location
richloc (line_table
, location
);
1907 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1912 /* Same as "warning at" above, but using RICHLOC. */
1915 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1917 gcc_assert (richloc
);
1919 auto_diagnostic_group d
;
1921 va_start (ap
, gmsgid
);
1922 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1927 /* Same as "warning at" above, but using METADATA. */
1930 warning_meta (rich_location
*richloc
,
1931 const diagnostic_metadata
&metadata
,
1932 int opt
, const char *gmsgid
, ...)
1934 gcc_assert (richloc
);
1936 auto_diagnostic_group d
;
1938 va_start (ap
, gmsgid
);
1940 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1946 /* Same as warning_n plural variant below, but using RICHLOC. */
1949 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1950 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1952 gcc_assert (richloc
);
1954 auto_diagnostic_group d
;
1956 va_start (ap
, plural_gmsgid
);
1957 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1958 singular_gmsgid
, plural_gmsgid
,
1964 /* A warning at LOCATION. Use this for code which is correct according to the
1965 relevant language specification but is likely to be buggy anyway.
1966 Returns true if the warning was printed, false if it was inhibited. */
1969 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1970 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1972 auto_diagnostic_group d
;
1974 va_start (ap
, plural_gmsgid
);
1975 rich_location
richloc (line_table
, location
);
1976 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1977 singular_gmsgid
, plural_gmsgid
,
1983 /* A "pedantic" warning at LOCATION: issues a warning unless
1984 -pedantic-errors was given on the command line, in which case it
1985 issues an error. Use this for diagnostics required by the relevant
1986 language standard, if you have chosen not to make them errors.
1988 Note that these diagnostics are issued independent of the setting
1989 of the -Wpedantic command-line switch. To get a warning enabled
1990 only with that switch, use either "if (pedantic) pedwarn
1991 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1992 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1994 Returns true if the warning was printed, false if it was inhibited. */
1997 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
1999 auto_diagnostic_group d
;
2001 va_start (ap
, gmsgid
);
2002 rich_location
richloc (line_table
, location
);
2003 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
2008 /* Same as pedwarn above, but using RICHLOC. */
2011 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
2013 gcc_assert (richloc
);
2015 auto_diagnostic_group d
;
2017 va_start (ap
, gmsgid
);
2018 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
2023 /* A "permissive" error at LOCATION: issues an error unless
2024 -fpermissive was given on the command line, in which case it issues
2025 a warning. Use this for things that really should be errors but we
2026 want to support legacy code.
2028 Returns true if the warning was printed, false if it was inhibited. */
2031 permerror (location_t location
, const char *gmsgid
, ...)
2033 auto_diagnostic_group d
;
2035 va_start (ap
, gmsgid
);
2036 rich_location
richloc (line_table
, location
);
2037 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2042 /* Same as "permerror" above, but at RICHLOC. */
2045 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
2047 gcc_assert (richloc
);
2049 auto_diagnostic_group d
;
2051 va_start (ap
, gmsgid
);
2052 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2057 /* A hard error: the code is definitely ill-formed, and an object file
2058 will not be produced. */
2060 error (const char *gmsgid
, ...)
2062 auto_diagnostic_group d
;
2064 va_start (ap
, gmsgid
);
2065 rich_location
richloc (line_table
, input_location
);
2066 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2070 /* A hard error: the code is definitely ill-formed, and an object file
2071 will not be produced. */
2073 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
2074 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
2076 auto_diagnostic_group d
;
2078 va_start (ap
, plural_gmsgid
);
2079 rich_location
richloc (line_table
, location
);
2080 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
2085 /* Same as above, but use location LOC instead of input_location. */
2087 error_at (location_t loc
, const char *gmsgid
, ...)
2089 auto_diagnostic_group d
;
2091 va_start (ap
, gmsgid
);
2092 rich_location
richloc (line_table
, loc
);
2093 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2097 /* Same as above, but use RICH_LOC. */
2100 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
2102 gcc_assert (richloc
);
2104 auto_diagnostic_group d
;
2106 va_start (ap
, gmsgid
);
2107 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2111 /* "Sorry, not implemented." Use for a language feature which is
2112 required by the relevant specification but not implemented by GCC.
2113 An object file will not be produced. */
2115 sorry (const char *gmsgid
, ...)
2117 auto_diagnostic_group d
;
2119 va_start (ap
, gmsgid
);
2120 rich_location
richloc (line_table
, input_location
);
2121 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2125 /* Same as above, but use location LOC instead of input_location. */
2127 sorry_at (location_t loc
, const char *gmsgid
, ...)
2129 auto_diagnostic_group d
;
2131 va_start (ap
, gmsgid
);
2132 rich_location
richloc (line_table
, loc
);
2133 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2137 /* Return true if an error or a "sorry" has been seen. Various
2138 processing is disabled after errors. */
2142 return errorcount
|| sorrycount
;
2145 /* An error which is severe enough that we make no attempt to
2146 continue. Do not use this for internal consistency checks; that's
2147 internal_error. Use of this function should be rare. */
2149 fatal_error (location_t loc
, const char *gmsgid
, ...)
2151 auto_diagnostic_group d
;
2153 va_start (ap
, gmsgid
);
2154 rich_location
richloc (line_table
, loc
);
2155 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
2161 /* An internal consistency check has failed. We make no attempt to
2164 internal_error (const char *gmsgid
, ...)
2166 auto_diagnostic_group d
;
2168 va_start (ap
, gmsgid
);
2169 rich_location
richloc (line_table
, input_location
);
2170 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
2176 /* Like internal_error, but no backtrace will be printed. Used when
2177 the internal error does not happen at the current location, but happened
2180 internal_error_no_backtrace (const char *gmsgid
, ...)
2182 auto_diagnostic_group d
;
2184 va_start (ap
, gmsgid
);
2185 rich_location
richloc (line_table
, input_location
);
2186 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
2192 /* Emit DIAGRAM to CONTEXT, respecting the output format. */
2195 diagnostic_emit_diagram (diagnostic_context
*context
,
2196 const diagnostic_diagram
&diagram
)
2198 if (context
->m_diagrams
.m_theme
== nullptr)
2201 if (context
->m_diagrams
.m_emission_cb
)
2203 context
->m_diagrams
.m_emission_cb (context
, diagram
);
2207 /* Default implementation. */
2208 char *saved_prefix
= pp_take_prefix (context
->printer
);
2209 pp_set_prefix (context
->printer
, NULL
);
2210 /* Use a newline before and after and a two-space indent
2211 to make the diagram stand out a little from the wall of text. */
2212 pp_newline (context
->printer
);
2213 diagram
.get_canvas ().print_to_pp (context
->printer
, " ");
2214 pp_newline (context
->printer
);
2215 pp_set_prefix (context
->printer
, saved_prefix
);
2216 pp_flush (context
->printer
);
2219 /* Special case error functions. Most are implemented in terms of the
2220 above, or should be. */
2222 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2223 runs its second argument through gettext. */
2225 fnotice (FILE *file
, const char *cmsgid
, ...)
2229 va_start (ap
, cmsgid
);
2230 vfprintf (file
, _(cmsgid
), ap
);
2234 /* Inform the user that an error occurred while trying to report some
2235 other error. This indicates catastrophic internal inconsistencies,
2236 so give up now. But do try to flush out the previous error.
2237 This mustn't use internal_error, that will cause infinite recursion. */
2240 error_recursion (diagnostic_context
*context
)
2242 if (context
->lock
< 3)
2243 pp_newline_and_flush (context
->printer
);
2246 "internal compiler error: error reporting routines re-entered.\n");
2248 /* Call diagnostic_action_after_output to get the "please submit a bug
2250 diagnostic_action_after_output (context
, DK_ICE
);
2252 /* Do not use gcc_unreachable here; that goes through internal_error
2253 and therefore would cause infinite recursion. */
2257 /* Report an internal compiler error in a friendly manner. This is
2258 the function that gets called upon use of abort() in the source
2259 code generally, thanks to a special macro. */
2262 fancy_abort (const char *file
, int line
, const char *function
)
2264 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2265 internal_error will crash internally in a way that prevents a
2266 useful message reaching the user.
2267 This can happen with libgccjit in the case of gcc_assert failures
2268 that occur outside of the libgccjit mutex that guards the rest of
2269 gcc's state, including global_dc (when global_dc may not be
2270 initialized yet, or might be in use by another thread).
2271 Handle such cases as gracefully as possible by falling back to a
2272 minimal abort handler that only relies on i18n. */
2273 if (global_dc
->printer
== NULL
)
2275 /* Print the error message. */
2276 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
2277 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
2278 fputc ('\n', stderr
);
2280 /* Attempt to print a backtrace. */
2281 struct backtrace_state
*state
2282 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
2285 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
2288 /* We can't call warn_if_plugins or emergency_dump_function as these
2289 rely on GCC state that might not be initialized, or might be in
2290 use by another thread. */
2292 /* Abort the process. */
2296 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2299 /* class auto_diagnostic_group. */
2301 /* Constructor: "push" this group into global_dc. */
2303 auto_diagnostic_group::auto_diagnostic_group ()
2305 global_dc
->diagnostic_group_nesting_depth
++;
2308 /* Destructor: "pop" this group from global_dc. */
2310 auto_diagnostic_group::~auto_diagnostic_group ()
2312 if (--global_dc
->diagnostic_group_nesting_depth
== 0)
2314 /* Handle the case where we've popped the final diagnostic group.
2315 If any diagnostics were emitted, give the context a chance
2317 if (global_dc
->diagnostic_group_emission_count
> 0)
2319 if (global_dc
->end_group_cb
)
2320 global_dc
->end_group_cb (global_dc
);
2322 global_dc
->diagnostic_group_emission_count
= 0;
2326 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2327 file-based output formats. */
2330 diagnostic_output_format_init (diagnostic_context
*context
,
2331 const char *base_file_name
,
2332 enum diagnostics_output_format format
)
2338 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT
:
2339 /* The default; do nothing. */
2342 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR
:
2343 diagnostic_output_format_init_json_stderr (context
);
2346 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
:
2347 diagnostic_output_format_init_json_file (context
, base_file_name
);
2350 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR
:
2351 diagnostic_output_format_init_sarif_stderr (context
);
2354 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
:
2355 diagnostic_output_format_init_sarif_file (context
, base_file_name
);
2360 /* Initialize CONTEXT->m_diagrams based on CHARSET.
2361 Specifically, make a text_art::theme object for m_diagrams.m_theme,
2362 (or NULL for "no diagrams"). */
2365 diagnostics_text_art_charset_init (diagnostic_context
*context
,
2366 enum diagnostic_text_art_charset charset
)
2368 delete context
->m_diagrams
.m_theme
;
2374 case DIAGNOSTICS_TEXT_ART_CHARSET_NONE
:
2375 context
->m_diagrams
.m_theme
= NULL
;
2378 case DIAGNOSTICS_TEXT_ART_CHARSET_ASCII
:
2379 context
->m_diagrams
.m_theme
= new text_art::ascii_theme ();
2382 case DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE
:
2383 context
->m_diagrams
.m_theme
= new text_art::unicode_theme ();
2386 case DIAGNOSTICS_TEXT_ART_CHARSET_EMOJI
:
2387 context
->m_diagrams
.m_theme
= new text_art::emoji_theme ();
2392 /* Implementation of diagnostic_path::num_events vfunc for
2393 simple_diagnostic_path: simply get the number of events in the vec. */
2396 simple_diagnostic_path::num_events () const
2398 return m_events
.length ();
2401 /* Implementation of diagnostic_path::get_event vfunc for
2402 simple_diagnostic_path: simply return the event in the vec. */
2404 const diagnostic_event
&
2405 simple_diagnostic_path::get_event (int idx
) const
2407 return *m_events
[idx
];
2410 /* Add an event to this path at LOC within function FNDECL at
2413 Use m_context's printer to format FMT, as the text of the new
2416 Return the id of the new event. */
2418 diagnostic_event_id_t
2419 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2420 const char *fmt
, ...)
2422 pretty_printer
*pp
= m_event_pp
;
2423 pp_clear_output_area (pp
);
2426 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2432 ti
.format_spec
= _(fmt
);
2436 ti
.m_richloc
= &rich_loc
;
2438 pp_format (pp
, &ti
);
2439 pp_output_formatted_text (pp
);
2443 simple_diagnostic_event
*new_event
2444 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2445 m_events
.safe_push (new_event
);
2447 pp_clear_output_area (pp
);
2449 return diagnostic_event_id_t (m_events
.length () - 1);
2452 /* struct simple_diagnostic_event. */
2454 /* simple_diagnostic_event's ctor. */
2456 simple_diagnostic_event::simple_diagnostic_event (location_t loc
,
2460 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
))
2464 /* simple_diagnostic_event's dtor. */
2466 simple_diagnostic_event::~simple_diagnostic_event ()
2471 /* Print PATH by emitting a dummy "note" associated with it. */
2474 void debug (diagnostic_path
*path
)
2476 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2477 richloc
.set_path (path
);
2478 inform (&richloc
, "debug path");
2481 /* Really call the system 'abort'. This has to go right at the end of
2482 this file, so that there are no functions after it that call abort
2483 and get the system abort instead of our macro. */
2493 namespace selftest
{
2495 /* Helper function for test_print_escaped_string. */
2498 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2502 print_escaped_string (&pp
, input
);
2503 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2506 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2507 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2509 /* Tests of print_escaped_string. */
2512 test_print_escaped_string ()
2515 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2517 /* Non-empty string. */
2518 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2520 /* Various things that need to be escaped: */
2522 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2525 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2528 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2531 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2534 /* Non-printable characters: BEL: '\a': 0x07 */
2535 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2537 /* Non-printable characters: vertical tab: '\v': 0x0b */
2538 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2542 /* Tests of print_parseable_fixits. */
2544 /* Verify that print_parseable_fixits emits the empty string if there
2548 test_print_parseable_fixits_none ()
2551 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2553 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2554 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2557 /* Verify that print_parseable_fixits does the right thing if there
2558 is an insertion fixit hint. */
2561 test_print_parseable_fixits_insert ()
2564 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2566 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2567 linemap_line_start (line_table
, 5, 100);
2568 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2569 location_t where
= linemap_position_for_column (line_table
, 10);
2570 richloc
.add_fixit_insert_before (where
, "added content");
2572 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2573 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2574 pp_formatted_text (&pp
));
2577 /* Verify that print_parseable_fixits does the right thing if there
2578 is an removal fixit hint. */
2581 test_print_parseable_fixits_remove ()
2584 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2586 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2587 linemap_line_start (line_table
, 5, 100);
2588 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2590 where
.m_start
= linemap_position_for_column (line_table
, 10);
2591 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2592 richloc
.add_fixit_remove (where
);
2594 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2595 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2596 pp_formatted_text (&pp
));
2599 /* Verify that print_parseable_fixits does the right thing if there
2600 is an replacement fixit hint. */
2603 test_print_parseable_fixits_replace ()
2606 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2608 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2609 linemap_line_start (line_table
, 5, 100);
2610 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2612 where
.m_start
= linemap_position_for_column (line_table
, 10);
2613 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2614 richloc
.add_fixit_replace (where
, "replacement");
2616 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2617 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2618 pp_formatted_text (&pp
));
2621 /* Verify that print_parseable_fixits correctly handles
2622 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2625 test_print_parseable_fixits_bytes_vs_display_columns ()
2627 line_table_test ltt
;
2628 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2630 /* 1-based byte offsets: 12345677778888999900001234567. */
2631 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2632 /* 1-based display cols: 123456[......7-8.....]9012345. */
2633 const int tabstop
= 8;
2635 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2636 const char *const fname
= tmp
.get_filename ();
2638 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2639 linemap_line_start (line_table
, 1, 100);
2640 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2642 where
.m_start
= linemap_position_for_column (line_table
, 12);
2643 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2644 richloc
.add_fixit_replace (where
, "color");
2647 pretty_printer tmp_pp
;
2648 print_escaped_string (&tmp_pp
, fname
);
2649 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2651 const int buf_len
= strlen (escaped_fname
) + 100;
2652 char *const expected
= XNEWVEC (char, buf_len
);
2656 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2658 snprintf (expected
, buf_len
,
2659 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2660 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2664 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2666 snprintf (expected
, buf_len
,
2667 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2668 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2671 XDELETEVEC (expected
);
2672 free (escaped_fname
);
2676 diagnostic_get_location_text (..., SHOW_COLUMN)
2677 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2678 colorization disabled. */
2681 assert_location_text (const char *expected_loc_text
,
2682 const char *filename
, int line
, int column
,
2685 enum diagnostics_column_unit column_unit
2686 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2688 test_diagnostic_context dc
;
2689 dc
.show_column
= show_column
;
2690 dc
.column_unit
= column_unit
;
2691 dc
.column_origin
= origin
;
2693 expanded_location xloc
;
2694 xloc
.file
= filename
;
2696 xloc
.column
= column
;
2700 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2701 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2702 free (actual_loc_text
);
2705 /* Verify that diagnostic_get_location_text works as expected. */
2708 test_diagnostic_get_location_text ()
2710 const char *old_progname
= progname
;
2711 progname
= "PROGNAME";
2712 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2713 char *built_in_colon
= concat (special_fname_builtin (), ":", (char *) 0);
2714 assert_location_text (built_in_colon
, special_fname_builtin (),
2716 free (built_in_colon
);
2717 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2718 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2719 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2720 for (int origin
= 0; origin
!= 2; ++origin
)
2721 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2722 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2723 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2724 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2726 maybe_line_and_column (INT_MAX
, INT_MAX
);
2727 maybe_line_and_column (INT_MIN
, INT_MIN
);
2730 /* In order to test display columns vs byte columns, we need to create a
2731 file for location_get_source_line() to read. */
2733 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2734 const int line_bytes
= strlen (content
) - 1;
2735 const int def_tabstop
= 8;
2736 const cpp_char_column_policy
policy (def_tabstop
, cpp_wcwidth
);
2737 const int display_width
= cpp_display_width (content
, line_bytes
, policy
);
2738 ASSERT_EQ (line_bytes
- 2, display_width
);
2739 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2740 const char *const fname
= tmp
.get_filename ();
2741 const int buf_len
= strlen (fname
) + 16;
2742 char *const expected
= XNEWVEC (char, buf_len
);
2744 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2745 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2746 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2748 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2749 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2750 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2752 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2753 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2754 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2756 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2757 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2758 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2760 XDELETEVEC (expected
);
2764 progname
= old_progname
;
2767 /* Selftest for num_digits. */
2772 ASSERT_EQ (1, num_digits (0));
2773 ASSERT_EQ (1, num_digits (9));
2774 ASSERT_EQ (2, num_digits (10));
2775 ASSERT_EQ (2, num_digits (99));
2776 ASSERT_EQ (3, num_digits (100));
2777 ASSERT_EQ (3, num_digits (999));
2778 ASSERT_EQ (4, num_digits (1000));
2779 ASSERT_EQ (4, num_digits (9999));
2780 ASSERT_EQ (5, num_digits (10000));
2781 ASSERT_EQ (5, num_digits (99999));
2782 ASSERT_EQ (6, num_digits (100000));
2783 ASSERT_EQ (6, num_digits (999999));
2784 ASSERT_EQ (7, num_digits (1000000));
2785 ASSERT_EQ (7, num_digits (9999999));
2786 ASSERT_EQ (8, num_digits (10000000));
2787 ASSERT_EQ (8, num_digits (99999999));
2790 /* Run all of the selftests within this file. */
2793 c_diagnostic_cc_tests ()
2795 test_print_escaped_string ();
2796 test_print_parseable_fixits_none ();
2797 test_print_parseable_fixits_insert ();
2798 test_print_parseable_fixits_remove ();
2799 test_print_parseable_fixits_replace ();
2800 test_print_parseable_fixits_bytes_vs_display_columns ();
2801 test_diagnostic_get_location_text ();
2806 } // namespace selftest
2808 #endif /* #if CHECKING_P */
2811 # pragma GCC diagnostic pop