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
27 #include "coretypes.h"
31 #include "backtrace.h"
32 #include "diagnostic.h"
33 #include "diagnostic-color.h"
34 #include "diagnostic-url.h"
35 #include "diagnostic-metadata.h"
36 #include "diagnostic-path.h"
37 #include "diagnostic-client-data-hooks.h"
38 #include "edit-context.h"
40 #include "selftest-diagnostic.h"
48 #ifdef GWINSZ_IN_SYS_IOCTL
49 # include <sys/ioctl.h>
52 /* Disable warnings about quoting issues in the pp_xxx calls below
53 that (intentionally) don't follow GCC diagnostic conventions. */
55 # pragma GCC diagnostic push
56 # pragma GCC diagnostic ignored "-Wformat-diag"
59 #define pedantic_warning_kind(DC) \
60 ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
61 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
62 #define permissive_error_option(DC) ((DC)->opt_permissive)
65 static bool diagnostic_impl (rich_location
*, const diagnostic_metadata
*,
67 va_list *, diagnostic_t
) ATTRIBUTE_GCC_DIAG(4,0);
68 static bool diagnostic_n_impl (rich_location
*, const diagnostic_metadata
*,
69 int, unsigned HOST_WIDE_INT
,
70 const char *, const char *, va_list *,
71 diagnostic_t
) ATTRIBUTE_GCC_DIAG(6,0);
73 static void error_recursion (diagnostic_context
*) ATTRIBUTE_NORETURN
;
74 static void real_abort (void) ATTRIBUTE_NORETURN
;
76 /* Name of program invoked, sans directories. */
80 /* A diagnostic_context surrogate for stderr. */
81 static diagnostic_context global_diagnostic_context
;
82 diagnostic_context
*global_dc
= &global_diagnostic_context
;
84 /* Return a malloc'd string containing MSG formatted a la printf. The
85 caller is responsible for freeing the memory. */
87 build_message_string (const char *msg
, ...)
93 str
= xvasprintf (msg
, ap
);
99 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
101 file_name_as_prefix (diagnostic_context
*context
, const char *f
)
104 = colorize_start (pp_show_color (context
->printer
), "locus");
105 const char *locus_ce
= colorize_stop (pp_show_color (context
->printer
));
106 return build_message_string ("%s%s:%s ", locus_cs
, f
, locus_ce
);
111 /* Return the value of the getenv("COLUMNS") as an integer. If the
112 value is not set to a positive integer, use ioctl to get the
113 terminal width. If it fails, return INT_MAX. */
115 get_terminal_width (void)
117 const char * s
= getenv ("COLUMNS");
127 if (ioctl (0, TIOCGWINSZ
, &w
) == 0 && w
.ws_col
> 0)
134 /* Set caret_max_width to value. */
136 diagnostic_set_caret_max_width (diagnostic_context
*context
, int value
)
138 /* One minus to account for the leading empty space. */
139 value
= value
? value
- 1
140 : (isatty (fileno (pp_buffer (context
->printer
)->stream
))
141 ? get_terminal_width () - 1: INT_MAX
);
146 context
->caret_max_width
= value
;
149 /* Default implementation of final_cb. */
152 default_diagnostic_final_cb (diagnostic_context
*context
)
154 /* Some of the errors may actually have been warnings. */
155 if (diagnostic_kind_count (context
, DK_WERROR
))
157 /* -Werror was given. */
158 if (context
->warning_as_error_requested
)
159 pp_verbatim (context
->printer
,
160 _("%s: all warnings being treated as errors"),
162 /* At least one -Werror= was given. */
164 pp_verbatim (context
->printer
,
165 _("%s: some warnings being treated as errors"),
167 pp_newline_and_flush (context
->printer
);
171 /* Initialize the diagnostic message outputting machinery. */
173 diagnostic_initialize (diagnostic_context
*context
, int n_opts
)
177 /* Allocate a basic pretty-printer. Clients will replace this a
178 much more elaborated pretty-printer if they wish. */
179 context
->printer
= XNEW (pretty_printer
);
180 new (context
->printer
) pretty_printer ();
182 memset (context
->diagnostic_count
, 0, sizeof context
->diagnostic_count
);
183 context
->warning_as_error_requested
= false;
184 context
->n_opts
= n_opts
;
185 context
->classify_diagnostic
= XNEWVEC (diagnostic_t
, n_opts
);
186 for (i
= 0; i
< n_opts
; i
++)
187 context
->classify_diagnostic
[i
] = DK_UNSPECIFIED
;
188 context
->show_caret
= false;
189 diagnostic_set_caret_max_width (context
, pp_line_cutoff (context
->printer
));
190 for (i
= 0; i
< rich_location::STATICALLY_ALLOCATED_RANGES
; i
++)
191 context
->caret_chars
[i
] = '^';
192 context
->show_cwe
= false;
193 context
->show_rules
= false;
194 context
->path_format
= DPF_NONE
;
195 context
->show_path_depths
= false;
196 context
->show_option_requested
= false;
197 context
->abort_on_error
= false;
198 context
->show_column
= false;
199 context
->pedantic_errors
= false;
200 context
->permissive
= false;
201 context
->opt_permissive
= 0;
202 context
->fatal_errors
= false;
203 context
->dc_inhibit_warnings
= false;
204 context
->dc_warn_system_headers
= false;
205 context
->max_errors
= 0;
206 context
->internal_error
= NULL
;
207 diagnostic_starter (context
) = default_diagnostic_starter
;
208 context
->start_span
= default_diagnostic_start_span_fn
;
209 diagnostic_finalizer (context
) = default_diagnostic_finalizer
;
210 context
->option_enabled
= NULL
;
211 context
->option_state
= NULL
;
212 context
->option_name
= NULL
;
213 context
->get_option_url
= NULL
;
214 context
->last_location
= UNKNOWN_LOCATION
;
215 context
->last_module
= 0;
216 context
->x_data
= NULL
;
218 context
->inhibit_notes_p
= false;
219 context
->colorize_source_p
= false;
220 context
->show_labels_p
= false;
221 context
->show_line_numbers_p
= false;
222 context
->min_margin_width
= 0;
223 context
->show_ruler_p
= false;
224 context
->report_bug
= false;
226 if (const char *var
= getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
228 if (!strcmp (var
, "fixits-v1"))
229 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
;
230 else if (!strcmp (var
, "fixits-v2"))
231 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
;
232 /* Silently ignore unrecognized values. */
234 context
->column_unit
= DIAGNOSTICS_COLUMN_UNIT_DISPLAY
;
235 context
->column_origin
= 1;
236 context
->tabstop
= 8;
237 context
->escape_format
= DIAGNOSTICS_ESCAPE_FORMAT_UNICODE
;
238 context
->edit_context_ptr
= NULL
;
239 context
->diagnostic_group_nesting_depth
= 0;
240 context
->diagnostic_group_emission_count
= 0;
241 context
->begin_group_cb
= NULL
;
242 context
->end_group_cb
= NULL
;
243 context
->final_cb
= default_diagnostic_final_cb
;
244 context
->ice_handler_cb
= NULL
;
245 context
->includes_seen
= NULL
;
246 context
->m_client_data_hooks
= NULL
;
249 /* Maybe initialize the color support. We require clients to do this
250 explicitly, since most clients don't want color. When called
251 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
254 diagnostic_color_init (diagnostic_context
*context
, int value
/*= -1 */)
256 /* value == -1 is the default value. */
259 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
260 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
261 otherwise default to -fdiagnostics-color=never, for other
262 values default to that
263 -fdiagnostics-color={never,auto,always}. */
264 if (DIAGNOSTICS_COLOR_DEFAULT
== -1)
266 if (!getenv ("GCC_COLORS"))
268 value
= DIAGNOSTICS_COLOR_AUTO
;
271 value
= DIAGNOSTICS_COLOR_DEFAULT
;
273 pp_show_color (context
->printer
)
274 = colorize_init ((diagnostic_color_rule_t
) value
);
277 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
280 diagnostic_urls_init (diagnostic_context
*context
, int value
/*= -1 */)
282 /* value == -1 is the default value. */
285 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
286 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
287 environment, otherwise default to -fdiagnostics-urls=never,
288 for other values default to that
289 -fdiagnostics-urls={never,auto,always}. */
290 if (DIAGNOSTICS_URLS_DEFAULT
== -1)
292 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
294 value
= DIAGNOSTICS_URL_AUTO
;
297 value
= DIAGNOSTICS_URLS_DEFAULT
;
300 context
->printer
->url_format
301 = determine_url_format ((diagnostic_url_rule_t
) value
);
304 /* Create the file_cache, if not already created, and tell it how to
305 translate files on input. */
306 void diagnostic_initialize_input_context (diagnostic_context
*context
,
307 diagnostic_input_charset_callback ccb
,
308 bool should_skip_bom
)
310 if (!context
->m_file_cache
)
311 context
->m_file_cache
= new file_cache
;
312 context
->m_file_cache
->initialize_input_context (ccb
, should_skip_bom
);
315 /* Do any cleaning up required after the last diagnostic is emitted. */
318 diagnostic_finish (diagnostic_context
*context
)
320 if (context
->final_cb
)
321 context
->final_cb (context
);
323 diagnostic_file_cache_fini ();
325 XDELETEVEC (context
->classify_diagnostic
);
326 context
->classify_diagnostic
= NULL
;
328 /* diagnostic_initialize allocates context->printer using XNEW
329 and placement-new. */
330 context
->printer
->~pretty_printer ();
331 XDELETE (context
->printer
);
332 context
->printer
= NULL
;
334 if (context
->edit_context_ptr
)
336 delete context
->edit_context_ptr
;
337 context
->edit_context_ptr
= NULL
;
340 if (context
->includes_seen
)
342 delete context
->includes_seen
;
343 context
->includes_seen
= nullptr;
346 if (context
->m_client_data_hooks
)
348 delete context
->m_client_data_hooks
;
349 context
->m_client_data_hooks
= NULL
;
353 /* Initialize DIAGNOSTIC, where the message MSG has already been
356 diagnostic_set_info_translated (diagnostic_info
*diagnostic
, const char *msg
,
357 va_list *args
, rich_location
*richloc
,
360 gcc_assert (richloc
);
361 diagnostic
->message
.err_no
= errno
;
362 diagnostic
->message
.args_ptr
= args
;
363 diagnostic
->message
.format_spec
= msg
;
364 diagnostic
->message
.m_richloc
= richloc
;
365 diagnostic
->richloc
= richloc
;
366 diagnostic
->metadata
= NULL
;
367 diagnostic
->kind
= kind
;
368 diagnostic
->option_index
= 0;
371 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
374 diagnostic_set_info (diagnostic_info
*diagnostic
, const char *gmsgid
,
375 va_list *args
, rich_location
*richloc
,
378 gcc_assert (richloc
);
379 diagnostic_set_info_translated (diagnostic
, _(gmsgid
), args
, richloc
, kind
);
382 static const char *const diagnostic_kind_color
[] = {
383 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
384 #include "diagnostic.def"
385 #undef DEFINE_DIAGNOSTIC_KIND
389 /* Get a color name for diagnostics of type KIND
390 Result could be NULL. */
393 diagnostic_get_color_for_kind (diagnostic_t kind
)
395 return diagnostic_kind_color
[kind
];
398 /* Given an expanded_location, convert the column (which is in 1-based bytes)
399 to the requested units, without converting the origin.
400 Return -1 if the column is invalid (<= 0). */
403 convert_column_unit (enum diagnostics_column_unit column_unit
,
415 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY
:
417 cpp_char_column_policy
policy (tabstop
, cpp_wcwidth
);
418 return location_compute_display_column (s
, policy
);
421 case DIAGNOSTICS_COLUMN_UNIT_BYTE
:
426 /* Given an expanded_location, convert the column (which is in 1-based bytes)
427 to the requested units and origin. Return -1 if the column is
430 diagnostic_converted_column (diagnostic_context
*context
, expanded_location s
)
433 = convert_column_unit (context
->column_unit
, context
->tabstop
, s
);
434 if (one_based_col
<= 0)
436 return one_based_col
+ (context
->column_origin
- 1);
439 /* Return a formatted line and column ':%line:%column'. Elided if
440 line == 0 or col < 0. (A column of 0 may be valid due to the
441 -fdiagnostics-column-origin option.)
442 The result is a statically allocated buffer. */
445 maybe_line_and_column (int line
, int col
)
447 static char result
[32];
452 = snprintf (result
, sizeof (result
),
453 col
>= 0 ? ":%d:%d" : ":%d", line
, col
);
454 gcc_checking_assert (l
< sizeof (result
));
461 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
462 The caller is responsible for freeing the memory. */
465 diagnostic_get_location_text (diagnostic_context
*context
,
468 pretty_printer
*pp
= context
->printer
;
469 const char *locus_cs
= colorize_start (pp_show_color (pp
), "locus");
470 const char *locus_ce
= colorize_stop (pp_show_color (pp
));
471 const char *file
= s
.file
? s
.file
: progname
;
474 if (strcmp (file
, special_fname_builtin ()))
477 if (context
->show_column
)
478 col
= diagnostic_converted_column (context
, s
);
481 const char *line_col
= maybe_line_and_column (line
, col
);
482 return build_message_string ("%s%s%s:%s", locus_cs
, file
,
486 static const char *const diagnostic_kind_text
[] = {
487 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
488 #include "diagnostic.def"
489 #undef DEFINE_DIAGNOSTIC_KIND
493 /* Return a malloc'd string describing a location and the severity of the
494 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
495 freeing the memory. */
497 diagnostic_build_prefix (diagnostic_context
*context
,
498 const diagnostic_info
*diagnostic
)
500 gcc_assert (diagnostic
->kind
< DK_LAST_DIAGNOSTIC_KIND
);
502 const char *text
= _(diagnostic_kind_text
[diagnostic
->kind
]);
503 const char *text_cs
= "", *text_ce
= "";
504 pretty_printer
*pp
= context
->printer
;
506 if (diagnostic_kind_color
[diagnostic
->kind
])
508 text_cs
= colorize_start (pp_show_color (pp
),
509 diagnostic_kind_color
[diagnostic
->kind
]);
510 text_ce
= colorize_stop (pp_show_color (pp
));
513 expanded_location s
= diagnostic_expand_location (diagnostic
);
514 char *location_text
= diagnostic_get_location_text (context
, s
);
516 char *result
= build_message_string ("%s %s%s%s", location_text
,
517 text_cs
, text
, text_ce
);
518 free (location_text
);
522 /* Functions at which to stop the backtrace print. It's not
523 particularly helpful to print the callers of these functions. */
525 static const char * const bt_stop
[] =
533 /* A callback function passed to the backtrace_full function. */
536 bt_callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
537 const char *function
)
539 int *pcount
= (int *) data
;
541 /* If we don't have any useful information, don't print
543 if (filename
== NULL
&& function
== NULL
)
546 /* Skip functions in diagnostic.cc. */
549 && strcmp (lbasename (filename
), "diagnostic.cc") == 0)
552 /* Print up to 20 functions. We could make this a --param, but
553 since this is only for debugging just use a constant for now. */
556 /* Returning a non-zero value stops the backtrace. */
562 if (function
!= NULL
)
564 char *str
= cplus_demangle_v3 (function
,
565 (DMGL_VERBOSE
| DMGL_ANSI
566 | DMGL_GNU_V3
| DMGL_PARAMS
));
573 for (size_t i
= 0; i
< ARRAY_SIZE (bt_stop
); ++i
)
575 size_t len
= strlen (bt_stop
[i
]);
576 if (strncmp (function
, bt_stop
[i
], len
) == 0
577 && (function
[len
] == '\0' || function
[len
] == '('))
581 /* Returning a non-zero value stops the backtrace. */
587 fprintf (stderr
, "0x%lx %s\n\t%s:%d\n",
589 function
== NULL
? "???" : function
,
590 filename
== NULL
? "???" : filename
,
599 /* A callback function passed to the backtrace_full function. This is
600 called if backtrace_full has an error. */
603 bt_err_callback (void *data ATTRIBUTE_UNUSED
, const char *msg
, int errnum
)
607 /* This means that no debug info was available. Just quietly
608 skip printing backtrace info. */
611 fprintf (stderr
, "%s%s%s\n", msg
, errnum
== 0 ? "" : ": ",
612 errnum
== 0 ? "" : xstrerror (errnum
));
615 /* Check if we've met the maximum error limit, and if so fatally exit
616 with a message. CONTEXT is the context to check, and FLUSH
617 indicates whether a diagnostic_finish call is needed. */
620 diagnostic_check_max_errors (diagnostic_context
*context
, bool flush
)
622 if (!context
->max_errors
)
625 int count
= (diagnostic_kind_count (context
, DK_ERROR
)
626 + diagnostic_kind_count (context
, DK_SORRY
)
627 + diagnostic_kind_count (context
, DK_WERROR
));
629 if (count
>= context
->max_errors
)
632 "compilation terminated due to -fmax-errors=%u.\n",
633 context
->max_errors
);
635 diagnostic_finish (context
);
636 exit (FATAL_EXIT_CODE
);
640 /* Take any action which is expected to happen after the diagnostic
641 is written out. This function does not always return. */
643 diagnostic_action_after_output (diagnostic_context
*context
,
644 diagnostic_t diag_kind
)
656 if (context
->abort_on_error
)
658 if (context
->fatal_errors
)
660 fnotice (stderr
, "compilation terminated due to -Wfatal-errors.\n");
661 diagnostic_finish (context
);
662 exit (FATAL_EXIT_CODE
);
669 /* Optional callback for attempting to handle ICEs gracefully. */
670 if (void (*ice_handler_cb
) (diagnostic_context
*)
671 = context
->ice_handler_cb
)
673 /* Clear the callback, to avoid potentially re-entering
674 the routine if there's a crash within the handler. */
675 context
->ice_handler_cb
= NULL
;
676 ice_handler_cb (context
);
678 /* The context might have had diagnostic_finish called on
681 struct backtrace_state
*state
= NULL
;
682 if (diag_kind
== DK_ICE
)
683 state
= backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
686 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
689 if (context
->abort_on_error
)
692 if (context
->report_bug
)
693 fnotice (stderr
, "Please submit a full bug report, "
694 "with preprocessed source.\n");
696 fnotice (stderr
, "Please submit a full bug report, "
697 "with preprocessed source (by using -freport-bug).\n");
700 fnotice (stderr
, "Please include the complete backtrace "
701 "with any bug report.\n");
702 fnotice (stderr
, "See %s for instructions.\n", bug_report_url
);
704 exit (ICE_EXIT_CODE
);
708 if (context
->abort_on_error
)
710 diagnostic_finish (context
);
711 fnotice (stderr
, "compilation terminated.\n");
712 exit (FATAL_EXIT_CODE
);
719 /* True if the last module or file in which a diagnostic was reported is
720 different from the current one. */
723 last_module_changed_p (diagnostic_context
*context
,
724 const line_map_ordinary
*map
)
726 return context
->last_module
!= map
;
729 /* Remember the current module or file as being the last one in which we
730 report a diagnostic. */
733 set_last_module (diagnostic_context
*context
, const line_map_ordinary
*map
)
735 context
->last_module
= map
;
738 /* Only dump the "In file included from..." stack once for each file. */
741 includes_seen (diagnostic_context
*context
, const line_map_ordinary
*map
)
743 /* No include path for main. */
744 if (MAIN_FILE_P (map
))
747 /* Always identify C++ modules, at least for now. */
749 if (linemap_check_ordinary (map
)->reason
== LC_RENAME
)
750 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
751 probe
= linemap_included_from_linemap (line_table
, map
);
752 if (MAP_MODULE_P (probe
))
755 if (!context
->includes_seen
)
756 context
->includes_seen
= new hash_set
<location_t
, false, location_hash
>;
758 /* Hash the location of the #include directive to better handle files
759 that are included multiple times with different macros defined. */
760 return context
->includes_seen
->add (linemap_included_from (map
));
764 diagnostic_report_current_module (diagnostic_context
*context
, location_t where
)
766 const line_map_ordinary
*map
= NULL
;
768 if (pp_needs_newline (context
->printer
))
770 pp_newline (context
->printer
);
771 pp_needs_newline (context
->printer
) = false;
774 if (where
<= BUILTINS_LOCATION
)
777 linemap_resolve_location (line_table
, where
,
778 LRK_MACRO_DEFINITION_LOCATION
,
781 if (map
&& last_module_changed_p (context
, map
))
783 set_last_module (context
, map
);
784 if (!includes_seen (context
, map
))
786 bool first
= true, need_inc
= true, was_module
= MAP_MODULE_P (map
);
787 expanded_location s
= {};
790 where
= linemap_included_from (map
);
791 map
= linemap_included_from_linemap (line_table
, map
);
792 bool is_module
= MAP_MODULE_P (map
);
793 s
.file
= LINEMAP_FILE (map
);
794 s
.line
= SOURCE_LINE (map
, where
);
796 if (first
&& context
->show_column
)
798 s
.column
= SOURCE_COLUMN (map
, where
);
799 col
= diagnostic_converted_column (context
, s
);
801 const char *line_col
= maybe_line_and_column (s
.line
, col
);
802 static const char *const msgs
[] =
806 N_("In file included from"), /* 2 */
807 N_(" included from"),
808 N_("In module"), /* 4 */
810 N_("In module imported at"), /* 6 */
814 unsigned index
= (was_module
? 6 : is_module
? 4
815 : need_inc
? 2 : 0) + !first
;
817 pp_verbatim (context
->printer
, "%s%s %r%s%s%R",
818 first
? "" : was_module
? ", " : ",\n",
820 "locus", s
.file
, line_col
);
821 first
= false, need_inc
= was_module
, was_module
= is_module
;
823 while (!includes_seen (context
, map
));
824 pp_verbatim (context
->printer
, ":");
825 pp_newline (context
->printer
);
830 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
834 diagnostic_show_any_path (diagnostic_context
*context
,
835 diagnostic_info
*diagnostic
)
837 const diagnostic_path
*path
= diagnostic
->richloc
->get_path ();
841 if (context
->print_path
)
842 context
->print_path (context
, path
);
845 /* class diagnostic_event. */
847 /* struct diagnostic_event::meaning. */
850 diagnostic_event::meaning::dump_to_pp (pretty_printer
*pp
) const
852 bool need_comma
= false;
853 pp_character (pp
, '{');
854 if (const char *verb_str
= maybe_get_verb_str (m_verb
))
856 pp_printf (pp
, "verb: %qs", verb_str
);
859 if (const char *noun_str
= maybe_get_noun_str (m_noun
))
862 pp_string (pp
, ", ");
863 pp_printf (pp
, "noun: %qs", noun_str
);
866 if (const char *property_str
= maybe_get_property_str (m_property
))
869 pp_string (pp
, ", ");
870 pp_printf (pp
, "property: %qs", property_str
);
873 pp_character (pp
, '}');
876 /* Get a string (or NULL) for V suitable for use within a SARIF
877 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
880 diagnostic_event::meaning::maybe_get_verb_str (enum verb v
)
907 /* Get a string (or NULL) for N suitable for use within a SARIF
908 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
911 diagnostic_event::meaning::maybe_get_noun_str (enum noun n
)
934 /* Get a string (or NULL) for P suitable for use within a SARIF
935 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
938 diagnostic_event::meaning::maybe_get_property_str (enum property p
)
944 case PROPERTY_unknown
:
953 /* class diagnostic_path. */
955 /* Subroutint of diagnostic_path::interprocedural_p.
956 Look for the first event in this path that is within a function
957 i.e. has a non-NULL fndecl, and a non-zero stack depth.
958 If found, write its index to *OUT_IDX and return true.
959 Otherwise return false. */
962 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx
) const
964 const unsigned num
= num_events ();
965 for (unsigned i
= 0; i
< num
; i
++)
967 if (!(get_event (i
).get_fndecl () == NULL
968 && get_event (i
).get_stack_depth () == 0))
977 /* Return true if the events in this path involve more than one
978 function, or false if it is purely intraprocedural. */
981 diagnostic_path::interprocedural_p () const
983 /* Ignore leading events that are outside of any function. */
984 unsigned first_fn_event_idx
;
985 if (!get_first_event_in_a_function (&first_fn_event_idx
))
988 const diagnostic_event
&first_fn_event
= get_event (first_fn_event_idx
);
989 tree first_fndecl
= first_fn_event
.get_fndecl ();
990 int first_fn_stack_depth
= first_fn_event
.get_stack_depth ();
992 const unsigned num
= num_events ();
993 for (unsigned i
= first_fn_event_idx
+ 1; i
< num
; i
++)
995 if (get_event (i
).get_fndecl () != first_fndecl
)
997 if (get_event (i
).get_stack_depth () != first_fn_stack_depth
)
1004 default_diagnostic_starter (diagnostic_context
*context
,
1005 diagnostic_info
*diagnostic
)
1007 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
1008 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
1013 default_diagnostic_start_span_fn (diagnostic_context
*context
,
1014 expanded_location exploc
)
1016 char *text
= diagnostic_get_location_text (context
, exploc
);
1017 pp_string (context
->printer
, text
);
1019 pp_newline (context
->printer
);
1023 default_diagnostic_finalizer (diagnostic_context
*context
,
1024 diagnostic_info
*diagnostic
,
1027 char *saved_prefix
= pp_take_prefix (context
->printer
);
1028 pp_set_prefix (context
->printer
, NULL
);
1029 pp_newline (context
->printer
);
1030 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
1031 pp_set_prefix (context
->printer
, saved_prefix
);
1032 pp_flush (context
->printer
);
1035 /* Interface to specify diagnostic kind overrides. Returns the
1036 previous setting, or DK_UNSPECIFIED if the parameters are out of
1037 range. If OPTION_INDEX is zero, the new setting is for all the
1040 diagnostic_classify_diagnostic (diagnostic_context
*context
,
1042 diagnostic_t new_kind
,
1045 diagnostic_t old_kind
;
1047 if (option_index
< 0
1048 || option_index
>= context
->n_opts
1049 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
1050 return DK_UNSPECIFIED
;
1052 old_kind
= context
->classify_diagnostic
[option_index
];
1054 /* Handle pragmas separately, since we need to keep track of *where*
1055 the pragmas were. */
1056 if (where
!= UNKNOWN_LOCATION
)
1060 /* Record the command-line status, so we can reset it back on DK_POP. */
1061 if (old_kind
== DK_UNSPECIFIED
)
1063 old_kind
= !context
->option_enabled (option_index
,
1065 context
->option_state
)
1066 ? DK_IGNORED
: (context
->warning_as_error_requested
1067 ? DK_ERROR
: DK_WARNING
);
1068 context
->classify_diagnostic
[option_index
] = old_kind
;
1071 for (i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1072 if (context
->classification_history
[i
].option
== option_index
)
1074 old_kind
= context
->classification_history
[i
].kind
;
1078 i
= context
->n_classification_history
;
1079 context
->classification_history
=
1080 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1081 * sizeof (diagnostic_classification_change_t
));
1082 context
->classification_history
[i
].location
= where
;
1083 context
->classification_history
[i
].option
= option_index
;
1084 context
->classification_history
[i
].kind
= new_kind
;
1085 context
->n_classification_history
++;
1088 context
->classify_diagnostic
[option_index
] = new_kind
;
1093 /* Save all diagnostic classifications in a stack. */
1095 diagnostic_push_diagnostics (diagnostic_context
*context
, location_t where ATTRIBUTE_UNUSED
)
1097 context
->push_list
= (int *) xrealloc (context
->push_list
, (context
->n_push
+ 1) * sizeof (int));
1098 context
->push_list
[context
->n_push
++] = context
->n_classification_history
;
1101 /* Restore the topmost classification set off the stack. If the stack
1102 is empty, revert to the state based on command line parameters. */
1104 diagnostic_pop_diagnostics (diagnostic_context
*context
, location_t where
)
1109 if (context
->n_push
)
1110 jump_to
= context
->push_list
[-- context
->n_push
];
1114 i
= context
->n_classification_history
;
1115 context
->classification_history
=
1116 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1117 * sizeof (diagnostic_classification_change_t
));
1118 context
->classification_history
[i
].location
= where
;
1119 context
->classification_history
[i
].option
= jump_to
;
1120 context
->classification_history
[i
].kind
= DK_POP
;
1121 context
->n_classification_history
++;
1124 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1125 escaping rules for -fdiagnostics-parseable-fixits. */
1128 print_escaped_string (pretty_printer
*pp
, const char *text
)
1133 pp_character (pp
, '"');
1134 for (const char *ch
= text
; *ch
; ch
++)
1139 /* Escape backslash as two backslashes. */
1140 pp_string (pp
, "\\\\");
1143 /* Escape tab as "\t". */
1144 pp_string (pp
, "\\t");
1147 /* Escape newline as "\n". */
1148 pp_string (pp
, "\\n");
1151 /* Escape doublequotes as \". */
1152 pp_string (pp
, "\\\"");
1156 pp_character (pp
, *ch
);
1158 /* Use octal for non-printable chars. */
1160 unsigned char c
= (*ch
& 0xff);
1161 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
1166 pp_character (pp
, '"');
1169 /* Implementation of -fdiagnostics-parseable-fixits and
1170 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1171 Print a machine-parseable version of all fixits in RICHLOC to PP,
1172 using COLUMN_UNIT to express columns.
1173 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1176 print_parseable_fixits (pretty_printer
*pp
, rich_location
*richloc
,
1177 enum diagnostics_column_unit column_unit
,
1181 gcc_assert (richloc
);
1183 char *saved_prefix
= pp_take_prefix (pp
);
1184 pp_set_prefix (pp
, NULL
);
1186 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
1188 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
1189 location_t start_loc
= hint
->get_start_loc ();
1190 expanded_location start_exploc
= expand_location (start_loc
);
1191 pp_string (pp
, "fix-it:");
1192 print_escaped_string (pp
, start_exploc
.file
);
1193 /* For compatibility with clang, print as a half-open range. */
1194 location_t next_loc
= hint
->get_next_loc ();
1195 expanded_location next_exploc
= expand_location (next_loc
);
1197 = convert_column_unit (column_unit
, tabstop
, start_exploc
);
1199 = convert_column_unit (column_unit
, tabstop
, next_exploc
);
1200 pp_printf (pp
, ":{%i:%i-%i:%i}:",
1201 start_exploc
.line
, start_col
,
1202 next_exploc
.line
, next_col
);
1203 print_escaped_string (pp
, hint
->get_string ());
1207 pp_set_prefix (pp
, saved_prefix
);
1210 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1213 get_any_inlining_info (diagnostic_context
*context
,
1214 diagnostic_info
*diagnostic
)
1216 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1218 if (context
->set_locations_cb
)
1219 /* Retrieve the locations into which the expression about to be
1220 diagnosed has been inlined, including those of all the callers
1221 all the way down the inlining stack. */
1222 context
->set_locations_cb (context
, diagnostic
);
1225 /* When there's no callback use just the one location provided
1226 by the caller of the diagnostic function. */
1227 location_t loc
= diagnostic_location (diagnostic
);
1228 ilocs
.safe_push (loc
);
1229 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1233 /* Update the kind of DIAGNOSTIC based on its location(s), including
1234 any of those in its inlining stack, relative to any
1235 #pragma GCC diagnostic
1236 directives recorded within CONTEXT.
1238 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1242 update_effective_level_from_pragmas (diagnostic_context
*context
,
1243 diagnostic_info
*diagnostic
)
1245 if (diagnostic
->m_iinfo
.m_allsyslocs
&& !context
->dc_warn_system_headers
)
1247 /* Ignore the diagnostic if all the inlined locations are
1248 in system headers and -Wno-system-headers is in effect. */
1249 diagnostic
->kind
= DK_IGNORED
;
1253 if (context
->n_classification_history
<= 0)
1254 return DK_UNSPECIFIED
;
1256 /* Iterate over the locations, checking the diagnostic disposition
1257 for the diagnostic at each. If it's explicitly set as opposed
1258 to unspecified, update the disposition for this instance of
1259 the diagnostic and return it. */
1260 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1262 /* FIXME: Stupid search. Optimize later. */
1263 for (int i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1265 const diagnostic_classification_change_t
&hist
1266 = context
->classification_history
[i
];
1268 location_t pragloc
= hist
.location
;
1269 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1272 if (hist
.kind
== (int) DK_POP
)
1274 /* Move on to the next region. */
1279 int option
= hist
.option
;
1280 /* The option 0 is for all the diagnostics. */
1281 if (option
== 0 || option
== diagnostic
->option_index
)
1283 diagnostic_t kind
= hist
.kind
;
1284 if (kind
!= DK_UNSPECIFIED
)
1285 diagnostic
->kind
= kind
;
1291 return DK_UNSPECIFIED
;
1294 /* Generate a URL string describing CWE. The caller is responsible for
1295 freeing the string. */
1298 get_cwe_url (int cwe
)
1300 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1303 /* If DIAGNOSTIC has a CWE identifier, print it.
1305 For example, if the diagnostic metadata associates it with CWE-119,
1306 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1307 description of the security issue. */
1310 print_any_cwe (diagnostic_context
*context
,
1311 const diagnostic_info
*diagnostic
)
1313 if (diagnostic
->metadata
== NULL
)
1316 int cwe
= diagnostic
->metadata
->get_cwe ();
1319 pretty_printer
*pp
= context
->printer
;
1320 char *saved_prefix
= pp_take_prefix (context
->printer
);
1321 pp_string (pp
, " [");
1322 pp_string (pp
, colorize_start (pp_show_color (pp
),
1323 diagnostic_kind_color
[diagnostic
->kind
]));
1324 if (pp
->url_format
!= URL_FORMAT_NONE
)
1326 char *cwe_url
= get_cwe_url (cwe
);
1327 pp_begin_url (pp
, cwe_url
);
1330 pp_printf (pp
, "CWE-%i", cwe
);
1331 pp_set_prefix (context
->printer
, saved_prefix
);
1332 if (pp
->url_format
!= URL_FORMAT_NONE
)
1334 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1335 pp_character (pp
, ']');
1339 /* If DIAGNOSTIC has any rules associated with it, print them.
1341 For example, if the diagnostic metadata associates it with a rule
1342 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1343 with any URL provided by the rule. */
1346 print_any_rules (diagnostic_context
*context
,
1347 const diagnostic_info
*diagnostic
)
1349 if (diagnostic
->metadata
== NULL
)
1352 for (unsigned idx
= 0; idx
< diagnostic
->metadata
->get_num_rules (); idx
++)
1354 const diagnostic_metadata::rule
&rule
1355 = diagnostic
->metadata
->get_rule (idx
);
1356 if (char *desc
= rule
.make_description ())
1358 pretty_printer
*pp
= context
->printer
;
1359 char *saved_prefix
= pp_take_prefix (context
->printer
);
1360 pp_string (pp
, " [");
1362 colorize_start (pp_show_color (pp
),
1363 diagnostic_kind_color
[diagnostic
->kind
]));
1365 if (pp
->url_format
!= URL_FORMAT_NONE
)
1367 url
= rule
.make_url ();
1369 pp_begin_url (pp
, url
);
1371 pp_string (pp
, desc
);
1372 pp_set_prefix (context
->printer
, saved_prefix
);
1373 if (pp
->url_format
!= URL_FORMAT_NONE
)
1377 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1378 pp_character (pp
, ']');
1384 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1385 printer, e.g. " [-Werror=uninitialized]".
1386 Subroutine of diagnostic_report_diagnostic. */
1389 print_option_information (diagnostic_context
*context
,
1390 const diagnostic_info
*diagnostic
,
1391 diagnostic_t orig_diag_kind
)
1395 option_text
= context
->option_name (context
, diagnostic
->option_index
,
1396 orig_diag_kind
, diagnostic
->kind
);
1400 char *option_url
= NULL
;
1401 if (context
->get_option_url
1402 && context
->printer
->url_format
!= URL_FORMAT_NONE
)
1403 option_url
= context
->get_option_url (context
,
1404 diagnostic
->option_index
);
1405 pretty_printer
*pp
= context
->printer
;
1406 pp_string (pp
, " [");
1407 pp_string (pp
, colorize_start (pp_show_color (pp
),
1408 diagnostic_kind_color
[diagnostic
->kind
]));
1410 pp_begin_url (pp
, option_url
);
1411 pp_string (pp
, option_text
);
1417 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1418 pp_character (pp
, ']');
1423 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1424 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1427 diagnostic_enabled (diagnostic_context
*context
,
1428 diagnostic_info
*diagnostic
)
1430 /* Update the inlining stack for this diagnostic. */
1431 get_any_inlining_info (context
, diagnostic
);
1433 /* Diagnostics with no option or -fpermissive are always enabled. */
1434 if (!diagnostic
->option_index
1435 || diagnostic
->option_index
== permissive_error_option (context
))
1438 /* This tests if the user provided the appropriate -Wfoo or
1440 if (! context
->option_enabled (diagnostic
->option_index
,
1442 context
->option_state
))
1445 /* This tests for #pragma diagnostic changes. */
1446 diagnostic_t diag_class
1447 = update_effective_level_from_pragmas (context
, diagnostic
);
1449 /* This tests if the user provided the appropriate -Werror=foo
1451 if (diag_class
== DK_UNSPECIFIED
1452 && (context
->classify_diagnostic
[diagnostic
->option_index
]
1455 = context
->classify_diagnostic
[diagnostic
->option_index
];
1457 /* This allows for future extensions, like temporarily disabling
1458 warnings for ranges of source code. */
1459 if (diagnostic
->kind
== DK_IGNORED
)
1465 /* Returns whether warning OPT is enabled at LOC. */
1468 warning_enabled_at (location_t loc
, int opt
)
1470 if (!diagnostic_report_warnings_p (global_dc
, loc
))
1473 rich_location
richloc (line_table
, loc
);
1474 diagnostic_info diagnostic
= {};
1475 diagnostic
.option_index
= opt
;
1476 diagnostic
.richloc
= &richloc
;
1477 diagnostic
.message
.m_richloc
= &richloc
;
1478 diagnostic
.kind
= DK_WARNING
;
1479 return diagnostic_enabled (global_dc
, &diagnostic
);
1482 /* Report a diagnostic message (an error or a warning) as specified by
1483 DC. This function is *the* subroutine in terms of which front-ends
1484 should implement their specific diagnostic handling modules. The
1485 front-end independent format specifiers are exactly those described
1486 in the documentation of output_format.
1487 Return true if a diagnostic was printed, false otherwise. */
1490 diagnostic_report_diagnostic (diagnostic_context
*context
,
1491 diagnostic_info
*diagnostic
)
1493 location_t location
= diagnostic_location (diagnostic
);
1494 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1496 /* Give preference to being able to inhibit warnings, before they
1497 get reclassified to something else. */
1498 bool report_warning_p
= true;
1499 if (diagnostic
->kind
== DK_WARNING
|| diagnostic
->kind
== DK_PEDWARN
)
1501 if (context
->dc_inhibit_warnings
)
1503 /* Remember the result of the overall system header warning setting
1504 but proceed to also check the inlining context. */
1505 report_warning_p
= diagnostic_report_warnings_p (context
, location
);
1506 if (!report_warning_p
&& diagnostic
->kind
== DK_PEDWARN
)
1510 if (diagnostic
->kind
== DK_PEDWARN
)
1512 diagnostic
->kind
= pedantic_warning_kind (context
);
1513 /* We do this to avoid giving the message for -pedantic-errors. */
1514 orig_diag_kind
= diagnostic
->kind
;
1517 if (diagnostic
->kind
== DK_NOTE
&& context
->inhibit_notes_p
)
1520 if (context
->lock
> 0)
1522 /* If we're reporting an ICE in the middle of some other error,
1523 try to flush out the previous error, then let this one
1524 through. Don't do this more than once. */
1525 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1526 && context
->lock
== 1)
1527 pp_newline_and_flush (context
->printer
);
1529 error_recursion (context
);
1532 /* If the user requested that warnings be treated as errors, so be
1533 it. Note that we do this before the next block so that
1534 individual warnings can be overridden back to warnings with
1536 if (context
->warning_as_error_requested
1537 && diagnostic
->kind
== DK_WARNING
)
1538 diagnostic
->kind
= DK_ERROR
;
1540 diagnostic
->message
.x_data
= &diagnostic
->x_data
;
1542 /* Check to see if the diagnostic is enabled at the location and
1543 not disabled by #pragma GCC diagnostic anywhere along the inlining
1545 if (!diagnostic_enabled (context
, diagnostic
))
1548 if (!report_warning_p
&& diagnostic
->m_iinfo
.m_allsyslocs
)
1549 /* Bail if the warning is not to be reported because all locations
1550 in the inlining stack (if there is one) are in system headers. */
1553 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1554 diagnostic_check_max_errors (context
);
1558 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1560 /* When not checking, ICEs are converted to fatal errors when an
1561 error has already occurred. This is counteracted by
1564 && (diagnostic_kind_count (context
, DK_ERROR
) > 0
1565 || diagnostic_kind_count (context
, DK_SORRY
) > 0)
1566 && !context
->abort_on_error
)
1569 = expand_location (diagnostic_location (diagnostic
));
1570 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1572 exit (ICE_EXIT_CODE
);
1574 if (context
->internal_error
)
1575 (*context
->internal_error
) (context
,
1576 diagnostic
->message
.format_spec
,
1577 diagnostic
->message
.args_ptr
);
1579 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1580 ++diagnostic_kind_count (context
, DK_WERROR
);
1582 ++diagnostic_kind_count (context
, diagnostic
->kind
);
1584 /* Is this the initial diagnostic within the stack of groups? */
1585 if (context
->diagnostic_group_emission_count
== 0)
1587 if (context
->begin_group_cb
)
1588 context
->begin_group_cb (context
);
1590 context
->diagnostic_group_emission_count
++;
1592 pp_format (context
->printer
, &diagnostic
->message
);
1593 (*diagnostic_starter (context
)) (context
, diagnostic
);
1594 pp_output_formatted_text (context
->printer
);
1595 if (context
->show_cwe
)
1596 print_any_cwe (context
, diagnostic
);
1597 if (context
->show_rules
)
1598 print_any_rules (context
, diagnostic
);
1599 if (context
->show_option_requested
)
1600 print_option_information (context
, diagnostic
, orig_diag_kind
);
1601 (*diagnostic_finalizer (context
)) (context
, diagnostic
, orig_diag_kind
);
1602 switch (context
->extra_output_kind
)
1606 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1607 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1608 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1610 pp_flush (context
->printer
);
1612 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1613 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1614 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1616 pp_flush (context
->printer
);
1619 diagnostic_action_after_output (context
, diagnostic
->kind
);
1620 diagnostic
->x_data
= NULL
;
1622 if (context
->edit_context_ptr
)
1623 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1624 context
->edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1628 diagnostic_show_any_path (context
, diagnostic
);
1633 /* Get the number of digits in the decimal representation of VALUE. */
1636 num_digits (int value
)
1638 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1639 using floating point. */
1640 gcc_assert (value
>= 0);
1654 /* Given a partial pathname as input, return another pathname that
1655 shares no directory elements with the pathname of __FILE__. This
1656 is used by fancy_abort() to print `internal compiler error in expr.cc'
1657 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1660 trim_filename (const char *name
)
1662 static const char this_file
[] = __FILE__
;
1663 const char *p
= name
, *q
= this_file
;
1665 /* First skip any "../" in each filename. This allows us to give a proper
1666 reference to a file in a subdirectory. */
1667 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1670 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1673 /* Now skip any parts the two filenames have in common. */
1674 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1677 /* Now go backwards until the previous directory separator. */
1678 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1684 /* Standard error reporting routines in increasing order of severity.
1685 All of these take arguments like printf. */
1687 /* Text to be emitted verbatim to the error message stream; this
1688 produces no prefix and disables line-wrapping. Use rarely. */
1690 verbatim (const char *gmsgid
, ...)
1695 va_start (ap
, gmsgid
);
1696 text
.err_no
= errno
;
1697 text
.args_ptr
= &ap
;
1698 text
.format_spec
= _(gmsgid
);
1700 pp_format_verbatim (global_dc
->printer
, &text
);
1701 pp_newline_and_flush (global_dc
->printer
);
1705 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1707 diagnostic_append_note (diagnostic_context
*context
,
1708 location_t location
,
1709 const char * gmsgid
, ...)
1711 diagnostic_info diagnostic
;
1713 rich_location
richloc (line_table
, location
);
1715 va_start (ap
, gmsgid
);
1716 diagnostic_set_info (&diagnostic
, gmsgid
, &ap
, &richloc
, DK_NOTE
);
1717 if (context
->inhibit_notes_p
)
1722 char *saved_prefix
= pp_take_prefix (context
->printer
);
1723 pp_set_prefix (context
->printer
,
1724 diagnostic_build_prefix (context
, &diagnostic
));
1725 pp_format (context
->printer
, &diagnostic
.message
);
1726 pp_output_formatted_text (context
->printer
);
1727 pp_destroy_prefix (context
->printer
);
1728 pp_set_prefix (context
->printer
, saved_prefix
);
1729 pp_newline (context
->printer
);
1730 diagnostic_show_locus (context
, &richloc
, DK_NOTE
);
1734 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1735 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1736 and internal_error_no_backtrace, as documented and defined below. */
1738 diagnostic_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1739 int opt
, const char *gmsgid
,
1740 va_list *ap
, diagnostic_t kind
)
1742 diagnostic_info diagnostic
;
1743 if (kind
== DK_PERMERROR
)
1745 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
,
1746 permissive_error_kind (global_dc
));
1747 diagnostic
.option_index
= permissive_error_option (global_dc
);
1751 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1752 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1753 diagnostic
.option_index
= opt
;
1755 diagnostic
.metadata
= metadata
;
1756 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1759 /* Implement inform_n, warning_n, and error_n, as documented and
1762 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1763 int opt
, unsigned HOST_WIDE_INT n
,
1764 const char *singular_gmsgid
,
1765 const char *plural_gmsgid
,
1766 va_list *ap
, diagnostic_t kind
)
1768 diagnostic_info diagnostic
;
1771 if (sizeof n
<= sizeof gtn
)
1774 /* Use the largest number ngettext can handle, otherwise
1775 preserve the six least significant decimal digits for
1776 languages where the plural form depends on them. */
1777 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1779 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1780 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1781 if (kind
== DK_WARNING
)
1782 diagnostic
.option_index
= opt
;
1783 diagnostic
.metadata
= metadata
;
1784 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1787 /* Wrapper around diagnostic_impl taking a variable argument list. */
1790 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1791 const char *gmsgid
, ...)
1793 auto_diagnostic_group d
;
1795 va_start (ap
, gmsgid
);
1796 rich_location
richloc (line_table
, location
);
1797 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1802 /* As above, but for rich_location *. */
1805 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1806 const char *gmsgid
, ...)
1808 auto_diagnostic_group d
;
1810 va_start (ap
, gmsgid
);
1811 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1816 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1819 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1820 const char *gmsgid
, va_list *ap
)
1822 rich_location
richloc (line_table
, location
);
1823 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1826 /* An informative note at LOCATION. Use this for additional details on an error
1829 inform (location_t location
, const char *gmsgid
, ...)
1831 auto_diagnostic_group d
;
1833 va_start (ap
, gmsgid
);
1834 rich_location
richloc (line_table
, location
);
1835 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1839 /* Same as "inform" above, but at RICHLOC. */
1841 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1843 gcc_assert (richloc
);
1845 auto_diagnostic_group d
;
1847 va_start (ap
, gmsgid
);
1848 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1852 /* An informative note at LOCATION. Use this for additional details on an
1855 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1856 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1859 va_start (ap
, plural_gmsgid
);
1860 auto_diagnostic_group d
;
1861 rich_location
richloc (line_table
, location
);
1862 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1867 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1868 to the relevant language specification but is likely to be buggy anyway.
1869 Returns true if the warning was printed, false if it was inhibited. */
1871 warning (int opt
, const char *gmsgid
, ...)
1873 auto_diagnostic_group d
;
1875 va_start (ap
, gmsgid
);
1876 rich_location
richloc (line_table
, input_location
);
1877 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1882 /* A warning at LOCATION. Use this for code which is correct according to the
1883 relevant language specification but is likely to be buggy anyway.
1884 Returns true if the warning was printed, false if it was inhibited. */
1887 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1889 auto_diagnostic_group d
;
1891 va_start (ap
, gmsgid
);
1892 rich_location
richloc (line_table
, location
);
1893 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1898 /* Same as "warning at" above, but using RICHLOC. */
1901 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1903 gcc_assert (richloc
);
1905 auto_diagnostic_group d
;
1907 va_start (ap
, gmsgid
);
1908 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1913 /* Same as "warning at" above, but using METADATA. */
1916 warning_meta (rich_location
*richloc
,
1917 const diagnostic_metadata
&metadata
,
1918 int opt
, const char *gmsgid
, ...)
1920 gcc_assert (richloc
);
1922 auto_diagnostic_group d
;
1924 va_start (ap
, gmsgid
);
1926 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1932 /* Same as warning_n plural variant below, but using RICHLOC. */
1935 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1936 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1938 gcc_assert (richloc
);
1940 auto_diagnostic_group d
;
1942 va_start (ap
, plural_gmsgid
);
1943 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1944 singular_gmsgid
, plural_gmsgid
,
1950 /* A warning at LOCATION. Use this for code which is correct according to the
1951 relevant language specification but is likely to be buggy anyway.
1952 Returns true if the warning was printed, false if it was inhibited. */
1955 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1956 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1958 auto_diagnostic_group d
;
1960 va_start (ap
, plural_gmsgid
);
1961 rich_location
richloc (line_table
, location
);
1962 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1963 singular_gmsgid
, plural_gmsgid
,
1969 /* A "pedantic" warning at LOCATION: issues a warning unless
1970 -pedantic-errors was given on the command line, in which case it
1971 issues an error. Use this for diagnostics required by the relevant
1972 language standard, if you have chosen not to make them errors.
1974 Note that these diagnostics are issued independent of the setting
1975 of the -Wpedantic command-line switch. To get a warning enabled
1976 only with that switch, use either "if (pedantic) pedwarn
1977 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1978 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1980 Returns true if the warning was printed, false if it was inhibited. */
1983 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
1985 auto_diagnostic_group d
;
1987 va_start (ap
, gmsgid
);
1988 rich_location
richloc (line_table
, location
);
1989 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1994 /* Same as pedwarn above, but using RICHLOC. */
1997 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1999 gcc_assert (richloc
);
2001 auto_diagnostic_group d
;
2003 va_start (ap
, gmsgid
);
2004 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
2009 /* A "permissive" error at LOCATION: issues an error unless
2010 -fpermissive was given on the command line, in which case it issues
2011 a warning. Use this for things that really should be errors but we
2012 want to support legacy code.
2014 Returns true if the warning was printed, false if it was inhibited. */
2017 permerror (location_t location
, const char *gmsgid
, ...)
2019 auto_diagnostic_group d
;
2021 va_start (ap
, gmsgid
);
2022 rich_location
richloc (line_table
, location
);
2023 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2028 /* Same as "permerror" above, but at RICHLOC. */
2031 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
2033 gcc_assert (richloc
);
2035 auto_diagnostic_group d
;
2037 va_start (ap
, gmsgid
);
2038 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2043 /* A hard error: the code is definitely ill-formed, and an object file
2044 will not be produced. */
2046 error (const char *gmsgid
, ...)
2048 auto_diagnostic_group d
;
2050 va_start (ap
, gmsgid
);
2051 rich_location
richloc (line_table
, input_location
);
2052 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2056 /* A hard error: the code is definitely ill-formed, and an object file
2057 will not be produced. */
2059 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
2060 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
2062 auto_diagnostic_group d
;
2064 va_start (ap
, plural_gmsgid
);
2065 rich_location
richloc (line_table
, location
);
2066 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
2071 /* Same as above, but use location LOC instead of input_location. */
2073 error_at (location_t loc
, const char *gmsgid
, ...)
2075 auto_diagnostic_group d
;
2077 va_start (ap
, gmsgid
);
2078 rich_location
richloc (line_table
, loc
);
2079 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2083 /* Same as above, but use RICH_LOC. */
2086 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
2088 gcc_assert (richloc
);
2090 auto_diagnostic_group d
;
2092 va_start (ap
, gmsgid
);
2093 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2097 /* "Sorry, not implemented." Use for a language feature which is
2098 required by the relevant specification but not implemented by GCC.
2099 An object file will not be produced. */
2101 sorry (const char *gmsgid
, ...)
2103 auto_diagnostic_group d
;
2105 va_start (ap
, gmsgid
);
2106 rich_location
richloc (line_table
, input_location
);
2107 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2111 /* Same as above, but use location LOC instead of input_location. */
2113 sorry_at (location_t loc
, const char *gmsgid
, ...)
2115 auto_diagnostic_group d
;
2117 va_start (ap
, gmsgid
);
2118 rich_location
richloc (line_table
, loc
);
2119 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2123 /* Return true if an error or a "sorry" has been seen. Various
2124 processing is disabled after errors. */
2128 return errorcount
|| sorrycount
;
2131 /* An error which is severe enough that we make no attempt to
2132 continue. Do not use this for internal consistency checks; that's
2133 internal_error. Use of this function should be rare. */
2135 fatal_error (location_t loc
, const char *gmsgid
, ...)
2137 auto_diagnostic_group d
;
2139 va_start (ap
, gmsgid
);
2140 rich_location
richloc (line_table
, loc
);
2141 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
2147 /* An internal consistency check has failed. We make no attempt to
2150 internal_error (const char *gmsgid
, ...)
2152 auto_diagnostic_group d
;
2154 va_start (ap
, gmsgid
);
2155 rich_location
richloc (line_table
, input_location
);
2156 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
2162 /* Like internal_error, but no backtrace will be printed. Used when
2163 the internal error does not happen at the current location, but happened
2166 internal_error_no_backtrace (const char *gmsgid
, ...)
2168 auto_diagnostic_group d
;
2170 va_start (ap
, gmsgid
);
2171 rich_location
richloc (line_table
, input_location
);
2172 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
2178 /* Special case error functions. Most are implemented in terms of the
2179 above, or should be. */
2181 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2182 runs its second argument through gettext. */
2184 fnotice (FILE *file
, const char *cmsgid
, ...)
2188 va_start (ap
, cmsgid
);
2189 vfprintf (file
, _(cmsgid
), ap
);
2193 /* Inform the user that an error occurred while trying to report some
2194 other error. This indicates catastrophic internal inconsistencies,
2195 so give up now. But do try to flush out the previous error.
2196 This mustn't use internal_error, that will cause infinite recursion. */
2199 error_recursion (diagnostic_context
*context
)
2201 if (context
->lock
< 3)
2202 pp_newline_and_flush (context
->printer
);
2205 "internal compiler error: error reporting routines re-entered.\n");
2207 /* Call diagnostic_action_after_output to get the "please submit a bug
2209 diagnostic_action_after_output (context
, DK_ICE
);
2211 /* Do not use gcc_unreachable here; that goes through internal_error
2212 and therefore would cause infinite recursion. */
2216 /* Report an internal compiler error in a friendly manner. This is
2217 the function that gets called upon use of abort() in the source
2218 code generally, thanks to a special macro. */
2221 fancy_abort (const char *file
, int line
, const char *function
)
2223 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2224 internal_error will crash internally in a way that prevents a
2225 useful message reaching the user.
2226 This can happen with libgccjit in the case of gcc_assert failures
2227 that occur outside of the libgccjit mutex that guards the rest of
2228 gcc's state, including global_dc (when global_dc may not be
2229 initialized yet, or might be in use by another thread).
2230 Handle such cases as gracefully as possible by falling back to a
2231 minimal abort handler that only relies on i18n. */
2232 if (global_dc
->printer
== NULL
)
2234 /* Print the error message. */
2235 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
2236 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
2237 fputc ('\n', stderr
);
2239 /* Attempt to print a backtrace. */
2240 struct backtrace_state
*state
2241 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
2244 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
2247 /* We can't call warn_if_plugins or emergency_dump_function as these
2248 rely on GCC state that might not be initialized, or might be in
2249 use by another thread. */
2251 /* Abort the process. */
2255 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2258 /* class auto_diagnostic_group. */
2260 /* Constructor: "push" this group into global_dc. */
2262 auto_diagnostic_group::auto_diagnostic_group ()
2264 global_dc
->diagnostic_group_nesting_depth
++;
2267 /* Destructor: "pop" this group from global_dc. */
2269 auto_diagnostic_group::~auto_diagnostic_group ()
2271 if (--global_dc
->diagnostic_group_nesting_depth
== 0)
2273 /* Handle the case where we've popped the final diagnostic group.
2274 If any diagnostics were emitted, give the context a chance
2276 if (global_dc
->diagnostic_group_emission_count
> 0)
2278 if (global_dc
->end_group_cb
)
2279 global_dc
->end_group_cb (global_dc
);
2281 global_dc
->diagnostic_group_emission_count
= 0;
2285 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2286 file-based output formats. */
2289 diagnostic_output_format_init (diagnostic_context
*context
,
2290 const char *base_file_name
,
2291 enum diagnostics_output_format format
)
2297 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT
:
2298 /* The default; do nothing. */
2301 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR
:
2302 diagnostic_output_format_init_json_stderr (context
);
2305 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
:
2306 diagnostic_output_format_init_json_file (context
, base_file_name
);
2309 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR
:
2310 diagnostic_output_format_init_sarif_stderr (context
);
2313 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
:
2314 diagnostic_output_format_init_sarif_file (context
, base_file_name
);
2319 /* Implementation of diagnostic_path::num_events vfunc for
2320 simple_diagnostic_path: simply get the number of events in the vec. */
2323 simple_diagnostic_path::num_events () const
2325 return m_events
.length ();
2328 /* Implementation of diagnostic_path::get_event vfunc for
2329 simple_diagnostic_path: simply return the event in the vec. */
2331 const diagnostic_event
&
2332 simple_diagnostic_path::get_event (int idx
) const
2334 return *m_events
[idx
];
2337 /* Add an event to this path at LOC within function FNDECL at
2340 Use m_context's printer to format FMT, as the text of the new
2343 Return the id of the new event. */
2345 diagnostic_event_id_t
2346 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2347 const char *fmt
, ...)
2349 pretty_printer
*pp
= m_event_pp
;
2350 pp_clear_output_area (pp
);
2353 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2359 ti
.format_spec
= _(fmt
);
2363 ti
.m_richloc
= &rich_loc
;
2365 pp_format (pp
, &ti
);
2366 pp_output_formatted_text (pp
);
2370 simple_diagnostic_event
*new_event
2371 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2372 m_events
.safe_push (new_event
);
2374 pp_clear_output_area (pp
);
2376 return diagnostic_event_id_t (m_events
.length () - 1);
2379 /* struct simple_diagnostic_event. */
2381 /* simple_diagnostic_event's ctor. */
2383 simple_diagnostic_event::simple_diagnostic_event (location_t loc
,
2387 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
))
2391 /* simple_diagnostic_event's dtor. */
2393 simple_diagnostic_event::~simple_diagnostic_event ()
2398 /* Print PATH by emitting a dummy "note" associated with it. */
2401 void debug (diagnostic_path
*path
)
2403 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2404 richloc
.set_path (path
);
2405 inform (&richloc
, "debug path");
2408 /* Really call the system 'abort'. This has to go right at the end of
2409 this file, so that there are no functions after it that call abort
2410 and get the system abort instead of our macro. */
2420 namespace selftest
{
2422 /* Helper function for test_print_escaped_string. */
2425 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2429 print_escaped_string (&pp
, input
);
2430 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2433 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2434 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2436 /* Tests of print_escaped_string. */
2439 test_print_escaped_string ()
2442 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2444 /* Non-empty string. */
2445 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2447 /* Various things that need to be escaped: */
2449 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2452 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2455 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2458 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2461 /* Non-printable characters: BEL: '\a': 0x07 */
2462 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2464 /* Non-printable characters: vertical tab: '\v': 0x0b */
2465 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2469 /* Tests of print_parseable_fixits. */
2471 /* Verify that print_parseable_fixits emits the empty string if there
2475 test_print_parseable_fixits_none ()
2478 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2480 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2481 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2484 /* Verify that print_parseable_fixits does the right thing if there
2485 is an insertion fixit hint. */
2488 test_print_parseable_fixits_insert ()
2491 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2493 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2494 linemap_line_start (line_table
, 5, 100);
2495 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2496 location_t where
= linemap_position_for_column (line_table
, 10);
2497 richloc
.add_fixit_insert_before (where
, "added content");
2499 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2500 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2501 pp_formatted_text (&pp
));
2504 /* Verify that print_parseable_fixits does the right thing if there
2505 is an removal fixit hint. */
2508 test_print_parseable_fixits_remove ()
2511 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2513 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2514 linemap_line_start (line_table
, 5, 100);
2515 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2517 where
.m_start
= linemap_position_for_column (line_table
, 10);
2518 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2519 richloc
.add_fixit_remove (where
);
2521 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2522 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2523 pp_formatted_text (&pp
));
2526 /* Verify that print_parseable_fixits does the right thing if there
2527 is an replacement fixit hint. */
2530 test_print_parseable_fixits_replace ()
2533 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2535 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2536 linemap_line_start (line_table
, 5, 100);
2537 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2539 where
.m_start
= linemap_position_for_column (line_table
, 10);
2540 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2541 richloc
.add_fixit_replace (where
, "replacement");
2543 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2544 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2545 pp_formatted_text (&pp
));
2548 /* Verify that print_parseable_fixits correctly handles
2549 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2552 test_print_parseable_fixits_bytes_vs_display_columns ()
2554 line_table_test ltt
;
2555 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2557 /* 1-based byte offsets: 12345677778888999900001234567. */
2558 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2559 /* 1-based display cols: 123456[......7-8.....]9012345. */
2560 const int tabstop
= 8;
2562 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2563 const char *const fname
= tmp
.get_filename ();
2565 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2566 linemap_line_start (line_table
, 1, 100);
2567 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2569 where
.m_start
= linemap_position_for_column (line_table
, 12);
2570 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2571 richloc
.add_fixit_replace (where
, "color");
2574 pretty_printer tmp_pp
;
2575 print_escaped_string (&tmp_pp
, fname
);
2576 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2578 const int buf_len
= strlen (escaped_fname
) + 100;
2579 char *const expected
= XNEWVEC (char, buf_len
);
2583 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2585 snprintf (expected
, buf_len
,
2586 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2587 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2591 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2593 snprintf (expected
, buf_len
,
2594 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2595 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2598 XDELETEVEC (expected
);
2599 free (escaped_fname
);
2603 diagnostic_get_location_text (..., SHOW_COLUMN)
2604 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2605 colorization disabled. */
2608 assert_location_text (const char *expected_loc_text
,
2609 const char *filename
, int line
, int column
,
2612 enum diagnostics_column_unit column_unit
2613 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2615 test_diagnostic_context dc
;
2616 dc
.show_column
= show_column
;
2617 dc
.column_unit
= column_unit
;
2618 dc
.column_origin
= origin
;
2620 expanded_location xloc
;
2621 xloc
.file
= filename
;
2623 xloc
.column
= column
;
2627 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2628 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2629 free (actual_loc_text
);
2632 /* Verify that diagnostic_get_location_text works as expected. */
2635 test_diagnostic_get_location_text ()
2637 const char *old_progname
= progname
;
2638 progname
= "PROGNAME";
2639 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2640 char *built_in_colon
= concat (special_fname_builtin (), ":", (char *) 0);
2641 assert_location_text (built_in_colon
, special_fname_builtin (),
2643 free (built_in_colon
);
2644 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2645 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2646 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2647 for (int origin
= 0; origin
!= 2; ++origin
)
2648 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2649 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2650 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2651 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2653 maybe_line_and_column (INT_MAX
, INT_MAX
);
2654 maybe_line_and_column (INT_MIN
, INT_MIN
);
2657 /* In order to test display columns vs byte columns, we need to create a
2658 file for location_get_source_line() to read. */
2660 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2661 const int line_bytes
= strlen (content
) - 1;
2662 const int def_tabstop
= 8;
2663 const cpp_char_column_policy
policy (def_tabstop
, cpp_wcwidth
);
2664 const int display_width
= cpp_display_width (content
, line_bytes
, policy
);
2665 ASSERT_EQ (line_bytes
- 2, display_width
);
2666 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2667 const char *const fname
= tmp
.get_filename ();
2668 const int buf_len
= strlen (fname
) + 16;
2669 char *const expected
= XNEWVEC (char, buf_len
);
2671 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2672 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2673 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2675 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2676 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2677 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2679 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2680 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2681 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2683 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2684 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2685 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2687 XDELETEVEC (expected
);
2691 progname
= old_progname
;
2694 /* Selftest for num_digits. */
2699 ASSERT_EQ (1, num_digits (0));
2700 ASSERT_EQ (1, num_digits (9));
2701 ASSERT_EQ (2, num_digits (10));
2702 ASSERT_EQ (2, num_digits (99));
2703 ASSERT_EQ (3, num_digits (100));
2704 ASSERT_EQ (3, num_digits (999));
2705 ASSERT_EQ (4, num_digits (1000));
2706 ASSERT_EQ (4, num_digits (9999));
2707 ASSERT_EQ (5, num_digits (10000));
2708 ASSERT_EQ (5, num_digits (99999));
2709 ASSERT_EQ (6, num_digits (100000));
2710 ASSERT_EQ (6, num_digits (999999));
2711 ASSERT_EQ (7, num_digits (1000000));
2712 ASSERT_EQ (7, num_digits (9999999));
2713 ASSERT_EQ (8, num_digits (10000000));
2714 ASSERT_EQ (8, num_digits (99999999));
2717 /* Run all of the selftests within this file. */
2720 c_diagnostic_cc_tests ()
2722 test_print_escaped_string ();
2723 test_print_parseable_fixits_none ();
2724 test_print_parseable_fixits_insert ();
2725 test_print_parseable_fixits_remove ();
2726 test_print_parseable_fixits_replace ();
2727 test_print_parseable_fixits_bytes_vs_display_columns ();
2728 test_diagnostic_get_location_text ();
2733 } // namespace selftest
2735 #endif /* #if CHECKING_P */
2738 # pragma GCC diagnostic pop