1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2022 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
->includes_seen
= NULL
;
245 context
->m_client_data_hooks
= NULL
;
248 /* Maybe initialize the color support. We require clients to do this
249 explicitly, since most clients don't want color. When called
250 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
253 diagnostic_color_init (diagnostic_context
*context
, int value
/*= -1 */)
255 /* value == -1 is the default value. */
258 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
259 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
260 otherwise default to -fdiagnostics-color=never, for other
261 values default to that
262 -fdiagnostics-color={never,auto,always}. */
263 if (DIAGNOSTICS_COLOR_DEFAULT
== -1)
265 if (!getenv ("GCC_COLORS"))
267 value
= DIAGNOSTICS_COLOR_AUTO
;
270 value
= DIAGNOSTICS_COLOR_DEFAULT
;
272 pp_show_color (context
->printer
)
273 = colorize_init ((diagnostic_color_rule_t
) value
);
276 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
279 diagnostic_urls_init (diagnostic_context
*context
, int value
/*= -1 */)
281 /* value == -1 is the default value. */
284 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
285 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
286 environment, otherwise default to -fdiagnostics-urls=never,
287 for other values default to that
288 -fdiagnostics-urls={never,auto,always}. */
289 if (DIAGNOSTICS_URLS_DEFAULT
== -1)
291 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
293 value
= DIAGNOSTICS_URL_AUTO
;
296 value
= DIAGNOSTICS_URLS_DEFAULT
;
299 context
->printer
->url_format
300 = determine_url_format ((diagnostic_url_rule_t
) value
);
303 /* Create the file_cache, if not already created, and tell it how to
304 translate files on input. */
305 void diagnostic_initialize_input_context (diagnostic_context
*context
,
306 diagnostic_input_charset_callback ccb
,
307 bool should_skip_bom
)
309 if (!context
->m_file_cache
)
310 context
->m_file_cache
= new file_cache
;
311 context
->m_file_cache
->initialize_input_context (ccb
, should_skip_bom
);
314 /* Do any cleaning up required after the last diagnostic is emitted. */
317 diagnostic_finish (diagnostic_context
*context
)
319 if (context
->final_cb
)
320 context
->final_cb (context
);
322 diagnostic_file_cache_fini ();
324 XDELETEVEC (context
->classify_diagnostic
);
325 context
->classify_diagnostic
= NULL
;
327 /* diagnostic_initialize allocates context->printer using XNEW
328 and placement-new. */
329 context
->printer
->~pretty_printer ();
330 XDELETE (context
->printer
);
331 context
->printer
= NULL
;
333 if (context
->edit_context_ptr
)
335 delete context
->edit_context_ptr
;
336 context
->edit_context_ptr
= NULL
;
339 if (context
->includes_seen
)
341 delete context
->includes_seen
;
342 context
->includes_seen
= nullptr;
345 if (context
->m_client_data_hooks
)
347 delete context
->m_client_data_hooks
;
348 context
->m_client_data_hooks
= NULL
;
352 /* Initialize DIAGNOSTIC, where the message MSG has already been
355 diagnostic_set_info_translated (diagnostic_info
*diagnostic
, const char *msg
,
356 va_list *args
, rich_location
*richloc
,
359 gcc_assert (richloc
);
360 diagnostic
->message
.err_no
= errno
;
361 diagnostic
->message
.args_ptr
= args
;
362 diagnostic
->message
.format_spec
= msg
;
363 diagnostic
->message
.m_richloc
= richloc
;
364 diagnostic
->richloc
= richloc
;
365 diagnostic
->metadata
= NULL
;
366 diagnostic
->kind
= kind
;
367 diagnostic
->option_index
= 0;
370 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
373 diagnostic_set_info (diagnostic_info
*diagnostic
, const char *gmsgid
,
374 va_list *args
, rich_location
*richloc
,
377 gcc_assert (richloc
);
378 diagnostic_set_info_translated (diagnostic
, _(gmsgid
), args
, richloc
, kind
);
381 static const char *const diagnostic_kind_color
[] = {
382 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
383 #include "diagnostic.def"
384 #undef DEFINE_DIAGNOSTIC_KIND
388 /* Get a color name for diagnostics of type KIND
389 Result could be NULL. */
392 diagnostic_get_color_for_kind (diagnostic_t kind
)
394 return diagnostic_kind_color
[kind
];
397 /* Given an expanded_location, convert the column (which is in 1-based bytes)
398 to the requested units, without converting the origin.
399 Return -1 if the column is invalid (<= 0). */
402 convert_column_unit (enum diagnostics_column_unit column_unit
,
414 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY
:
416 cpp_char_column_policy
policy (tabstop
, cpp_wcwidth
);
417 return location_compute_display_column (s
, policy
);
420 case DIAGNOSTICS_COLUMN_UNIT_BYTE
:
425 /* Given an expanded_location, convert the column (which is in 1-based bytes)
426 to the requested units and origin. Return -1 if the column is
429 diagnostic_converted_column (diagnostic_context
*context
, expanded_location s
)
432 = convert_column_unit (context
->column_unit
, context
->tabstop
, s
);
433 if (one_based_col
<= 0)
435 return one_based_col
+ (context
->column_origin
- 1);
438 /* Return a formatted line and column ':%line:%column'. Elided if
439 line == 0 or col < 0. (A column of 0 may be valid due to the
440 -fdiagnostics-column-origin option.)
441 The result is a statically allocated buffer. */
444 maybe_line_and_column (int line
, int col
)
446 static char result
[32];
451 = snprintf (result
, sizeof (result
),
452 col
>= 0 ? ":%d:%d" : ":%d", line
, col
);
453 gcc_checking_assert (l
< sizeof (result
));
460 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
461 The caller is responsible for freeing the memory. */
464 diagnostic_get_location_text (diagnostic_context
*context
,
467 pretty_printer
*pp
= context
->printer
;
468 const char *locus_cs
= colorize_start (pp_show_color (pp
), "locus");
469 const char *locus_ce
= colorize_stop (pp_show_color (pp
));
470 const char *file
= s
.file
? s
.file
: progname
;
473 if (strcmp (file
, special_fname_builtin ()))
476 if (context
->show_column
)
477 col
= diagnostic_converted_column (context
, s
);
480 const char *line_col
= maybe_line_and_column (line
, col
);
481 return build_message_string ("%s%s%s:%s", locus_cs
, file
,
485 static const char *const diagnostic_kind_text
[] = {
486 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
487 #include "diagnostic.def"
488 #undef DEFINE_DIAGNOSTIC_KIND
492 /* Return a malloc'd string describing a location and the severity of the
493 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
494 freeing the memory. */
496 diagnostic_build_prefix (diagnostic_context
*context
,
497 const diagnostic_info
*diagnostic
)
499 gcc_assert (diagnostic
->kind
< DK_LAST_DIAGNOSTIC_KIND
);
501 const char *text
= _(diagnostic_kind_text
[diagnostic
->kind
]);
502 const char *text_cs
= "", *text_ce
= "";
503 pretty_printer
*pp
= context
->printer
;
505 if (diagnostic_kind_color
[diagnostic
->kind
])
507 text_cs
= colorize_start (pp_show_color (pp
),
508 diagnostic_kind_color
[diagnostic
->kind
]);
509 text_ce
= colorize_stop (pp_show_color (pp
));
512 expanded_location s
= diagnostic_expand_location (diagnostic
);
513 char *location_text
= diagnostic_get_location_text (context
, s
);
515 char *result
= build_message_string ("%s %s%s%s", location_text
,
516 text_cs
, text
, text_ce
);
517 free (location_text
);
521 /* Functions at which to stop the backtrace print. It's not
522 particularly helpful to print the callers of these functions. */
524 static const char * const bt_stop
[] =
532 /* A callback function passed to the backtrace_full function. */
535 bt_callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
536 const char *function
)
538 int *pcount
= (int *) data
;
540 /* If we don't have any useful information, don't print
542 if (filename
== NULL
&& function
== NULL
)
545 /* Skip functions in diagnostic.cc. */
548 && strcmp (lbasename (filename
), "diagnostic.cc") == 0)
551 /* Print up to 20 functions. We could make this a --param, but
552 since this is only for debugging just use a constant for now. */
555 /* Returning a non-zero value stops the backtrace. */
561 if (function
!= NULL
)
563 char *str
= cplus_demangle_v3 (function
,
564 (DMGL_VERBOSE
| DMGL_ANSI
565 | DMGL_GNU_V3
| DMGL_PARAMS
));
572 for (size_t i
= 0; i
< ARRAY_SIZE (bt_stop
); ++i
)
574 size_t len
= strlen (bt_stop
[i
]);
575 if (strncmp (function
, bt_stop
[i
], len
) == 0
576 && (function
[len
] == '\0' || function
[len
] == '('))
580 /* Returning a non-zero value stops the backtrace. */
586 fprintf (stderr
, "0x%lx %s\n\t%s:%d\n",
588 function
== NULL
? "???" : function
,
589 filename
== NULL
? "???" : filename
,
598 /* A callback function passed to the backtrace_full function. This is
599 called if backtrace_full has an error. */
602 bt_err_callback (void *data ATTRIBUTE_UNUSED
, const char *msg
, int errnum
)
606 /* This means that no debug info was available. Just quietly
607 skip printing backtrace info. */
610 fprintf (stderr
, "%s%s%s\n", msg
, errnum
== 0 ? "" : ": ",
611 errnum
== 0 ? "" : xstrerror (errnum
));
614 /* Check if we've met the maximum error limit, and if so fatally exit
615 with a message. CONTEXT is the context to check, and FLUSH
616 indicates whether a diagnostic_finish call is needed. */
619 diagnostic_check_max_errors (diagnostic_context
*context
, bool flush
)
621 if (!context
->max_errors
)
624 int count
= (diagnostic_kind_count (context
, DK_ERROR
)
625 + diagnostic_kind_count (context
, DK_SORRY
)
626 + diagnostic_kind_count (context
, DK_WERROR
));
628 if (count
>= context
->max_errors
)
631 "compilation terminated due to -fmax-errors=%u.\n",
632 context
->max_errors
);
634 diagnostic_finish (context
);
635 exit (FATAL_EXIT_CODE
);
639 /* Take any action which is expected to happen after the diagnostic
640 is written out. This function does not always return. */
642 diagnostic_action_after_output (diagnostic_context
*context
,
643 diagnostic_t diag_kind
)
655 if (context
->abort_on_error
)
657 if (context
->fatal_errors
)
659 fnotice (stderr
, "compilation terminated due to -Wfatal-errors.\n");
660 diagnostic_finish (context
);
661 exit (FATAL_EXIT_CODE
);
668 struct backtrace_state
*state
= NULL
;
669 if (diag_kind
== DK_ICE
)
670 state
= backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
673 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
676 if (context
->abort_on_error
)
679 if (context
->report_bug
)
680 fnotice (stderr
, "Please submit a full bug report, "
681 "with preprocessed source.\n");
683 fnotice (stderr
, "Please submit a full bug report, "
684 "with preprocessed source (by using -freport-bug).\n");
687 fnotice (stderr
, "Please include the complete backtrace "
688 "with any bug report.\n");
689 fnotice (stderr
, "See %s for instructions.\n", bug_report_url
);
691 exit (ICE_EXIT_CODE
);
695 if (context
->abort_on_error
)
697 diagnostic_finish (context
);
698 fnotice (stderr
, "compilation terminated.\n");
699 exit (FATAL_EXIT_CODE
);
706 /* True if the last module or file in which a diagnostic was reported is
707 different from the current one. */
710 last_module_changed_p (diagnostic_context
*context
,
711 const line_map_ordinary
*map
)
713 return context
->last_module
!= map
;
716 /* Remember the current module or file as being the last one in which we
717 report a diagnostic. */
720 set_last_module (diagnostic_context
*context
, const line_map_ordinary
*map
)
722 context
->last_module
= map
;
725 /* Only dump the "In file included from..." stack once for each file. */
728 includes_seen (diagnostic_context
*context
, const line_map_ordinary
*map
)
730 /* No include path for main. */
731 if (MAIN_FILE_P (map
))
734 /* Always identify C++ modules, at least for now. */
736 if (linemap_check_ordinary (map
)->reason
== LC_RENAME
)
737 /* The module source file shows up as LC_RENAME inside LC_MODULE. */
738 probe
= linemap_included_from_linemap (line_table
, map
);
739 if (MAP_MODULE_P (probe
))
742 if (!context
->includes_seen
)
743 context
->includes_seen
= new hash_set
<location_t
, false, location_hash
>;
745 /* Hash the location of the #include directive to better handle files
746 that are included multiple times with different macros defined. */
747 return context
->includes_seen
->add (linemap_included_from (map
));
751 diagnostic_report_current_module (diagnostic_context
*context
, location_t where
)
753 const line_map_ordinary
*map
= NULL
;
755 if (pp_needs_newline (context
->printer
))
757 pp_newline (context
->printer
);
758 pp_needs_newline (context
->printer
) = false;
761 if (where
<= BUILTINS_LOCATION
)
764 linemap_resolve_location (line_table
, where
,
765 LRK_MACRO_DEFINITION_LOCATION
,
768 if (map
&& last_module_changed_p (context
, map
))
770 set_last_module (context
, map
);
771 if (!includes_seen (context
, map
))
773 bool first
= true, need_inc
= true, was_module
= MAP_MODULE_P (map
);
774 expanded_location s
= {};
777 where
= linemap_included_from (map
);
778 map
= linemap_included_from_linemap (line_table
, map
);
779 bool is_module
= MAP_MODULE_P (map
);
780 s
.file
= LINEMAP_FILE (map
);
781 s
.line
= SOURCE_LINE (map
, where
);
783 if (first
&& context
->show_column
)
785 s
.column
= SOURCE_COLUMN (map
, where
);
786 col
= diagnostic_converted_column (context
, s
);
788 const char *line_col
= maybe_line_and_column (s
.line
, col
);
789 static const char *const msgs
[] =
793 N_("In file included from"), /* 2 */
794 N_(" included from"),
795 N_("In module"), /* 4 */
797 N_("In module imported at"), /* 6 */
801 unsigned index
= (was_module
? 6 : is_module
? 4
802 : need_inc
? 2 : 0) + !first
;
804 pp_verbatim (context
->printer
, "%s%s %r%s%s%R",
805 first
? "" : was_module
? ", " : ",\n",
807 "locus", s
.file
, line_col
);
808 first
= false, need_inc
= was_module
, was_module
= is_module
;
810 while (!includes_seen (context
, map
));
811 pp_verbatim (context
->printer
, ":");
812 pp_newline (context
->printer
);
817 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
821 diagnostic_show_any_path (diagnostic_context
*context
,
822 diagnostic_info
*diagnostic
)
824 const diagnostic_path
*path
= diagnostic
->richloc
->get_path ();
828 if (context
->print_path
)
829 context
->print_path (context
, path
);
832 /* class diagnostic_event. */
834 /* struct diagnostic_event::meaning. */
837 diagnostic_event::meaning::dump_to_pp (pretty_printer
*pp
) const
839 bool need_comma
= false;
840 pp_character (pp
, '{');
841 if (const char *verb_str
= maybe_get_verb_str (m_verb
))
843 pp_printf (pp
, "verb: %qs", verb_str
);
846 if (const char *noun_str
= maybe_get_noun_str (m_noun
))
849 pp_string (pp
, ", ");
850 pp_printf (pp
, "noun: %qs", noun_str
);
853 if (const char *property_str
= maybe_get_property_str (m_property
))
856 pp_string (pp
, ", ");
857 pp_printf (pp
, "property: %qs", property_str
);
860 pp_character (pp
, '}');
863 /* Get a string (or NULL) for V suitable for use within a SARIF
864 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
867 diagnostic_event::meaning::maybe_get_verb_str (enum verb v
)
894 /* Get a string (or NULL) for N suitable for use within a SARIF
895 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
898 diagnostic_event::meaning::maybe_get_noun_str (enum noun n
)
921 /* Get a string (or NULL) for P suitable for use within a SARIF
922 threadFlowLocation "kinds" property (SARIF v2.1.0 section 3.38.8). */
925 diagnostic_event::meaning::maybe_get_property_str (enum property p
)
931 case PROPERTY_unknown
:
940 /* class diagnostic_path. */
942 /* Subroutint of diagnostic_path::interprocedural_p.
943 Look for the first event in this path that is within a function
944 i.e. has a non-NULL fndecl, and a non-zero stack depth.
945 If found, write its index to *OUT_IDX and return true.
946 Otherwise return false. */
949 diagnostic_path::get_first_event_in_a_function (unsigned *out_idx
) const
951 const unsigned num
= num_events ();
952 for (unsigned i
= 0; i
< num
; i
++)
954 if (!(get_event (i
).get_fndecl () == NULL
955 && get_event (i
).get_stack_depth () == 0))
964 /* Return true if the events in this path involve more than one
965 function, or false if it is purely intraprocedural. */
968 diagnostic_path::interprocedural_p () const
970 /* Ignore leading events that are outside of any function. */
971 unsigned first_fn_event_idx
;
972 if (!get_first_event_in_a_function (&first_fn_event_idx
))
975 const diagnostic_event
&first_fn_event
= get_event (first_fn_event_idx
);
976 tree first_fndecl
= first_fn_event
.get_fndecl ();
977 int first_fn_stack_depth
= first_fn_event
.get_stack_depth ();
979 const unsigned num
= num_events ();
980 for (unsigned i
= first_fn_event_idx
+ 1; i
< num
; i
++)
982 if (get_event (i
).get_fndecl () != first_fndecl
)
984 if (get_event (i
).get_stack_depth () != first_fn_stack_depth
)
991 default_diagnostic_starter (diagnostic_context
*context
,
992 diagnostic_info
*diagnostic
)
994 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
995 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
1000 default_diagnostic_start_span_fn (diagnostic_context
*context
,
1001 expanded_location exploc
)
1003 char *text
= diagnostic_get_location_text (context
, exploc
);
1004 pp_string (context
->printer
, text
);
1006 pp_newline (context
->printer
);
1010 default_diagnostic_finalizer (diagnostic_context
*context
,
1011 diagnostic_info
*diagnostic
,
1014 char *saved_prefix
= pp_take_prefix (context
->printer
);
1015 pp_set_prefix (context
->printer
, NULL
);
1016 pp_newline (context
->printer
);
1017 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
1018 pp_set_prefix (context
->printer
, saved_prefix
);
1019 pp_flush (context
->printer
);
1022 /* Interface to specify diagnostic kind overrides. Returns the
1023 previous setting, or DK_UNSPECIFIED if the parameters are out of
1024 range. If OPTION_INDEX is zero, the new setting is for all the
1027 diagnostic_classify_diagnostic (diagnostic_context
*context
,
1029 diagnostic_t new_kind
,
1032 diagnostic_t old_kind
;
1034 if (option_index
< 0
1035 || option_index
>= context
->n_opts
1036 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
1037 return DK_UNSPECIFIED
;
1039 old_kind
= context
->classify_diagnostic
[option_index
];
1041 /* Handle pragmas separately, since we need to keep track of *where*
1042 the pragmas were. */
1043 if (where
!= UNKNOWN_LOCATION
)
1047 /* Record the command-line status, so we can reset it back on DK_POP. */
1048 if (old_kind
== DK_UNSPECIFIED
)
1050 old_kind
= !context
->option_enabled (option_index
,
1052 context
->option_state
)
1053 ? DK_IGNORED
: (context
->warning_as_error_requested
1054 ? DK_ERROR
: DK_WARNING
);
1055 context
->classify_diagnostic
[option_index
] = old_kind
;
1058 for (i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1059 if (context
->classification_history
[i
].option
== option_index
)
1061 old_kind
= context
->classification_history
[i
].kind
;
1065 i
= context
->n_classification_history
;
1066 context
->classification_history
=
1067 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1068 * sizeof (diagnostic_classification_change_t
));
1069 context
->classification_history
[i
].location
= where
;
1070 context
->classification_history
[i
].option
= option_index
;
1071 context
->classification_history
[i
].kind
= new_kind
;
1072 context
->n_classification_history
++;
1075 context
->classify_diagnostic
[option_index
] = new_kind
;
1080 /* Save all diagnostic classifications in a stack. */
1082 diagnostic_push_diagnostics (diagnostic_context
*context
, location_t where ATTRIBUTE_UNUSED
)
1084 context
->push_list
= (int *) xrealloc (context
->push_list
, (context
->n_push
+ 1) * sizeof (int));
1085 context
->push_list
[context
->n_push
++] = context
->n_classification_history
;
1088 /* Restore the topmost classification set off the stack. If the stack
1089 is empty, revert to the state based on command line parameters. */
1091 diagnostic_pop_diagnostics (diagnostic_context
*context
, location_t where
)
1096 if (context
->n_push
)
1097 jump_to
= context
->push_list
[-- context
->n_push
];
1101 i
= context
->n_classification_history
;
1102 context
->classification_history
=
1103 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1104 * sizeof (diagnostic_classification_change_t
));
1105 context
->classification_history
[i
].location
= where
;
1106 context
->classification_history
[i
].option
= jump_to
;
1107 context
->classification_history
[i
].kind
= DK_POP
;
1108 context
->n_classification_history
++;
1111 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1112 escaping rules for -fdiagnostics-parseable-fixits. */
1115 print_escaped_string (pretty_printer
*pp
, const char *text
)
1120 pp_character (pp
, '"');
1121 for (const char *ch
= text
; *ch
; ch
++)
1126 /* Escape backslash as two backslashes. */
1127 pp_string (pp
, "\\\\");
1130 /* Escape tab as "\t". */
1131 pp_string (pp
, "\\t");
1134 /* Escape newline as "\n". */
1135 pp_string (pp
, "\\n");
1138 /* Escape doublequotes as \". */
1139 pp_string (pp
, "\\\"");
1143 pp_character (pp
, *ch
);
1145 /* Use octal for non-printable chars. */
1147 unsigned char c
= (*ch
& 0xff);
1148 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
1153 pp_character (pp
, '"');
1156 /* Implementation of -fdiagnostics-parseable-fixits and
1157 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1158 Print a machine-parseable version of all fixits in RICHLOC to PP,
1159 using COLUMN_UNIT to express columns.
1160 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1163 print_parseable_fixits (pretty_printer
*pp
, rich_location
*richloc
,
1164 enum diagnostics_column_unit column_unit
,
1168 gcc_assert (richloc
);
1170 char *saved_prefix
= pp_take_prefix (pp
);
1171 pp_set_prefix (pp
, NULL
);
1173 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
1175 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
1176 location_t start_loc
= hint
->get_start_loc ();
1177 expanded_location start_exploc
= expand_location (start_loc
);
1178 pp_string (pp
, "fix-it:");
1179 print_escaped_string (pp
, start_exploc
.file
);
1180 /* For compatibility with clang, print as a half-open range. */
1181 location_t next_loc
= hint
->get_next_loc ();
1182 expanded_location next_exploc
= expand_location (next_loc
);
1184 = convert_column_unit (column_unit
, tabstop
, start_exploc
);
1186 = convert_column_unit (column_unit
, tabstop
, next_exploc
);
1187 pp_printf (pp
, ":{%i:%i-%i:%i}:",
1188 start_exploc
.line
, start_col
,
1189 next_exploc
.line
, next_col
);
1190 print_escaped_string (pp
, hint
->get_string ());
1194 pp_set_prefix (pp
, saved_prefix
);
1197 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1200 get_any_inlining_info (diagnostic_context
*context
,
1201 diagnostic_info
*diagnostic
)
1203 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1205 if (context
->set_locations_cb
)
1206 /* Retrieve the locations into which the expression about to be
1207 diagnosed has been inlined, including those of all the callers
1208 all the way down the inlining stack. */
1209 context
->set_locations_cb (context
, diagnostic
);
1212 /* When there's no callback use just the one location provided
1213 by the caller of the diagnostic function. */
1214 location_t loc
= diagnostic_location (diagnostic
);
1215 ilocs
.safe_push (loc
);
1216 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1220 /* Update the kind of DIAGNOSTIC based on its location(s), including
1221 any of those in its inlining stack, relative to any
1222 #pragma GCC diagnostic
1223 directives recorded within CONTEXT.
1225 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1229 update_effective_level_from_pragmas (diagnostic_context
*context
,
1230 diagnostic_info
*diagnostic
)
1232 if (diagnostic
->m_iinfo
.m_allsyslocs
&& !context
->dc_warn_system_headers
)
1234 /* Ignore the diagnostic if all the inlined locations are
1235 in system headers and -Wno-system-headers is in effect. */
1236 diagnostic
->kind
= DK_IGNORED
;
1240 if (context
->n_classification_history
<= 0)
1241 return DK_UNSPECIFIED
;
1243 /* Iterate over the locations, checking the diagnostic disposition
1244 for the diagnostic at each. If it's explicitly set as opposed
1245 to unspecified, update the disposition for this instance of
1246 the diagnostic and return it. */
1247 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1249 /* FIXME: Stupid search. Optimize later. */
1250 for (int i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1252 const diagnostic_classification_change_t
&hist
1253 = context
->classification_history
[i
];
1255 location_t pragloc
= hist
.location
;
1256 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1259 if (hist
.kind
== (int) DK_POP
)
1261 /* Move on to the next region. */
1266 int option
= hist
.option
;
1267 /* The option 0 is for all the diagnostics. */
1268 if (option
== 0 || option
== diagnostic
->option_index
)
1270 diagnostic_t kind
= hist
.kind
;
1271 if (kind
!= DK_UNSPECIFIED
)
1272 diagnostic
->kind
= kind
;
1278 return DK_UNSPECIFIED
;
1281 /* Generate a URL string describing CWE. The caller is responsible for
1282 freeing the string. */
1285 get_cwe_url (int cwe
)
1287 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1290 /* If DIAGNOSTIC has a CWE identifier, print it.
1292 For example, if the diagnostic metadata associates it with CWE-119,
1293 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1294 description of the security issue. */
1297 print_any_cwe (diagnostic_context
*context
,
1298 const diagnostic_info
*diagnostic
)
1300 if (diagnostic
->metadata
== NULL
)
1303 int cwe
= diagnostic
->metadata
->get_cwe ();
1306 pretty_printer
*pp
= context
->printer
;
1307 char *saved_prefix
= pp_take_prefix (context
->printer
);
1308 pp_string (pp
, " [");
1309 pp_string (pp
, colorize_start (pp_show_color (pp
),
1310 diagnostic_kind_color
[diagnostic
->kind
]));
1311 if (pp
->url_format
!= URL_FORMAT_NONE
)
1313 char *cwe_url
= get_cwe_url (cwe
);
1314 pp_begin_url (pp
, cwe_url
);
1317 pp_printf (pp
, "CWE-%i", cwe
);
1318 pp_set_prefix (context
->printer
, saved_prefix
);
1319 if (pp
->url_format
!= URL_FORMAT_NONE
)
1321 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1322 pp_character (pp
, ']');
1326 /* If DIAGNOSTIC has any rules associated with it, print them.
1328 For example, if the diagnostic metadata associates it with a rule
1329 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1330 with any URL provided by the rule. */
1333 print_any_rules (diagnostic_context
*context
,
1334 const diagnostic_info
*diagnostic
)
1336 if (diagnostic
->metadata
== NULL
)
1339 for (unsigned idx
= 0; idx
< diagnostic
->metadata
->get_num_rules (); idx
++)
1341 const diagnostic_metadata::rule
&rule
1342 = diagnostic
->metadata
->get_rule (idx
);
1343 if (char *desc
= rule
.make_description ())
1345 pretty_printer
*pp
= context
->printer
;
1346 char *saved_prefix
= pp_take_prefix (context
->printer
);
1347 pp_string (pp
, " [");
1349 colorize_start (pp_show_color (pp
),
1350 diagnostic_kind_color
[diagnostic
->kind
]));
1352 if (pp
->url_format
!= URL_FORMAT_NONE
)
1354 url
= rule
.make_url ();
1356 pp_begin_url (pp
, url
);
1358 pp_string (pp
, desc
);
1359 pp_set_prefix (context
->printer
, saved_prefix
);
1360 if (pp
->url_format
!= URL_FORMAT_NONE
)
1364 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1365 pp_character (pp
, ']');
1371 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1372 printer, e.g. " [-Werror=uninitialized]".
1373 Subroutine of diagnostic_report_diagnostic. */
1376 print_option_information (diagnostic_context
*context
,
1377 const diagnostic_info
*diagnostic
,
1378 diagnostic_t orig_diag_kind
)
1382 option_text
= context
->option_name (context
, diagnostic
->option_index
,
1383 orig_diag_kind
, diagnostic
->kind
);
1387 char *option_url
= NULL
;
1388 if (context
->get_option_url
1389 && context
->printer
->url_format
!= URL_FORMAT_NONE
)
1390 option_url
= context
->get_option_url (context
,
1391 diagnostic
->option_index
);
1392 pretty_printer
*pp
= context
->printer
;
1393 pp_string (pp
, " [");
1394 pp_string (pp
, colorize_start (pp_show_color (pp
),
1395 diagnostic_kind_color
[diagnostic
->kind
]));
1397 pp_begin_url (pp
, option_url
);
1398 pp_string (pp
, option_text
);
1404 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1405 pp_character (pp
, ']');
1410 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1411 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1414 diagnostic_enabled (diagnostic_context
*context
,
1415 diagnostic_info
*diagnostic
)
1417 /* Update the inlining stack for this diagnostic. */
1418 get_any_inlining_info (context
, diagnostic
);
1420 /* Diagnostics with no option or -fpermissive are always enabled. */
1421 if (!diagnostic
->option_index
1422 || diagnostic
->option_index
== permissive_error_option (context
))
1425 /* This tests if the user provided the appropriate -Wfoo or
1427 if (! context
->option_enabled (diagnostic
->option_index
,
1429 context
->option_state
))
1432 /* This tests for #pragma diagnostic changes. */
1433 diagnostic_t diag_class
1434 = update_effective_level_from_pragmas (context
, diagnostic
);
1436 /* This tests if the user provided the appropriate -Werror=foo
1438 if (diag_class
== DK_UNSPECIFIED
1439 && (context
->classify_diagnostic
[diagnostic
->option_index
]
1442 = context
->classify_diagnostic
[diagnostic
->option_index
];
1444 /* This allows for future extensions, like temporarily disabling
1445 warnings for ranges of source code. */
1446 if (diagnostic
->kind
== DK_IGNORED
)
1452 /* Returns whether warning OPT is enabled at LOC. */
1455 warning_enabled_at (location_t loc
, int opt
)
1457 if (!diagnostic_report_warnings_p (global_dc
, loc
))
1460 rich_location
richloc (line_table
, loc
);
1461 diagnostic_info diagnostic
= {};
1462 diagnostic
.option_index
= opt
;
1463 diagnostic
.richloc
= &richloc
;
1464 diagnostic
.message
.m_richloc
= &richloc
;
1465 diagnostic
.kind
= DK_WARNING
;
1466 return diagnostic_enabled (global_dc
, &diagnostic
);
1469 /* Report a diagnostic message (an error or a warning) as specified by
1470 DC. This function is *the* subroutine in terms of which front-ends
1471 should implement their specific diagnostic handling modules. The
1472 front-end independent format specifiers are exactly those described
1473 in the documentation of output_format.
1474 Return true if a diagnostic was printed, false otherwise. */
1477 diagnostic_report_diagnostic (diagnostic_context
*context
,
1478 diagnostic_info
*diagnostic
)
1480 location_t location
= diagnostic_location (diagnostic
);
1481 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1483 /* Give preference to being able to inhibit warnings, before they
1484 get reclassified to something else. */
1485 bool report_warning_p
= true;
1486 if (diagnostic
->kind
== DK_WARNING
|| diagnostic
->kind
== DK_PEDWARN
)
1488 if (context
->dc_inhibit_warnings
)
1490 /* Remember the result of the overall system header warning setting
1491 but proceed to also check the inlining context. */
1492 report_warning_p
= diagnostic_report_warnings_p (context
, location
);
1493 if (!report_warning_p
&& diagnostic
->kind
== DK_PEDWARN
)
1497 if (diagnostic
->kind
== DK_PEDWARN
)
1499 diagnostic
->kind
= pedantic_warning_kind (context
);
1500 /* We do this to avoid giving the message for -pedantic-errors. */
1501 orig_diag_kind
= diagnostic
->kind
;
1504 if (diagnostic
->kind
== DK_NOTE
&& context
->inhibit_notes_p
)
1507 if (context
->lock
> 0)
1509 /* If we're reporting an ICE in the middle of some other error,
1510 try to flush out the previous error, then let this one
1511 through. Don't do this more than once. */
1512 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1513 && context
->lock
== 1)
1514 pp_newline_and_flush (context
->printer
);
1516 error_recursion (context
);
1519 /* If the user requested that warnings be treated as errors, so be
1520 it. Note that we do this before the next block so that
1521 individual warnings can be overridden back to warnings with
1523 if (context
->warning_as_error_requested
1524 && diagnostic
->kind
== DK_WARNING
)
1525 diagnostic
->kind
= DK_ERROR
;
1527 diagnostic
->message
.x_data
= &diagnostic
->x_data
;
1529 /* Check to see if the diagnostic is enabled at the location and
1530 not disabled by #pragma GCC diagnostic anywhere along the inlining
1532 if (!diagnostic_enabled (context
, diagnostic
))
1535 if (!report_warning_p
&& diagnostic
->m_iinfo
.m_allsyslocs
)
1536 /* Bail if the warning is not to be reported because all locations
1537 in the inlining stack (if there is one) are in system headers. */
1540 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1541 diagnostic_check_max_errors (context
);
1545 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1547 /* When not checking, ICEs are converted to fatal errors when an
1548 error has already occurred. This is counteracted by
1551 && (diagnostic_kind_count (context
, DK_ERROR
) > 0
1552 || diagnostic_kind_count (context
, DK_SORRY
) > 0)
1553 && !context
->abort_on_error
)
1556 = expand_location (diagnostic_location (diagnostic
));
1557 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1559 exit (ICE_EXIT_CODE
);
1561 if (context
->internal_error
)
1562 (*context
->internal_error
) (context
,
1563 diagnostic
->message
.format_spec
,
1564 diagnostic
->message
.args_ptr
);
1566 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1567 ++diagnostic_kind_count (context
, DK_WERROR
);
1569 ++diagnostic_kind_count (context
, diagnostic
->kind
);
1571 /* Is this the initial diagnostic within the stack of groups? */
1572 if (context
->diagnostic_group_emission_count
== 0)
1574 if (context
->begin_group_cb
)
1575 context
->begin_group_cb (context
);
1577 context
->diagnostic_group_emission_count
++;
1579 pp_format (context
->printer
, &diagnostic
->message
);
1580 (*diagnostic_starter (context
)) (context
, diagnostic
);
1581 pp_output_formatted_text (context
->printer
);
1582 if (context
->show_cwe
)
1583 print_any_cwe (context
, diagnostic
);
1584 if (context
->show_rules
)
1585 print_any_rules (context
, diagnostic
);
1586 if (context
->show_option_requested
)
1587 print_option_information (context
, diagnostic
, orig_diag_kind
);
1588 (*diagnostic_finalizer (context
)) (context
, diagnostic
, orig_diag_kind
);
1589 switch (context
->extra_output_kind
)
1593 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1594 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1595 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1597 pp_flush (context
->printer
);
1599 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1600 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1601 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1603 pp_flush (context
->printer
);
1606 diagnostic_action_after_output (context
, diagnostic
->kind
);
1607 diagnostic
->x_data
= NULL
;
1609 if (context
->edit_context_ptr
)
1610 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1611 context
->edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1615 diagnostic_show_any_path (context
, diagnostic
);
1620 /* Get the number of digits in the decimal representation of VALUE. */
1623 num_digits (int value
)
1625 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1626 using floating point. */
1627 gcc_assert (value
>= 0);
1641 /* Given a partial pathname as input, return another pathname that
1642 shares no directory elements with the pathname of __FILE__. This
1643 is used by fancy_abort() to print `internal compiler error in expr.cc'
1644 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1647 trim_filename (const char *name
)
1649 static const char this_file
[] = __FILE__
;
1650 const char *p
= name
, *q
= this_file
;
1652 /* First skip any "../" in each filename. This allows us to give a proper
1653 reference to a file in a subdirectory. */
1654 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1657 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1660 /* Now skip any parts the two filenames have in common. */
1661 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1664 /* Now go backwards until the previous directory separator. */
1665 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1671 /* Standard error reporting routines in increasing order of severity.
1672 All of these take arguments like printf. */
1674 /* Text to be emitted verbatim to the error message stream; this
1675 produces no prefix and disables line-wrapping. Use rarely. */
1677 verbatim (const char *gmsgid
, ...)
1682 va_start (ap
, gmsgid
);
1683 text
.err_no
= errno
;
1684 text
.args_ptr
= &ap
;
1685 text
.format_spec
= _(gmsgid
);
1687 pp_format_verbatim (global_dc
->printer
, &text
);
1688 pp_newline_and_flush (global_dc
->printer
);
1692 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1694 diagnostic_append_note (diagnostic_context
*context
,
1695 location_t location
,
1696 const char * gmsgid
, ...)
1698 diagnostic_info diagnostic
;
1700 rich_location
richloc (line_table
, location
);
1702 va_start (ap
, gmsgid
);
1703 diagnostic_set_info (&diagnostic
, gmsgid
, &ap
, &richloc
, DK_NOTE
);
1704 if (context
->inhibit_notes_p
)
1709 char *saved_prefix
= pp_take_prefix (context
->printer
);
1710 pp_set_prefix (context
->printer
,
1711 diagnostic_build_prefix (context
, &diagnostic
));
1712 pp_format (context
->printer
, &diagnostic
.message
);
1713 pp_output_formatted_text (context
->printer
);
1714 pp_destroy_prefix (context
->printer
);
1715 pp_set_prefix (context
->printer
, saved_prefix
);
1716 pp_newline (context
->printer
);
1717 diagnostic_show_locus (context
, &richloc
, DK_NOTE
);
1721 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1722 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1723 and internal_error_no_backtrace, as documented and defined below. */
1725 diagnostic_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1726 int opt
, const char *gmsgid
,
1727 va_list *ap
, diagnostic_t kind
)
1729 diagnostic_info diagnostic
;
1730 if (kind
== DK_PERMERROR
)
1732 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
,
1733 permissive_error_kind (global_dc
));
1734 diagnostic
.option_index
= permissive_error_option (global_dc
);
1738 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1739 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1740 diagnostic
.option_index
= opt
;
1742 diagnostic
.metadata
= metadata
;
1743 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1746 /* Implement inform_n, warning_n, and error_n, as documented and
1749 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1750 int opt
, unsigned HOST_WIDE_INT n
,
1751 const char *singular_gmsgid
,
1752 const char *plural_gmsgid
,
1753 va_list *ap
, diagnostic_t kind
)
1755 diagnostic_info diagnostic
;
1758 if (sizeof n
<= sizeof gtn
)
1761 /* Use the largest number ngettext can handle, otherwise
1762 preserve the six least significant decimal digits for
1763 languages where the plural form depends on them. */
1764 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1766 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1767 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1768 if (kind
== DK_WARNING
)
1769 diagnostic
.option_index
= opt
;
1770 diagnostic
.metadata
= metadata
;
1771 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1774 /* Wrapper around diagnostic_impl taking a variable argument list. */
1777 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1778 const char *gmsgid
, ...)
1780 auto_diagnostic_group d
;
1782 va_start (ap
, gmsgid
);
1783 rich_location
richloc (line_table
, location
);
1784 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1789 /* As above, but for rich_location *. */
1792 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1793 const char *gmsgid
, ...)
1795 auto_diagnostic_group d
;
1797 va_start (ap
, gmsgid
);
1798 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1803 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1806 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1807 const char *gmsgid
, va_list *ap
)
1809 rich_location
richloc (line_table
, location
);
1810 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1813 /* An informative note at LOCATION. Use this for additional details on an error
1816 inform (location_t location
, const char *gmsgid
, ...)
1818 auto_diagnostic_group d
;
1820 va_start (ap
, gmsgid
);
1821 rich_location
richloc (line_table
, location
);
1822 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1826 /* Same as "inform" above, but at RICHLOC. */
1828 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1830 gcc_assert (richloc
);
1832 auto_diagnostic_group d
;
1834 va_start (ap
, gmsgid
);
1835 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1839 /* An informative note at LOCATION. Use this for additional details on an
1842 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1843 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1846 va_start (ap
, plural_gmsgid
);
1847 auto_diagnostic_group d
;
1848 rich_location
richloc (line_table
, location
);
1849 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1854 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1855 to the relevant language specification but is likely to be buggy anyway.
1856 Returns true if the warning was printed, false if it was inhibited. */
1858 warning (int opt
, const char *gmsgid
, ...)
1860 auto_diagnostic_group d
;
1862 va_start (ap
, gmsgid
);
1863 rich_location
richloc (line_table
, input_location
);
1864 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1869 /* A warning at LOCATION. Use this for code which is correct according to the
1870 relevant language specification but is likely to be buggy anyway.
1871 Returns true if the warning was printed, false if it was inhibited. */
1874 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1876 auto_diagnostic_group d
;
1878 va_start (ap
, gmsgid
);
1879 rich_location
richloc (line_table
, location
);
1880 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1885 /* Same as "warning at" above, but using RICHLOC. */
1888 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1890 gcc_assert (richloc
);
1892 auto_diagnostic_group d
;
1894 va_start (ap
, gmsgid
);
1895 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1900 /* Same as "warning at" above, but using METADATA. */
1903 warning_meta (rich_location
*richloc
,
1904 const diagnostic_metadata
&metadata
,
1905 int opt
, const char *gmsgid
, ...)
1907 gcc_assert (richloc
);
1909 auto_diagnostic_group d
;
1911 va_start (ap
, gmsgid
);
1913 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1919 /* Same as warning_n plural variant below, but using RICHLOC. */
1922 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1923 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1925 gcc_assert (richloc
);
1927 auto_diagnostic_group d
;
1929 va_start (ap
, plural_gmsgid
);
1930 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1931 singular_gmsgid
, plural_gmsgid
,
1937 /* A warning at LOCATION. Use this for code which is correct according to the
1938 relevant language specification but is likely to be buggy anyway.
1939 Returns true if the warning was printed, false if it was inhibited. */
1942 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1943 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1945 auto_diagnostic_group d
;
1947 va_start (ap
, plural_gmsgid
);
1948 rich_location
richloc (line_table
, location
);
1949 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1950 singular_gmsgid
, plural_gmsgid
,
1956 /* A "pedantic" warning at LOCATION: issues a warning unless
1957 -pedantic-errors was given on the command line, in which case it
1958 issues an error. Use this for diagnostics required by the relevant
1959 language standard, if you have chosen not to make them errors.
1961 Note that these diagnostics are issued independent of the setting
1962 of the -Wpedantic command-line switch. To get a warning enabled
1963 only with that switch, use either "if (pedantic) pedwarn
1964 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1965 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1967 Returns true if the warning was printed, false if it was inhibited. */
1970 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
1972 auto_diagnostic_group d
;
1974 va_start (ap
, gmsgid
);
1975 rich_location
richloc (line_table
, location
);
1976 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1981 /* Same as pedwarn above, but using RICHLOC. */
1984 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1986 gcc_assert (richloc
);
1988 auto_diagnostic_group d
;
1990 va_start (ap
, gmsgid
);
1991 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1996 /* A "permissive" error at LOCATION: issues an error unless
1997 -fpermissive was given on the command line, in which case it issues
1998 a warning. Use this for things that really should be errors but we
1999 want to support legacy code.
2001 Returns true if the warning was printed, false if it was inhibited. */
2004 permerror (location_t location
, const char *gmsgid
, ...)
2006 auto_diagnostic_group d
;
2008 va_start (ap
, gmsgid
);
2009 rich_location
richloc (line_table
, location
);
2010 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2015 /* Same as "permerror" above, but at RICHLOC. */
2018 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
2020 gcc_assert (richloc
);
2022 auto_diagnostic_group d
;
2024 va_start (ap
, gmsgid
);
2025 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
2030 /* A hard error: the code is definitely ill-formed, and an object file
2031 will not be produced. */
2033 error (const char *gmsgid
, ...)
2035 auto_diagnostic_group d
;
2037 va_start (ap
, gmsgid
);
2038 rich_location
richloc (line_table
, input_location
);
2039 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2043 /* A hard error: the code is definitely ill-formed, and an object file
2044 will not be produced. */
2046 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
2047 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
2049 auto_diagnostic_group d
;
2051 va_start (ap
, plural_gmsgid
);
2052 rich_location
richloc (line_table
, location
);
2053 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
2058 /* Same as above, but use location LOC instead of input_location. */
2060 error_at (location_t loc
, const char *gmsgid
, ...)
2062 auto_diagnostic_group d
;
2064 va_start (ap
, gmsgid
);
2065 rich_location
richloc (line_table
, loc
);
2066 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2070 /* Same as above, but use RICH_LOC. */
2073 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
2075 gcc_assert (richloc
);
2077 auto_diagnostic_group d
;
2079 va_start (ap
, gmsgid
);
2080 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2084 /* "Sorry, not implemented." Use for a language feature which is
2085 required by the relevant specification but not implemented by GCC.
2086 An object file will not be produced. */
2088 sorry (const char *gmsgid
, ...)
2090 auto_diagnostic_group d
;
2092 va_start (ap
, gmsgid
);
2093 rich_location
richloc (line_table
, input_location
);
2094 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2098 /* Same as above, but use location LOC instead of input_location. */
2100 sorry_at (location_t loc
, const char *gmsgid
, ...)
2102 auto_diagnostic_group d
;
2104 va_start (ap
, gmsgid
);
2105 rich_location
richloc (line_table
, loc
);
2106 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2110 /* Return true if an error or a "sorry" has been seen. Various
2111 processing is disabled after errors. */
2115 return errorcount
|| sorrycount
;
2118 /* An error which is severe enough that we make no attempt to
2119 continue. Do not use this for internal consistency checks; that's
2120 internal_error. Use of this function should be rare. */
2122 fatal_error (location_t loc
, const char *gmsgid
, ...)
2124 auto_diagnostic_group d
;
2126 va_start (ap
, gmsgid
);
2127 rich_location
richloc (line_table
, loc
);
2128 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
2134 /* An internal consistency check has failed. We make no attempt to
2137 internal_error (const char *gmsgid
, ...)
2139 auto_diagnostic_group d
;
2141 va_start (ap
, gmsgid
);
2142 rich_location
richloc (line_table
, input_location
);
2143 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
2149 /* Like internal_error, but no backtrace will be printed. Used when
2150 the internal error does not happen at the current location, but happened
2153 internal_error_no_backtrace (const char *gmsgid
, ...)
2155 auto_diagnostic_group d
;
2157 va_start (ap
, gmsgid
);
2158 rich_location
richloc (line_table
, input_location
);
2159 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
2165 /* Special case error functions. Most are implemented in terms of the
2166 above, or should be. */
2168 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2169 runs its second argument through gettext. */
2171 fnotice (FILE *file
, const char *cmsgid
, ...)
2175 va_start (ap
, cmsgid
);
2176 vfprintf (file
, _(cmsgid
), ap
);
2180 /* Inform the user that an error occurred while trying to report some
2181 other error. This indicates catastrophic internal inconsistencies,
2182 so give up now. But do try to flush out the previous error.
2183 This mustn't use internal_error, that will cause infinite recursion. */
2186 error_recursion (diagnostic_context
*context
)
2188 if (context
->lock
< 3)
2189 pp_newline_and_flush (context
->printer
);
2192 "internal compiler error: error reporting routines re-entered.\n");
2194 /* Call diagnostic_action_after_output to get the "please submit a bug
2196 diagnostic_action_after_output (context
, DK_ICE
);
2198 /* Do not use gcc_unreachable here; that goes through internal_error
2199 and therefore would cause infinite recursion. */
2203 /* Report an internal compiler error in a friendly manner. This is
2204 the function that gets called upon use of abort() in the source
2205 code generally, thanks to a special macro. */
2208 fancy_abort (const char *file
, int line
, const char *function
)
2210 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2211 internal_error will crash internally in a way that prevents a
2212 useful message reaching the user.
2213 This can happen with libgccjit in the case of gcc_assert failures
2214 that occur outside of the libgccjit mutex that guards the rest of
2215 gcc's state, including global_dc (when global_dc may not be
2216 initialized yet, or might be in use by another thread).
2217 Handle such cases as gracefully as possible by falling back to a
2218 minimal abort handler that only relies on i18n. */
2219 if (global_dc
->printer
== NULL
)
2221 /* Print the error message. */
2222 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
2223 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
2224 fputc ('\n', stderr
);
2226 /* Attempt to print a backtrace. */
2227 struct backtrace_state
*state
2228 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
2231 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
2234 /* We can't call warn_if_plugins or emergency_dump_function as these
2235 rely on GCC state that might not be initialized, or might be in
2236 use by another thread. */
2238 /* Abort the process. */
2242 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2245 /* class auto_diagnostic_group. */
2247 /* Constructor: "push" this group into global_dc. */
2249 auto_diagnostic_group::auto_diagnostic_group ()
2251 global_dc
->diagnostic_group_nesting_depth
++;
2254 /* Destructor: "pop" this group from global_dc. */
2256 auto_diagnostic_group::~auto_diagnostic_group ()
2258 if (--global_dc
->diagnostic_group_nesting_depth
== 0)
2260 /* Handle the case where we've popped the final diagnostic group.
2261 If any diagnostics were emitted, give the context a chance
2263 if (global_dc
->diagnostic_group_emission_count
> 0)
2265 if (global_dc
->end_group_cb
)
2266 global_dc
->end_group_cb (global_dc
);
2268 global_dc
->diagnostic_group_emission_count
= 0;
2272 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2273 file-based output formats. */
2276 diagnostic_output_format_init (diagnostic_context
*context
,
2277 const char *base_file_name
,
2278 enum diagnostics_output_format format
)
2284 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT
:
2285 /* The default; do nothing. */
2288 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR
:
2289 diagnostic_output_format_init_json_stderr (context
);
2292 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
:
2293 diagnostic_output_format_init_json_file (context
, base_file_name
);
2296 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR
:
2297 diagnostic_output_format_init_sarif_stderr (context
);
2300 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
:
2301 diagnostic_output_format_init_sarif_file (context
, base_file_name
);
2306 /* Implementation of diagnostic_path::num_events vfunc for
2307 simple_diagnostic_path: simply get the number of events in the vec. */
2310 simple_diagnostic_path::num_events () const
2312 return m_events
.length ();
2315 /* Implementation of diagnostic_path::get_event vfunc for
2316 simple_diagnostic_path: simply return the event in the vec. */
2318 const diagnostic_event
&
2319 simple_diagnostic_path::get_event (int idx
) const
2321 return *m_events
[idx
];
2324 /* Add an event to this path at LOC within function FNDECL at
2327 Use m_context's printer to format FMT, as the text of the new
2330 Return the id of the new event. */
2332 diagnostic_event_id_t
2333 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2334 const char *fmt
, ...)
2336 pretty_printer
*pp
= m_event_pp
;
2337 pp_clear_output_area (pp
);
2340 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2346 ti
.format_spec
= _(fmt
);
2350 ti
.m_richloc
= &rich_loc
;
2352 pp_format (pp
, &ti
);
2353 pp_output_formatted_text (pp
);
2357 simple_diagnostic_event
*new_event
2358 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2359 m_events
.safe_push (new_event
);
2361 pp_clear_output_area (pp
);
2363 return diagnostic_event_id_t (m_events
.length () - 1);
2366 /* struct simple_diagnostic_event. */
2368 /* simple_diagnostic_event's ctor. */
2370 simple_diagnostic_event::simple_diagnostic_event (location_t loc
,
2374 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
))
2378 /* simple_diagnostic_event's dtor. */
2380 simple_diagnostic_event::~simple_diagnostic_event ()
2385 /* Print PATH by emitting a dummy "note" associated with it. */
2388 void debug (diagnostic_path
*path
)
2390 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2391 richloc
.set_path (path
);
2392 inform (&richloc
, "debug path");
2395 /* Really call the system 'abort'. This has to go right at the end of
2396 this file, so that there are no functions after it that call abort
2397 and get the system abort instead of our macro. */
2407 namespace selftest
{
2409 /* Helper function for test_print_escaped_string. */
2412 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2416 print_escaped_string (&pp
, input
);
2417 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2420 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2421 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2423 /* Tests of print_escaped_string. */
2426 test_print_escaped_string ()
2429 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2431 /* Non-empty string. */
2432 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2434 /* Various things that need to be escaped: */
2436 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2439 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2442 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2445 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2448 /* Non-printable characters: BEL: '\a': 0x07 */
2449 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2451 /* Non-printable characters: vertical tab: '\v': 0x0b */
2452 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2456 /* Tests of print_parseable_fixits. */
2458 /* Verify that print_parseable_fixits emits the empty string if there
2462 test_print_parseable_fixits_none ()
2465 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2467 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2468 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2471 /* Verify that print_parseable_fixits does the right thing if there
2472 is an insertion fixit hint. */
2475 test_print_parseable_fixits_insert ()
2478 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2480 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2481 linemap_line_start (line_table
, 5, 100);
2482 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2483 location_t where
= linemap_position_for_column (line_table
, 10);
2484 richloc
.add_fixit_insert_before (where
, "added content");
2486 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2487 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2488 pp_formatted_text (&pp
));
2491 /* Verify that print_parseable_fixits does the right thing if there
2492 is an removal fixit hint. */
2495 test_print_parseable_fixits_remove ()
2498 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2500 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2501 linemap_line_start (line_table
, 5, 100);
2502 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2504 where
.m_start
= linemap_position_for_column (line_table
, 10);
2505 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2506 richloc
.add_fixit_remove (where
);
2508 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2509 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2510 pp_formatted_text (&pp
));
2513 /* Verify that print_parseable_fixits does the right thing if there
2514 is an replacement fixit hint. */
2517 test_print_parseable_fixits_replace ()
2520 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2522 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2523 linemap_line_start (line_table
, 5, 100);
2524 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2526 where
.m_start
= linemap_position_for_column (line_table
, 10);
2527 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2528 richloc
.add_fixit_replace (where
, "replacement");
2530 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2531 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2532 pp_formatted_text (&pp
));
2535 /* Verify that print_parseable_fixits correctly handles
2536 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2539 test_print_parseable_fixits_bytes_vs_display_columns ()
2541 line_table_test ltt
;
2542 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2544 /* 1-based byte offsets: 12345677778888999900001234567. */
2545 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2546 /* 1-based display cols: 123456[......7-8.....]9012345. */
2547 const int tabstop
= 8;
2549 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2550 const char *const fname
= tmp
.get_filename ();
2552 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2553 linemap_line_start (line_table
, 1, 100);
2554 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2556 where
.m_start
= linemap_position_for_column (line_table
, 12);
2557 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2558 richloc
.add_fixit_replace (where
, "color");
2561 pretty_printer tmp_pp
;
2562 print_escaped_string (&tmp_pp
, fname
);
2563 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2565 const int buf_len
= strlen (escaped_fname
) + 100;
2566 char *const expected
= XNEWVEC (char, buf_len
);
2570 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2572 snprintf (expected
, buf_len
,
2573 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2574 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2578 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2580 snprintf (expected
, buf_len
,
2581 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2582 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2585 XDELETEVEC (expected
);
2586 free (escaped_fname
);
2590 diagnostic_get_location_text (..., SHOW_COLUMN)
2591 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2592 colorization disabled. */
2595 assert_location_text (const char *expected_loc_text
,
2596 const char *filename
, int line
, int column
,
2599 enum diagnostics_column_unit column_unit
2600 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2602 test_diagnostic_context dc
;
2603 dc
.show_column
= show_column
;
2604 dc
.column_unit
= column_unit
;
2605 dc
.column_origin
= origin
;
2607 expanded_location xloc
;
2608 xloc
.file
= filename
;
2610 xloc
.column
= column
;
2614 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2615 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2616 free (actual_loc_text
);
2619 /* Verify that diagnostic_get_location_text works as expected. */
2622 test_diagnostic_get_location_text ()
2624 const char *old_progname
= progname
;
2625 progname
= "PROGNAME";
2626 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2627 char *built_in_colon
= concat (special_fname_builtin (), ":", (char *) 0);
2628 assert_location_text (built_in_colon
, special_fname_builtin (),
2630 free (built_in_colon
);
2631 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2632 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2633 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2634 for (int origin
= 0; origin
!= 2; ++origin
)
2635 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2636 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2637 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2638 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2640 maybe_line_and_column (INT_MAX
, INT_MAX
);
2641 maybe_line_and_column (INT_MIN
, INT_MIN
);
2644 /* In order to test display columns vs byte columns, we need to create a
2645 file for location_get_source_line() to read. */
2647 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2648 const int line_bytes
= strlen (content
) - 1;
2649 const int def_tabstop
= 8;
2650 const cpp_char_column_policy
policy (def_tabstop
, cpp_wcwidth
);
2651 const int display_width
= cpp_display_width (content
, line_bytes
, policy
);
2652 ASSERT_EQ (line_bytes
- 2, display_width
);
2653 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2654 const char *const fname
= tmp
.get_filename ();
2655 const int buf_len
= strlen (fname
) + 16;
2656 char *const expected
= XNEWVEC (char, buf_len
);
2658 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2659 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2660 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2662 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2663 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2664 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2666 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2667 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2668 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2670 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2671 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2672 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2674 XDELETEVEC (expected
);
2678 progname
= old_progname
;
2681 /* Selftest for num_digits. */
2686 ASSERT_EQ (1, num_digits (0));
2687 ASSERT_EQ (1, num_digits (9));
2688 ASSERT_EQ (2, num_digits (10));
2689 ASSERT_EQ (2, num_digits (99));
2690 ASSERT_EQ (3, num_digits (100));
2691 ASSERT_EQ (3, num_digits (999));
2692 ASSERT_EQ (4, num_digits (1000));
2693 ASSERT_EQ (4, num_digits (9999));
2694 ASSERT_EQ (5, num_digits (10000));
2695 ASSERT_EQ (5, num_digits (99999));
2696 ASSERT_EQ (6, num_digits (100000));
2697 ASSERT_EQ (6, num_digits (999999));
2698 ASSERT_EQ (7, num_digits (1000000));
2699 ASSERT_EQ (7, num_digits (9999999));
2700 ASSERT_EQ (8, num_digits (10000000));
2701 ASSERT_EQ (8, num_digits (99999999));
2704 /* Run all of the selftests within this file. */
2707 c_diagnostic_cc_tests ()
2709 test_print_escaped_string ();
2710 test_print_parseable_fixits_none ();
2711 test_print_parseable_fixits_insert ();
2712 test_print_parseable_fixits_remove ();
2713 test_print_parseable_fixits_replace ();
2714 test_print_parseable_fixits_bytes_vs_display_columns ();
2715 test_diagnostic_get_location_text ();
2720 } // namespace selftest
2722 #endif /* #if CHECKING_P */
2725 # pragma GCC diagnostic pop