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
, N_("<built-in>")))
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 /* Return true if the events in this path involve more than one
943 function, or false if it is purely intraprocedural. */
946 diagnostic_path::interprocedural_p () const
948 const unsigned num
= num_events ();
949 for (unsigned i
= 0; i
< num
; i
++)
951 if (get_event (i
).get_fndecl () != get_event (0).get_fndecl ())
953 if (get_event (i
).get_stack_depth () != get_event (0).get_stack_depth ())
960 default_diagnostic_starter (diagnostic_context
*context
,
961 diagnostic_info
*diagnostic
)
963 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
964 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
969 default_diagnostic_start_span_fn (diagnostic_context
*context
,
970 expanded_location exploc
)
972 char *text
= diagnostic_get_location_text (context
, exploc
);
973 pp_string (context
->printer
, text
);
975 pp_newline (context
->printer
);
979 default_diagnostic_finalizer (diagnostic_context
*context
,
980 diagnostic_info
*diagnostic
,
983 char *saved_prefix
= pp_take_prefix (context
->printer
);
984 pp_set_prefix (context
->printer
, NULL
);
985 pp_newline (context
->printer
);
986 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
987 pp_set_prefix (context
->printer
, saved_prefix
);
988 pp_flush (context
->printer
);
991 /* Interface to specify diagnostic kind overrides. Returns the
992 previous setting, or DK_UNSPECIFIED if the parameters are out of
993 range. If OPTION_INDEX is zero, the new setting is for all the
996 diagnostic_classify_diagnostic (diagnostic_context
*context
,
998 diagnostic_t new_kind
,
1001 diagnostic_t old_kind
;
1003 if (option_index
< 0
1004 || option_index
>= context
->n_opts
1005 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
1006 return DK_UNSPECIFIED
;
1008 old_kind
= context
->classify_diagnostic
[option_index
];
1010 /* Handle pragmas separately, since we need to keep track of *where*
1011 the pragmas were. */
1012 if (where
!= UNKNOWN_LOCATION
)
1016 /* Record the command-line status, so we can reset it back on DK_POP. */
1017 if (old_kind
== DK_UNSPECIFIED
)
1019 old_kind
= !context
->option_enabled (option_index
,
1021 context
->option_state
)
1022 ? DK_IGNORED
: (context
->warning_as_error_requested
1023 ? DK_ERROR
: DK_WARNING
);
1024 context
->classify_diagnostic
[option_index
] = old_kind
;
1027 for (i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1028 if (context
->classification_history
[i
].option
== option_index
)
1030 old_kind
= context
->classification_history
[i
].kind
;
1034 i
= context
->n_classification_history
;
1035 context
->classification_history
=
1036 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1037 * sizeof (diagnostic_classification_change_t
));
1038 context
->classification_history
[i
].location
= where
;
1039 context
->classification_history
[i
].option
= option_index
;
1040 context
->classification_history
[i
].kind
= new_kind
;
1041 context
->n_classification_history
++;
1044 context
->classify_diagnostic
[option_index
] = new_kind
;
1049 /* Save all diagnostic classifications in a stack. */
1051 diagnostic_push_diagnostics (diagnostic_context
*context
, location_t where ATTRIBUTE_UNUSED
)
1053 context
->push_list
= (int *) xrealloc (context
->push_list
, (context
->n_push
+ 1) * sizeof (int));
1054 context
->push_list
[context
->n_push
++] = context
->n_classification_history
;
1057 /* Restore the topmost classification set off the stack. If the stack
1058 is empty, revert to the state based on command line parameters. */
1060 diagnostic_pop_diagnostics (diagnostic_context
*context
, location_t where
)
1065 if (context
->n_push
)
1066 jump_to
= context
->push_list
[-- context
->n_push
];
1070 i
= context
->n_classification_history
;
1071 context
->classification_history
=
1072 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
1073 * sizeof (diagnostic_classification_change_t
));
1074 context
->classification_history
[i
].location
= where
;
1075 context
->classification_history
[i
].option
= jump_to
;
1076 context
->classification_history
[i
].kind
= DK_POP
;
1077 context
->n_classification_history
++;
1080 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
1081 escaping rules for -fdiagnostics-parseable-fixits. */
1084 print_escaped_string (pretty_printer
*pp
, const char *text
)
1089 pp_character (pp
, '"');
1090 for (const char *ch
= text
; *ch
; ch
++)
1095 /* Escape backslash as two backslashes. */
1096 pp_string (pp
, "\\\\");
1099 /* Escape tab as "\t". */
1100 pp_string (pp
, "\\t");
1103 /* Escape newline as "\n". */
1104 pp_string (pp
, "\\n");
1107 /* Escape doublequotes as \". */
1108 pp_string (pp
, "\\\"");
1112 pp_character (pp
, *ch
);
1114 /* Use octal for non-printable chars. */
1116 unsigned char c
= (*ch
& 0xff);
1117 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
1122 pp_character (pp
, '"');
1125 /* Implementation of -fdiagnostics-parseable-fixits and
1126 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
1127 Print a machine-parseable version of all fixits in RICHLOC to PP,
1128 using COLUMN_UNIT to express columns.
1129 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
1132 print_parseable_fixits (pretty_printer
*pp
, rich_location
*richloc
,
1133 enum diagnostics_column_unit column_unit
,
1137 gcc_assert (richloc
);
1139 char *saved_prefix
= pp_take_prefix (pp
);
1140 pp_set_prefix (pp
, NULL
);
1142 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
1144 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
1145 location_t start_loc
= hint
->get_start_loc ();
1146 expanded_location start_exploc
= expand_location (start_loc
);
1147 pp_string (pp
, "fix-it:");
1148 print_escaped_string (pp
, start_exploc
.file
);
1149 /* For compatibility with clang, print as a half-open range. */
1150 location_t next_loc
= hint
->get_next_loc ();
1151 expanded_location next_exploc
= expand_location (next_loc
);
1153 = convert_column_unit (column_unit
, tabstop
, start_exploc
);
1155 = convert_column_unit (column_unit
, tabstop
, next_exploc
);
1156 pp_printf (pp
, ":{%i:%i-%i:%i}:",
1157 start_exploc
.line
, start_col
,
1158 next_exploc
.line
, next_col
);
1159 print_escaped_string (pp
, hint
->get_string ());
1163 pp_set_prefix (pp
, saved_prefix
);
1166 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1169 get_any_inlining_info (diagnostic_context
*context
,
1170 diagnostic_info
*diagnostic
)
1172 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1174 if (context
->set_locations_cb
)
1175 /* Retrieve the locations into which the expression about to be
1176 diagnosed has been inlined, including those of all the callers
1177 all the way down the inlining stack. */
1178 context
->set_locations_cb (context
, diagnostic
);
1181 /* When there's no callback use just the one location provided
1182 by the caller of the diagnostic function. */
1183 location_t loc
= diagnostic_location (diagnostic
);
1184 ilocs
.safe_push (loc
);
1185 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1189 /* Update the kind of DIAGNOSTIC based on its location(s), including
1190 any of those in its inlining stack, relative to any
1191 #pragma GCC diagnostic
1192 directives recorded within CONTEXT.
1194 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1198 update_effective_level_from_pragmas (diagnostic_context
*context
,
1199 diagnostic_info
*diagnostic
)
1201 if (diagnostic
->m_iinfo
.m_allsyslocs
&& !context
->dc_warn_system_headers
)
1203 /* Ignore the diagnostic if all the inlined locations are
1204 in system headers and -Wno-system-headers is in effect. */
1205 diagnostic
->kind
= DK_IGNORED
;
1209 if (context
->n_classification_history
<= 0)
1210 return DK_UNSPECIFIED
;
1212 /* Iterate over the locations, checking the diagnostic disposition
1213 for the diagnostic at each. If it's explicitly set as opposed
1214 to unspecified, update the disposition for this instance of
1215 the diagnostic and return it. */
1216 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1218 /* FIXME: Stupid search. Optimize later. */
1219 for (int i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1221 const diagnostic_classification_change_t
&hist
1222 = context
->classification_history
[i
];
1224 location_t pragloc
= hist
.location
;
1225 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1228 if (hist
.kind
== (int) DK_POP
)
1230 /* Move on to the next region. */
1235 int option
= hist
.option
;
1236 /* The option 0 is for all the diagnostics. */
1237 if (option
== 0 || option
== diagnostic
->option_index
)
1239 diagnostic_t kind
= hist
.kind
;
1240 if (kind
!= DK_UNSPECIFIED
)
1241 diagnostic
->kind
= kind
;
1247 return DK_UNSPECIFIED
;
1250 /* Generate a URL string describing CWE. The caller is responsible for
1251 freeing the string. */
1254 get_cwe_url (int cwe
)
1256 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1259 /* If DIAGNOSTIC has a CWE identifier, print it.
1261 For example, if the diagnostic metadata associates it with CWE-119,
1262 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1263 description of the security issue. */
1266 print_any_cwe (diagnostic_context
*context
,
1267 const diagnostic_info
*diagnostic
)
1269 if (diagnostic
->metadata
== NULL
)
1272 int cwe
= diagnostic
->metadata
->get_cwe ();
1275 pretty_printer
*pp
= context
->printer
;
1276 char *saved_prefix
= pp_take_prefix (context
->printer
);
1277 pp_string (pp
, " [");
1278 pp_string (pp
, colorize_start (pp_show_color (pp
),
1279 diagnostic_kind_color
[diagnostic
->kind
]));
1280 if (pp
->url_format
!= URL_FORMAT_NONE
)
1282 char *cwe_url
= get_cwe_url (cwe
);
1283 pp_begin_url (pp
, cwe_url
);
1286 pp_printf (pp
, "CWE-%i", cwe
);
1287 pp_set_prefix (context
->printer
, saved_prefix
);
1288 if (pp
->url_format
!= URL_FORMAT_NONE
)
1290 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1291 pp_character (pp
, ']');
1295 /* If DIAGNOSTIC has any rules associated with it, print them.
1297 For example, if the diagnostic metadata associates it with a rule
1298 named "STR34-C", then " [STR34-C]" will be printed, suitably colorized,
1299 with any URL provided by the rule. */
1302 print_any_rules (diagnostic_context
*context
,
1303 const diagnostic_info
*diagnostic
)
1305 if (diagnostic
->metadata
== NULL
)
1308 for (unsigned idx
= 0; idx
< diagnostic
->metadata
->get_num_rules (); idx
++)
1310 const diagnostic_metadata::rule
&rule
1311 = diagnostic
->metadata
->get_rule (idx
);
1312 if (char *desc
= rule
.make_description ())
1314 pretty_printer
*pp
= context
->printer
;
1315 char *saved_prefix
= pp_take_prefix (context
->printer
);
1316 pp_string (pp
, " [");
1318 colorize_start (pp_show_color (pp
),
1319 diagnostic_kind_color
[diagnostic
->kind
]));
1321 if (pp
->url_format
!= URL_FORMAT_NONE
)
1323 url
= rule
.make_url ();
1325 pp_begin_url (pp
, url
);
1327 pp_string (pp
, desc
);
1328 pp_set_prefix (context
->printer
, saved_prefix
);
1329 if (pp
->url_format
!= URL_FORMAT_NONE
)
1333 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1334 pp_character (pp
, ']');
1340 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1341 printer, e.g. " [-Werror=uninitialized]".
1342 Subroutine of diagnostic_report_diagnostic. */
1345 print_option_information (diagnostic_context
*context
,
1346 const diagnostic_info
*diagnostic
,
1347 diagnostic_t orig_diag_kind
)
1351 option_text
= context
->option_name (context
, diagnostic
->option_index
,
1352 orig_diag_kind
, diagnostic
->kind
);
1356 char *option_url
= NULL
;
1357 if (context
->get_option_url
1358 && context
->printer
->url_format
!= URL_FORMAT_NONE
)
1359 option_url
= context
->get_option_url (context
,
1360 diagnostic
->option_index
);
1361 pretty_printer
*pp
= context
->printer
;
1362 pp_string (pp
, " [");
1363 pp_string (pp
, colorize_start (pp_show_color (pp
),
1364 diagnostic_kind_color
[diagnostic
->kind
]));
1366 pp_begin_url (pp
, option_url
);
1367 pp_string (pp
, option_text
);
1373 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1374 pp_character (pp
, ']');
1379 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1380 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1383 diagnostic_enabled (diagnostic_context
*context
,
1384 diagnostic_info
*diagnostic
)
1386 /* Update the inlining stack for this diagnostic. */
1387 get_any_inlining_info (context
, diagnostic
);
1389 /* Diagnostics with no option or -fpermissive are always enabled. */
1390 if (!diagnostic
->option_index
1391 || diagnostic
->option_index
== permissive_error_option (context
))
1394 /* This tests if the user provided the appropriate -Wfoo or
1396 if (! context
->option_enabled (diagnostic
->option_index
,
1398 context
->option_state
))
1401 /* This tests for #pragma diagnostic changes. */
1402 diagnostic_t diag_class
1403 = update_effective_level_from_pragmas (context
, diagnostic
);
1405 /* This tests if the user provided the appropriate -Werror=foo
1407 if (diag_class
== DK_UNSPECIFIED
1408 && (context
->classify_diagnostic
[diagnostic
->option_index
]
1411 = context
->classify_diagnostic
[diagnostic
->option_index
];
1413 /* This allows for future extensions, like temporarily disabling
1414 warnings for ranges of source code. */
1415 if (diagnostic
->kind
== DK_IGNORED
)
1421 /* Returns whether warning OPT is enabled at LOC. */
1424 warning_enabled_at (location_t loc
, int opt
)
1426 if (!diagnostic_report_warnings_p (global_dc
, loc
))
1429 rich_location
richloc (line_table
, loc
);
1430 diagnostic_info diagnostic
= {};
1431 diagnostic
.option_index
= opt
;
1432 diagnostic
.richloc
= &richloc
;
1433 diagnostic
.message
.m_richloc
= &richloc
;
1434 diagnostic
.kind
= DK_WARNING
;
1435 return diagnostic_enabled (global_dc
, &diagnostic
);
1438 /* Report a diagnostic message (an error or a warning) as specified by
1439 DC. This function is *the* subroutine in terms of which front-ends
1440 should implement their specific diagnostic handling modules. The
1441 front-end independent format specifiers are exactly those described
1442 in the documentation of output_format.
1443 Return true if a diagnostic was printed, false otherwise. */
1446 diagnostic_report_diagnostic (diagnostic_context
*context
,
1447 diagnostic_info
*diagnostic
)
1449 location_t location
= diagnostic_location (diagnostic
);
1450 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1452 /* Give preference to being able to inhibit warnings, before they
1453 get reclassified to something else. */
1454 bool report_warning_p
= true;
1455 if (diagnostic
->kind
== DK_WARNING
|| diagnostic
->kind
== DK_PEDWARN
)
1457 if (context
->dc_inhibit_warnings
)
1459 /* Remember the result of the overall system header warning setting
1460 but proceed to also check the inlining context. */
1461 report_warning_p
= diagnostic_report_warnings_p (context
, location
);
1462 if (!report_warning_p
&& diagnostic
->kind
== DK_PEDWARN
)
1466 if (diagnostic
->kind
== DK_PEDWARN
)
1468 diagnostic
->kind
= pedantic_warning_kind (context
);
1469 /* We do this to avoid giving the message for -pedantic-errors. */
1470 orig_diag_kind
= diagnostic
->kind
;
1473 if (diagnostic
->kind
== DK_NOTE
&& context
->inhibit_notes_p
)
1476 if (context
->lock
> 0)
1478 /* If we're reporting an ICE in the middle of some other error,
1479 try to flush out the previous error, then let this one
1480 through. Don't do this more than once. */
1481 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1482 && context
->lock
== 1)
1483 pp_newline_and_flush (context
->printer
);
1485 error_recursion (context
);
1488 /* If the user requested that warnings be treated as errors, so be
1489 it. Note that we do this before the next block so that
1490 individual warnings can be overridden back to warnings with
1492 if (context
->warning_as_error_requested
1493 && diagnostic
->kind
== DK_WARNING
)
1494 diagnostic
->kind
= DK_ERROR
;
1496 diagnostic
->message
.x_data
= &diagnostic
->x_data
;
1498 /* Check to see if the diagnostic is enabled at the location and
1499 not disabled by #pragma GCC diagnostic anywhere along the inlining
1501 if (!diagnostic_enabled (context
, diagnostic
))
1504 if (!report_warning_p
&& diagnostic
->m_iinfo
.m_allsyslocs
)
1505 /* Bail if the warning is not to be reported because all locations
1506 in the inlining stack (if there is one) are in system headers. */
1509 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1510 diagnostic_check_max_errors (context
);
1514 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1516 /* When not checking, ICEs are converted to fatal errors when an
1517 error has already occurred. This is counteracted by
1520 && (diagnostic_kind_count (context
, DK_ERROR
) > 0
1521 || diagnostic_kind_count (context
, DK_SORRY
) > 0)
1522 && !context
->abort_on_error
)
1525 = expand_location (diagnostic_location (diagnostic
));
1526 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1528 exit (ICE_EXIT_CODE
);
1530 if (context
->internal_error
)
1531 (*context
->internal_error
) (context
,
1532 diagnostic
->message
.format_spec
,
1533 diagnostic
->message
.args_ptr
);
1535 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1536 ++diagnostic_kind_count (context
, DK_WERROR
);
1538 ++diagnostic_kind_count (context
, diagnostic
->kind
);
1540 /* Is this the initial diagnostic within the stack of groups? */
1541 if (context
->diagnostic_group_emission_count
== 0)
1543 if (context
->begin_group_cb
)
1544 context
->begin_group_cb (context
);
1546 context
->diagnostic_group_emission_count
++;
1548 pp_format (context
->printer
, &diagnostic
->message
);
1549 (*diagnostic_starter (context
)) (context
, diagnostic
);
1550 pp_output_formatted_text (context
->printer
);
1551 if (context
->show_cwe
)
1552 print_any_cwe (context
, diagnostic
);
1553 if (context
->show_rules
)
1554 print_any_rules (context
, diagnostic
);
1555 if (context
->show_option_requested
)
1556 print_option_information (context
, diagnostic
, orig_diag_kind
);
1557 (*diagnostic_finalizer (context
)) (context
, diagnostic
, orig_diag_kind
);
1558 switch (context
->extra_output_kind
)
1562 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1563 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1564 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1566 pp_flush (context
->printer
);
1568 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1569 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1570 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1572 pp_flush (context
->printer
);
1575 diagnostic_action_after_output (context
, diagnostic
->kind
);
1576 diagnostic
->x_data
= NULL
;
1578 if (context
->edit_context_ptr
)
1579 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1580 context
->edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1584 diagnostic_show_any_path (context
, diagnostic
);
1589 /* Get the number of digits in the decimal representation of VALUE. */
1592 num_digits (int value
)
1594 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1595 using floating point. */
1596 gcc_assert (value
>= 0);
1610 /* Given a partial pathname as input, return another pathname that
1611 shares no directory elements with the pathname of __FILE__. This
1612 is used by fancy_abort() to print `internal compiler error in expr.cc'
1613 instead of `internal compiler error in ../../GCC/gcc/expr.cc'. */
1616 trim_filename (const char *name
)
1618 static const char this_file
[] = __FILE__
;
1619 const char *p
= name
, *q
= this_file
;
1621 /* First skip any "../" in each filename. This allows us to give a proper
1622 reference to a file in a subdirectory. */
1623 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1626 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1629 /* Now skip any parts the two filenames have in common. */
1630 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1633 /* Now go backwards until the previous directory separator. */
1634 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1640 /* Standard error reporting routines in increasing order of severity.
1641 All of these take arguments like printf. */
1643 /* Text to be emitted verbatim to the error message stream; this
1644 produces no prefix and disables line-wrapping. Use rarely. */
1646 verbatim (const char *gmsgid
, ...)
1651 va_start (ap
, gmsgid
);
1652 text
.err_no
= errno
;
1653 text
.args_ptr
= &ap
;
1654 text
.format_spec
= _(gmsgid
);
1656 pp_format_verbatim (global_dc
->printer
, &text
);
1657 pp_newline_and_flush (global_dc
->printer
);
1661 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1663 diagnostic_append_note (diagnostic_context
*context
,
1664 location_t location
,
1665 const char * gmsgid
, ...)
1667 diagnostic_info diagnostic
;
1669 rich_location
richloc (line_table
, location
);
1671 va_start (ap
, gmsgid
);
1672 diagnostic_set_info (&diagnostic
, gmsgid
, &ap
, &richloc
, DK_NOTE
);
1673 if (context
->inhibit_notes_p
)
1678 char *saved_prefix
= pp_take_prefix (context
->printer
);
1679 pp_set_prefix (context
->printer
,
1680 diagnostic_build_prefix (context
, &diagnostic
));
1681 pp_format (context
->printer
, &diagnostic
.message
);
1682 pp_output_formatted_text (context
->printer
);
1683 pp_destroy_prefix (context
->printer
);
1684 pp_set_prefix (context
->printer
, saved_prefix
);
1685 pp_newline (context
->printer
);
1686 diagnostic_show_locus (context
, &richloc
, DK_NOTE
);
1690 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1691 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1692 and internal_error_no_backtrace, as documented and defined below. */
1694 diagnostic_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1695 int opt
, const char *gmsgid
,
1696 va_list *ap
, diagnostic_t kind
)
1698 diagnostic_info diagnostic
;
1699 if (kind
== DK_PERMERROR
)
1701 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
,
1702 permissive_error_kind (global_dc
));
1703 diagnostic
.option_index
= permissive_error_option (global_dc
);
1707 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1708 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1709 diagnostic
.option_index
= opt
;
1711 diagnostic
.metadata
= metadata
;
1712 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1715 /* Implement inform_n, warning_n, and error_n, as documented and
1718 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1719 int opt
, unsigned HOST_WIDE_INT n
,
1720 const char *singular_gmsgid
,
1721 const char *plural_gmsgid
,
1722 va_list *ap
, diagnostic_t kind
)
1724 diagnostic_info diagnostic
;
1727 if (sizeof n
<= sizeof gtn
)
1730 /* Use the largest number ngettext can handle, otherwise
1731 preserve the six least significant decimal digits for
1732 languages where the plural form depends on them. */
1733 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1735 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1736 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1737 if (kind
== DK_WARNING
)
1738 diagnostic
.option_index
= opt
;
1739 diagnostic
.metadata
= metadata
;
1740 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1743 /* Wrapper around diagnostic_impl taking a variable argument list. */
1746 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1747 const char *gmsgid
, ...)
1749 auto_diagnostic_group d
;
1751 va_start (ap
, gmsgid
);
1752 rich_location
richloc (line_table
, location
);
1753 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1758 /* As above, but for rich_location *. */
1761 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1762 const char *gmsgid
, ...)
1764 auto_diagnostic_group d
;
1766 va_start (ap
, gmsgid
);
1767 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1772 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1775 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1776 const char *gmsgid
, va_list *ap
)
1778 rich_location
richloc (line_table
, location
);
1779 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1782 /* An informative note at LOCATION. Use this for additional details on an error
1785 inform (location_t location
, const char *gmsgid
, ...)
1787 auto_diagnostic_group d
;
1789 va_start (ap
, gmsgid
);
1790 rich_location
richloc (line_table
, location
);
1791 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1795 /* Same as "inform" above, but at RICHLOC. */
1797 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1799 gcc_assert (richloc
);
1801 auto_diagnostic_group d
;
1803 va_start (ap
, gmsgid
);
1804 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1808 /* An informative note at LOCATION. Use this for additional details on an
1811 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1812 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1815 va_start (ap
, plural_gmsgid
);
1816 auto_diagnostic_group d
;
1817 rich_location
richloc (line_table
, location
);
1818 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1823 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1824 to the relevant language specification but is likely to be buggy anyway.
1825 Returns true if the warning was printed, false if it was inhibited. */
1827 warning (int opt
, const char *gmsgid
, ...)
1829 auto_diagnostic_group d
;
1831 va_start (ap
, gmsgid
);
1832 rich_location
richloc (line_table
, input_location
);
1833 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1838 /* A warning at LOCATION. Use this for code which is correct according to the
1839 relevant language specification but is likely to be buggy anyway.
1840 Returns true if the warning was printed, false if it was inhibited. */
1843 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1845 auto_diagnostic_group d
;
1847 va_start (ap
, gmsgid
);
1848 rich_location
richloc (line_table
, location
);
1849 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1854 /* Same as "warning at" above, but using RICHLOC. */
1857 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1859 gcc_assert (richloc
);
1861 auto_diagnostic_group d
;
1863 va_start (ap
, gmsgid
);
1864 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1869 /* Same as "warning at" above, but using METADATA. */
1872 warning_meta (rich_location
*richloc
,
1873 const diagnostic_metadata
&metadata
,
1874 int opt
, const char *gmsgid
, ...)
1876 gcc_assert (richloc
);
1878 auto_diagnostic_group d
;
1880 va_start (ap
, gmsgid
);
1882 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1888 /* Same as warning_n plural variant below, but using RICHLOC. */
1891 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1892 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1894 gcc_assert (richloc
);
1896 auto_diagnostic_group d
;
1898 va_start (ap
, plural_gmsgid
);
1899 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1900 singular_gmsgid
, plural_gmsgid
,
1906 /* A warning at LOCATION. Use this for code which is correct according to the
1907 relevant language specification but is likely to be buggy anyway.
1908 Returns true if the warning was printed, false if it was inhibited. */
1911 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1912 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1914 auto_diagnostic_group d
;
1916 va_start (ap
, plural_gmsgid
);
1917 rich_location
richloc (line_table
, location
);
1918 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1919 singular_gmsgid
, plural_gmsgid
,
1925 /* A "pedantic" warning at LOCATION: issues a warning unless
1926 -pedantic-errors was given on the command line, in which case it
1927 issues an error. Use this for diagnostics required by the relevant
1928 language standard, if you have chosen not to make them errors.
1930 Note that these diagnostics are issued independent of the setting
1931 of the -Wpedantic command-line switch. To get a warning enabled
1932 only with that switch, use either "if (pedantic) pedwarn
1933 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1934 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1936 Returns true if the warning was printed, false if it was inhibited. */
1939 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
1941 auto_diagnostic_group d
;
1943 va_start (ap
, gmsgid
);
1944 rich_location
richloc (line_table
, location
);
1945 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1950 /* Same as pedwarn above, but using RICHLOC. */
1953 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1955 gcc_assert (richloc
);
1957 auto_diagnostic_group d
;
1959 va_start (ap
, gmsgid
);
1960 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1965 /* A "permissive" error at LOCATION: issues an error unless
1966 -fpermissive was given on the command line, in which case it issues
1967 a warning. Use this for things that really should be errors but we
1968 want to support legacy code.
1970 Returns true if the warning was printed, false if it was inhibited. */
1973 permerror (location_t location
, const char *gmsgid
, ...)
1975 auto_diagnostic_group d
;
1977 va_start (ap
, gmsgid
);
1978 rich_location
richloc (line_table
, location
);
1979 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
1984 /* Same as "permerror" above, but at RICHLOC. */
1987 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
1989 gcc_assert (richloc
);
1991 auto_diagnostic_group d
;
1993 va_start (ap
, gmsgid
);
1994 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
1999 /* A hard error: the code is definitely ill-formed, and an object file
2000 will not be produced. */
2002 error (const char *gmsgid
, ...)
2004 auto_diagnostic_group d
;
2006 va_start (ap
, gmsgid
);
2007 rich_location
richloc (line_table
, input_location
);
2008 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2012 /* A hard error: the code is definitely ill-formed, and an object file
2013 will not be produced. */
2015 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
2016 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
2018 auto_diagnostic_group d
;
2020 va_start (ap
, plural_gmsgid
);
2021 rich_location
richloc (line_table
, location
);
2022 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
2027 /* Same as above, but use location LOC instead of input_location. */
2029 error_at (location_t loc
, const char *gmsgid
, ...)
2031 auto_diagnostic_group d
;
2033 va_start (ap
, gmsgid
);
2034 rich_location
richloc (line_table
, loc
);
2035 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2039 /* Same as above, but use RICH_LOC. */
2042 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
2044 gcc_assert (richloc
);
2046 auto_diagnostic_group d
;
2048 va_start (ap
, gmsgid
);
2049 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
2053 /* "Sorry, not implemented." Use for a language feature which is
2054 required by the relevant specification but not implemented by GCC.
2055 An object file will not be produced. */
2057 sorry (const char *gmsgid
, ...)
2059 auto_diagnostic_group d
;
2061 va_start (ap
, gmsgid
);
2062 rich_location
richloc (line_table
, input_location
);
2063 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2067 /* Same as above, but use location LOC instead of input_location. */
2069 sorry_at (location_t loc
, const char *gmsgid
, ...)
2071 auto_diagnostic_group d
;
2073 va_start (ap
, gmsgid
);
2074 rich_location
richloc (line_table
, loc
);
2075 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
2079 /* Return true if an error or a "sorry" has been seen. Various
2080 processing is disabled after errors. */
2084 return errorcount
|| sorrycount
;
2087 /* An error which is severe enough that we make no attempt to
2088 continue. Do not use this for internal consistency checks; that's
2089 internal_error. Use of this function should be rare. */
2091 fatal_error (location_t loc
, const char *gmsgid
, ...)
2093 auto_diagnostic_group d
;
2095 va_start (ap
, gmsgid
);
2096 rich_location
richloc (line_table
, loc
);
2097 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
2103 /* An internal consistency check has failed. We make no attempt to
2106 internal_error (const char *gmsgid
, ...)
2108 auto_diagnostic_group d
;
2110 va_start (ap
, gmsgid
);
2111 rich_location
richloc (line_table
, input_location
);
2112 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
2118 /* Like internal_error, but no backtrace will be printed. Used when
2119 the internal error does not happen at the current location, but happened
2122 internal_error_no_backtrace (const char *gmsgid
, ...)
2124 auto_diagnostic_group d
;
2126 va_start (ap
, gmsgid
);
2127 rich_location
richloc (line_table
, input_location
);
2128 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
2134 /* Special case error functions. Most are implemented in terms of the
2135 above, or should be. */
2137 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
2138 runs its second argument through gettext. */
2140 fnotice (FILE *file
, const char *cmsgid
, ...)
2144 va_start (ap
, cmsgid
);
2145 vfprintf (file
, _(cmsgid
), ap
);
2149 /* Inform the user that an error occurred while trying to report some
2150 other error. This indicates catastrophic internal inconsistencies,
2151 so give up now. But do try to flush out the previous error.
2152 This mustn't use internal_error, that will cause infinite recursion. */
2155 error_recursion (diagnostic_context
*context
)
2157 if (context
->lock
< 3)
2158 pp_newline_and_flush (context
->printer
);
2161 "internal compiler error: error reporting routines re-entered.\n");
2163 /* Call diagnostic_action_after_output to get the "please submit a bug
2165 diagnostic_action_after_output (context
, DK_ICE
);
2167 /* Do not use gcc_unreachable here; that goes through internal_error
2168 and therefore would cause infinite recursion. */
2172 /* Report an internal compiler error in a friendly manner. This is
2173 the function that gets called upon use of abort() in the source
2174 code generally, thanks to a special macro. */
2177 fancy_abort (const char *file
, int line
, const char *function
)
2179 /* If fancy_abort is called before the diagnostic subsystem is initialized,
2180 internal_error will crash internally in a way that prevents a
2181 useful message reaching the user.
2182 This can happen with libgccjit in the case of gcc_assert failures
2183 that occur outside of the libgccjit mutex that guards the rest of
2184 gcc's state, including global_dc (when global_dc may not be
2185 initialized yet, or might be in use by another thread).
2186 Handle such cases as gracefully as possible by falling back to a
2187 minimal abort handler that only relies on i18n. */
2188 if (global_dc
->printer
== NULL
)
2190 /* Print the error message. */
2191 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
2192 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
2193 fputc ('\n', stderr
);
2195 /* Attempt to print a backtrace. */
2196 struct backtrace_state
*state
2197 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
2200 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
2203 /* We can't call warn_if_plugins or emergency_dump_function as these
2204 rely on GCC state that might not be initialized, or might be in
2205 use by another thread. */
2207 /* Abort the process. */
2211 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2214 /* class auto_diagnostic_group. */
2216 /* Constructor: "push" this group into global_dc. */
2218 auto_diagnostic_group::auto_diagnostic_group ()
2220 global_dc
->diagnostic_group_nesting_depth
++;
2223 /* Destructor: "pop" this group from global_dc. */
2225 auto_diagnostic_group::~auto_diagnostic_group ()
2227 if (--global_dc
->diagnostic_group_nesting_depth
== 0)
2229 /* Handle the case where we've popped the final diagnostic group.
2230 If any diagnostics were emitted, give the context a chance
2232 if (global_dc
->diagnostic_group_emission_count
> 0)
2234 if (global_dc
->end_group_cb
)
2235 global_dc
->end_group_cb (global_dc
);
2237 global_dc
->diagnostic_group_emission_count
= 0;
2241 /* Set the output format for CONTEXT to FORMAT, using BASE_FILE_NAME for
2242 file-based output formats. */
2245 diagnostic_output_format_init (diagnostic_context
*context
,
2246 const char *base_file_name
,
2247 enum diagnostics_output_format format
)
2253 case DIAGNOSTICS_OUTPUT_FORMAT_TEXT
:
2254 /* The default; do nothing. */
2257 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_STDERR
:
2258 diagnostic_output_format_init_json_stderr (context
);
2261 case DIAGNOSTICS_OUTPUT_FORMAT_JSON_FILE
:
2262 diagnostic_output_format_init_json_file (context
, base_file_name
);
2265 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_STDERR
:
2266 diagnostic_output_format_init_sarif_stderr (context
);
2269 case DIAGNOSTICS_OUTPUT_FORMAT_SARIF_FILE
:
2270 diagnostic_output_format_init_sarif_file (context
, base_file_name
);
2275 /* Implementation of diagnostic_path::num_events vfunc for
2276 simple_diagnostic_path: simply get the number of events in the vec. */
2279 simple_diagnostic_path::num_events () const
2281 return m_events
.length ();
2284 /* Implementation of diagnostic_path::get_event vfunc for
2285 simple_diagnostic_path: simply return the event in the vec. */
2287 const diagnostic_event
&
2288 simple_diagnostic_path::get_event (int idx
) const
2290 return *m_events
[idx
];
2293 /* Add an event to this path at LOC within function FNDECL at
2296 Use m_context's printer to format FMT, as the text of the new
2299 Return the id of the new event. */
2301 diagnostic_event_id_t
2302 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2303 const char *fmt
, ...)
2305 pretty_printer
*pp
= m_event_pp
;
2306 pp_clear_output_area (pp
);
2309 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2315 ti
.format_spec
= _(fmt
);
2319 ti
.m_richloc
= &rich_loc
;
2321 pp_format (pp
, &ti
);
2322 pp_output_formatted_text (pp
);
2326 simple_diagnostic_event
*new_event
2327 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2328 m_events
.safe_push (new_event
);
2330 pp_clear_output_area (pp
);
2332 return diagnostic_event_id_t (m_events
.length () - 1);
2335 /* struct simple_diagnostic_event. */
2337 /* simple_diagnostic_event's ctor. */
2339 simple_diagnostic_event::simple_diagnostic_event (location_t loc
,
2343 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
))
2347 /* simple_diagnostic_event's dtor. */
2349 simple_diagnostic_event::~simple_diagnostic_event ()
2354 /* Print PATH by emitting a dummy "note" associated with it. */
2357 void debug (diagnostic_path
*path
)
2359 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2360 richloc
.set_path (path
);
2361 inform (&richloc
, "debug path");
2364 /* Really call the system 'abort'. This has to go right at the end of
2365 this file, so that there are no functions after it that call abort
2366 and get the system abort instead of our macro. */
2376 namespace selftest
{
2378 /* Helper function for test_print_escaped_string. */
2381 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2385 print_escaped_string (&pp
, input
);
2386 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2389 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2390 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2392 /* Tests of print_escaped_string. */
2395 test_print_escaped_string ()
2398 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2400 /* Non-empty string. */
2401 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2403 /* Various things that need to be escaped: */
2405 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2408 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2411 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2414 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2417 /* Non-printable characters: BEL: '\a': 0x07 */
2418 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2420 /* Non-printable characters: vertical tab: '\v': 0x0b */
2421 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2425 /* Tests of print_parseable_fixits. */
2427 /* Verify that print_parseable_fixits emits the empty string if there
2431 test_print_parseable_fixits_none ()
2434 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2436 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2437 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2440 /* Verify that print_parseable_fixits does the right thing if there
2441 is an insertion fixit hint. */
2444 test_print_parseable_fixits_insert ()
2447 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2449 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2450 linemap_line_start (line_table
, 5, 100);
2451 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2452 location_t where
= linemap_position_for_column (line_table
, 10);
2453 richloc
.add_fixit_insert_before (where
, "added content");
2455 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2456 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2457 pp_formatted_text (&pp
));
2460 /* Verify that print_parseable_fixits does the right thing if there
2461 is an removal fixit hint. */
2464 test_print_parseable_fixits_remove ()
2467 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2469 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2470 linemap_line_start (line_table
, 5, 100);
2471 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2473 where
.m_start
= linemap_position_for_column (line_table
, 10);
2474 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2475 richloc
.add_fixit_remove (where
);
2477 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2478 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2479 pp_formatted_text (&pp
));
2482 /* Verify that print_parseable_fixits does the right thing if there
2483 is an replacement fixit hint. */
2486 test_print_parseable_fixits_replace ()
2489 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2491 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2492 linemap_line_start (line_table
, 5, 100);
2493 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2495 where
.m_start
= linemap_position_for_column (line_table
, 10);
2496 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2497 richloc
.add_fixit_replace (where
, "replacement");
2499 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2500 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2501 pp_formatted_text (&pp
));
2504 /* Verify that print_parseable_fixits correctly handles
2505 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2508 test_print_parseable_fixits_bytes_vs_display_columns ()
2510 line_table_test ltt
;
2511 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2513 /* 1-based byte offsets: 12345677778888999900001234567. */
2514 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2515 /* 1-based display cols: 123456[......7-8.....]9012345. */
2516 const int tabstop
= 8;
2518 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2519 const char *const fname
= tmp
.get_filename ();
2521 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2522 linemap_line_start (line_table
, 1, 100);
2523 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2525 where
.m_start
= linemap_position_for_column (line_table
, 12);
2526 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2527 richloc
.add_fixit_replace (where
, "color");
2530 pretty_printer tmp_pp
;
2531 print_escaped_string (&tmp_pp
, fname
);
2532 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2534 const int buf_len
= strlen (escaped_fname
) + 100;
2535 char *const expected
= XNEWVEC (char, buf_len
);
2539 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2541 snprintf (expected
, buf_len
,
2542 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2543 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2547 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2549 snprintf (expected
, buf_len
,
2550 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2551 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2554 XDELETEVEC (expected
);
2555 free (escaped_fname
);
2559 diagnostic_get_location_text (..., SHOW_COLUMN)
2560 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2561 colorization disabled. */
2564 assert_location_text (const char *expected_loc_text
,
2565 const char *filename
, int line
, int column
,
2568 enum diagnostics_column_unit column_unit
2569 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2571 test_diagnostic_context dc
;
2572 dc
.show_column
= show_column
;
2573 dc
.column_unit
= column_unit
;
2574 dc
.column_origin
= origin
;
2576 expanded_location xloc
;
2577 xloc
.file
= filename
;
2579 xloc
.column
= column
;
2583 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2584 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2585 free (actual_loc_text
);
2588 /* Verify that diagnostic_get_location_text works as expected. */
2591 test_diagnostic_get_location_text ()
2593 const char *old_progname
= progname
;
2594 progname
= "PROGNAME";
2595 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2596 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2597 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2598 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2599 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2600 for (int origin
= 0; origin
!= 2; ++origin
)
2601 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2602 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2603 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2604 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2606 maybe_line_and_column (INT_MAX
, INT_MAX
);
2607 maybe_line_and_column (INT_MIN
, INT_MIN
);
2610 /* In order to test display columns vs byte columns, we need to create a
2611 file for location_get_source_line() to read. */
2613 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2614 const int line_bytes
= strlen (content
) - 1;
2615 const int def_tabstop
= 8;
2616 const cpp_char_column_policy
policy (def_tabstop
, cpp_wcwidth
);
2617 const int display_width
= cpp_display_width (content
, line_bytes
, policy
);
2618 ASSERT_EQ (line_bytes
- 2, display_width
);
2619 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2620 const char *const fname
= tmp
.get_filename ();
2621 const int buf_len
= strlen (fname
) + 16;
2622 char *const expected
= XNEWVEC (char, buf_len
);
2624 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2625 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2626 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2628 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2629 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2630 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2632 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2633 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2634 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2636 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2637 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2638 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2640 XDELETEVEC (expected
);
2644 progname
= old_progname
;
2647 /* Selftest for num_digits. */
2652 ASSERT_EQ (1, num_digits (0));
2653 ASSERT_EQ (1, num_digits (9));
2654 ASSERT_EQ (2, num_digits (10));
2655 ASSERT_EQ (2, num_digits (99));
2656 ASSERT_EQ (3, num_digits (100));
2657 ASSERT_EQ (3, num_digits (999));
2658 ASSERT_EQ (4, num_digits (1000));
2659 ASSERT_EQ (4, num_digits (9999));
2660 ASSERT_EQ (5, num_digits (10000));
2661 ASSERT_EQ (5, num_digits (99999));
2662 ASSERT_EQ (6, num_digits (100000));
2663 ASSERT_EQ (6, num_digits (999999));
2664 ASSERT_EQ (7, num_digits (1000000));
2665 ASSERT_EQ (7, num_digits (9999999));
2666 ASSERT_EQ (8, num_digits (10000000));
2667 ASSERT_EQ (8, num_digits (99999999));
2670 /* Run all of the selftests within this file. */
2673 c_diagnostic_cc_tests ()
2675 test_print_escaped_string ();
2676 test_print_parseable_fixits_none ();
2677 test_print_parseable_fixits_insert ();
2678 test_print_parseable_fixits_remove ();
2679 test_print_parseable_fixits_replace ();
2680 test_print_parseable_fixits_bytes_vs_display_columns ();
2681 test_diagnostic_get_location_text ();
2686 } // namespace selftest
2688 #endif /* #if CHECKING_P */
2691 # pragma GCC diagnostic pop