1 /* Language-independent diagnostic subroutines for the GNU Compiler Collection
2 Copyright (C) 1999-2021 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 "edit-context.h"
39 #include "selftest-diagnostic.h"
47 #ifdef GWINSZ_IN_SYS_IOCTL
48 # include <sys/ioctl.h>
51 /* Disable warnings about quoting issues in the pp_xxx calls below
52 that (intentionally) don't follow GCC diagnostic conventions. */
54 # pragma GCC diagnostic push
55 # pragma GCC diagnostic ignored "-Wformat-diag"
58 #define pedantic_warning_kind(DC) \
59 ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
60 #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
61 #define permissive_error_option(DC) ((DC)->opt_permissive)
64 static bool diagnostic_impl (rich_location
*, const diagnostic_metadata
*,
66 va_list *, diagnostic_t
) ATTRIBUTE_GCC_DIAG(4,0);
67 static bool diagnostic_n_impl (rich_location
*, const diagnostic_metadata
*,
68 int, unsigned HOST_WIDE_INT
,
69 const char *, const char *, va_list *,
70 diagnostic_t
) ATTRIBUTE_GCC_DIAG(6,0);
72 static void error_recursion (diagnostic_context
*) ATTRIBUTE_NORETURN
;
73 static void real_abort (void) ATTRIBUTE_NORETURN
;
75 /* Name of program invoked, sans directories. */
79 /* A diagnostic_context surrogate for stderr. */
80 static diagnostic_context global_diagnostic_context
;
81 diagnostic_context
*global_dc
= &global_diagnostic_context
;
83 /* Return a malloc'd string containing MSG formatted a la printf. The
84 caller is responsible for freeing the memory. */
86 build_message_string (const char *msg
, ...)
92 str
= xvasprintf (msg
, ap
);
98 /* Same as diagnostic_build_prefix, but only the source FILE is given. */
100 file_name_as_prefix (diagnostic_context
*context
, const char *f
)
103 = colorize_start (pp_show_color (context
->printer
), "locus");
104 const char *locus_ce
= colorize_stop (pp_show_color (context
->printer
));
105 return build_message_string ("%s%s:%s ", locus_cs
, f
, locus_ce
);
110 /* Return the value of the getenv("COLUMNS") as an integer. If the
111 value is not set to a positive integer, use ioctl to get the
112 terminal width. If it fails, return INT_MAX. */
114 get_terminal_width (void)
116 const char * s
= getenv ("COLUMNS");
126 if (ioctl (0, TIOCGWINSZ
, &w
) == 0 && w
.ws_col
> 0)
133 /* Set caret_max_width to value. */
135 diagnostic_set_caret_max_width (diagnostic_context
*context
, int value
)
137 /* One minus to account for the leading empty space. */
138 value
= value
? value
- 1
139 : (isatty (fileno (pp_buffer (context
->printer
)->stream
))
140 ? get_terminal_width () - 1: INT_MAX
);
145 context
->caret_max_width
= value
;
148 /* Default implementation of final_cb. */
151 default_diagnostic_final_cb (diagnostic_context
*context
)
153 /* Some of the errors may actually have been warnings. */
154 if (diagnostic_kind_count (context
, DK_WERROR
))
156 /* -Werror was given. */
157 if (context
->warning_as_error_requested
)
158 pp_verbatim (context
->printer
,
159 _("%s: all warnings being treated as errors"),
161 /* At least one -Werror= was given. */
163 pp_verbatim (context
->printer
,
164 _("%s: some warnings being treated as errors"),
166 pp_newline_and_flush (context
->printer
);
170 /* Initialize the diagnostic message outputting machinery. */
172 diagnostic_initialize (diagnostic_context
*context
, int n_opts
)
176 /* Allocate a basic pretty-printer. Clients will replace this a
177 much more elaborated pretty-printer if they wish. */
178 context
->printer
= XNEW (pretty_printer
);
179 new (context
->printer
) pretty_printer ();
181 memset (context
->diagnostic_count
, 0, sizeof context
->diagnostic_count
);
182 context
->warning_as_error_requested
= false;
183 context
->n_opts
= n_opts
;
184 context
->classify_diagnostic
= XNEWVEC (diagnostic_t
, n_opts
);
185 for (i
= 0; i
< n_opts
; i
++)
186 context
->classify_diagnostic
[i
] = DK_UNSPECIFIED
;
187 context
->show_caret
= false;
188 diagnostic_set_caret_max_width (context
, pp_line_cutoff (context
->printer
));
189 for (i
= 0; i
< rich_location::STATICALLY_ALLOCATED_RANGES
; i
++)
190 context
->caret_chars
[i
] = '^';
191 context
->show_cwe
= false;
192 context
->path_format
= DPF_NONE
;
193 context
->show_path_depths
= false;
194 context
->show_option_requested
= false;
195 context
->abort_on_error
= false;
196 context
->show_column
= false;
197 context
->pedantic_errors
= false;
198 context
->permissive
= false;
199 context
->opt_permissive
= 0;
200 context
->fatal_errors
= false;
201 context
->dc_inhibit_warnings
= false;
202 context
->dc_warn_system_headers
= false;
203 context
->max_errors
= 0;
204 context
->internal_error
= NULL
;
205 diagnostic_starter (context
) = default_diagnostic_starter
;
206 context
->start_span
= default_diagnostic_start_span_fn
;
207 diagnostic_finalizer (context
) = default_diagnostic_finalizer
;
208 context
->option_enabled
= NULL
;
209 context
->option_state
= NULL
;
210 context
->option_name
= NULL
;
211 context
->get_option_url
= NULL
;
212 context
->last_location
= UNKNOWN_LOCATION
;
213 context
->last_module
= 0;
214 context
->x_data
= NULL
;
216 context
->inhibit_notes_p
= false;
217 context
->colorize_source_p
= false;
218 context
->show_labels_p
= false;
219 context
->show_line_numbers_p
= false;
220 context
->min_margin_width
= 0;
221 context
->show_ruler_p
= false;
222 if (const char *var
= getenv ("GCC_EXTRA_DIAGNOSTIC_OUTPUT"))
224 if (!strcmp (var
, "fixits-v1"))
225 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
;
226 else if (!strcmp (var
, "fixits-v2"))
227 context
->extra_output_kind
= EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
;
228 /* Silently ignore unrecognized values. */
230 context
->column_unit
= DIAGNOSTICS_COLUMN_UNIT_DISPLAY
;
231 context
->column_origin
= 1;
232 context
->tabstop
= 8;
233 context
->edit_context_ptr
= NULL
;
234 context
->diagnostic_group_nesting_depth
= 0;
235 context
->diagnostic_group_emission_count
= 0;
236 context
->begin_group_cb
= NULL
;
237 context
->end_group_cb
= NULL
;
238 context
->final_cb
= default_diagnostic_final_cb
;
241 /* Maybe initialize the color support. We require clients to do this
242 explicitly, since most clients don't want color. When called
243 without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
246 diagnostic_color_init (diagnostic_context
*context
, int value
/*= -1 */)
248 /* value == -1 is the default value. */
251 /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
252 -fdiagnostics-color=auto if GCC_COLORS is in the environment,
253 otherwise default to -fdiagnostics-color=never, for other
254 values default to that
255 -fdiagnostics-color={never,auto,always}. */
256 if (DIAGNOSTICS_COLOR_DEFAULT
== -1)
258 if (!getenv ("GCC_COLORS"))
260 value
= DIAGNOSTICS_COLOR_AUTO
;
263 value
= DIAGNOSTICS_COLOR_DEFAULT
;
265 pp_show_color (context
->printer
)
266 = colorize_init ((diagnostic_color_rule_t
) value
);
269 /* Initialize URL support within CONTEXT based on VALUE, handling "auto". */
272 diagnostic_urls_init (diagnostic_context
*context
, int value
/*= -1 */)
274 /* value == -1 is the default value. */
277 /* If DIAGNOSTICS_URLS_DEFAULT is -1, default to
278 -fdiagnostics-urls=auto if GCC_URLS or TERM_URLS is in the
279 environment, otherwise default to -fdiagnostics-urls=never,
280 for other values default to that
281 -fdiagnostics-urls={never,auto,always}. */
282 if (DIAGNOSTICS_URLS_DEFAULT
== -1)
284 if (!getenv ("GCC_URLS") && !getenv ("TERM_URLS"))
286 value
= DIAGNOSTICS_URL_AUTO
;
289 value
= DIAGNOSTICS_URLS_DEFAULT
;
292 context
->printer
->url_format
293 = determine_url_format ((diagnostic_url_rule_t
) value
);
296 /* Create the file_cache, if not already created, and tell it how to
297 translate files on input. */
298 void diagnostic_initialize_input_context (diagnostic_context
*context
,
299 diagnostic_input_charset_callback ccb
,
300 bool should_skip_bom
)
302 if (!context
->m_file_cache
)
303 context
->m_file_cache
= new file_cache
;
304 context
->m_file_cache
->initialize_input_context (ccb
, should_skip_bom
);
307 /* Do any cleaning up required after the last diagnostic is emitted. */
310 diagnostic_finish (diagnostic_context
*context
)
312 if (context
->final_cb
)
313 context
->final_cb (context
);
315 diagnostic_file_cache_fini ();
317 XDELETEVEC (context
->classify_diagnostic
);
318 context
->classify_diagnostic
= NULL
;
320 /* diagnostic_initialize allocates context->printer using XNEW
321 and placement-new. */
322 context
->printer
->~pretty_printer ();
323 XDELETE (context
->printer
);
324 context
->printer
= NULL
;
326 if (context
->edit_context_ptr
)
328 delete context
->edit_context_ptr
;
329 context
->edit_context_ptr
= NULL
;
333 /* Initialize DIAGNOSTIC, where the message MSG has already been
336 diagnostic_set_info_translated (diagnostic_info
*diagnostic
, const char *msg
,
337 va_list *args
, rich_location
*richloc
,
340 gcc_assert (richloc
);
341 diagnostic
->message
.err_no
= errno
;
342 diagnostic
->message
.args_ptr
= args
;
343 diagnostic
->message
.format_spec
= msg
;
344 diagnostic
->message
.m_richloc
= richloc
;
345 diagnostic
->richloc
= richloc
;
346 diagnostic
->metadata
= NULL
;
347 diagnostic
->kind
= kind
;
348 diagnostic
->option_index
= 0;
351 /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
354 diagnostic_set_info (diagnostic_info
*diagnostic
, const char *gmsgid
,
355 va_list *args
, rich_location
*richloc
,
358 gcc_assert (richloc
);
359 diagnostic_set_info_translated (diagnostic
, _(gmsgid
), args
, richloc
, kind
);
362 static const char *const diagnostic_kind_color
[] = {
363 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
364 #include "diagnostic.def"
365 #undef DEFINE_DIAGNOSTIC_KIND
369 /* Get a color name for diagnostics of type KIND
370 Result could be NULL. */
373 diagnostic_get_color_for_kind (diagnostic_t kind
)
375 return diagnostic_kind_color
[kind
];
378 /* Given an expanded_location, convert the column (which is in 1-based bytes)
379 to the requested units, without converting the origin.
380 Return -1 if the column is invalid (<= 0). */
383 convert_column_unit (enum diagnostics_column_unit column_unit
,
395 case DIAGNOSTICS_COLUMN_UNIT_DISPLAY
:
396 return location_compute_display_column (s
, tabstop
);
398 case DIAGNOSTICS_COLUMN_UNIT_BYTE
:
403 /* Given an expanded_location, convert the column (which is in 1-based bytes)
404 to the requested units and origin. Return -1 if the column is
407 diagnostic_converted_column (diagnostic_context
*context
, expanded_location s
)
410 = convert_column_unit (context
->column_unit
, context
->tabstop
, s
);
411 if (one_based_col
<= 0)
413 return one_based_col
+ (context
->column_origin
- 1);
416 /* Return a formatted line and column ':%line:%column'. Elided if
417 line == 0 or col < 0. (A column of 0 may be valid due to the
418 -fdiagnostics-column-origin option.)
419 The result is a statically allocated buffer. */
422 maybe_line_and_column (int line
, int col
)
424 static char result
[32];
429 = snprintf (result
, sizeof (result
),
430 col
>= 0 ? ":%d:%d" : ":%d", line
, col
);
431 gcc_checking_assert (l
< sizeof (result
));
438 /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
439 The caller is responsible for freeing the memory. */
442 diagnostic_get_location_text (diagnostic_context
*context
,
445 pretty_printer
*pp
= context
->printer
;
446 const char *locus_cs
= colorize_start (pp_show_color (pp
), "locus");
447 const char *locus_ce
= colorize_stop (pp_show_color (pp
));
448 const char *file
= s
.file
? s
.file
: progname
;
451 if (strcmp (file
, N_("<built-in>")))
454 if (context
->show_column
)
455 col
= diagnostic_converted_column (context
, s
);
458 const char *line_col
= maybe_line_and_column (line
, col
);
459 return build_message_string ("%s%s%s:%s", locus_cs
, file
,
463 static const char *const diagnostic_kind_text
[] = {
464 #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
465 #include "diagnostic.def"
466 #undef DEFINE_DIAGNOSTIC_KIND
470 /* Return a malloc'd string describing a location and the severity of the
471 diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
472 freeing the memory. */
474 diagnostic_build_prefix (diagnostic_context
*context
,
475 const diagnostic_info
*diagnostic
)
477 gcc_assert (diagnostic
->kind
< DK_LAST_DIAGNOSTIC_KIND
);
479 const char *text
= _(diagnostic_kind_text
[diagnostic
->kind
]);
480 const char *text_cs
= "", *text_ce
= "";
481 pretty_printer
*pp
= context
->printer
;
483 if (diagnostic_kind_color
[diagnostic
->kind
])
485 text_cs
= colorize_start (pp_show_color (pp
),
486 diagnostic_kind_color
[diagnostic
->kind
]);
487 text_ce
= colorize_stop (pp_show_color (pp
));
490 expanded_location s
= diagnostic_expand_location (diagnostic
);
491 char *location_text
= diagnostic_get_location_text (context
, s
);
493 char *result
= build_message_string ("%s %s%s%s", location_text
,
494 text_cs
, text
, text_ce
);
495 free (location_text
);
499 /* Functions at which to stop the backtrace print. It's not
500 particularly helpful to print the callers of these functions. */
502 static const char * const bt_stop
[] =
510 /* A callback function passed to the backtrace_full function. */
513 bt_callback (void *data
, uintptr_t pc
, const char *filename
, int lineno
,
514 const char *function
)
516 int *pcount
= (int *) data
;
518 /* If we don't have any useful information, don't print
520 if (filename
== NULL
&& function
== NULL
)
523 /* Skip functions in diagnostic.c. */
526 && strcmp (lbasename (filename
), "diagnostic.c") == 0)
529 /* Print up to 20 functions. We could make this a --param, but
530 since this is only for debugging just use a constant for now. */
533 /* Returning a non-zero value stops the backtrace. */
539 if (function
!= NULL
)
541 char *str
= cplus_demangle_v3 (function
,
542 (DMGL_VERBOSE
| DMGL_ANSI
543 | DMGL_GNU_V3
| DMGL_PARAMS
));
550 for (size_t i
= 0; i
< ARRAY_SIZE (bt_stop
); ++i
)
552 size_t len
= strlen (bt_stop
[i
]);
553 if (strncmp (function
, bt_stop
[i
], len
) == 0
554 && (function
[len
] == '\0' || function
[len
] == '('))
558 /* Returning a non-zero value stops the backtrace. */
564 fprintf (stderr
, "0x%lx %s\n\t%s:%d\n",
566 function
== NULL
? "???" : function
,
567 filename
== NULL
? "???" : filename
,
576 /* A callback function passed to the backtrace_full function. This is
577 called if backtrace_full has an error. */
580 bt_err_callback (void *data ATTRIBUTE_UNUSED
, const char *msg
, int errnum
)
584 /* This means that no debug info was available. Just quietly
585 skip printing backtrace info. */
588 fprintf (stderr
, "%s%s%s\n", msg
, errnum
== 0 ? "" : ": ",
589 errnum
== 0 ? "" : xstrerror (errnum
));
592 /* Check if we've met the maximum error limit, and if so fatally exit
593 with a message. CONTEXT is the context to check, and FLUSH
594 indicates whether a diagnostic_finish call is needed. */
597 diagnostic_check_max_errors (diagnostic_context
*context
, bool flush
)
599 if (!context
->max_errors
)
602 int count
= (diagnostic_kind_count (context
, DK_ERROR
)
603 + diagnostic_kind_count (context
, DK_SORRY
)
604 + diagnostic_kind_count (context
, DK_WERROR
));
606 if (count
>= context
->max_errors
)
609 "compilation terminated due to -fmax-errors=%u.\n",
610 context
->max_errors
);
612 diagnostic_finish (context
);
613 exit (FATAL_EXIT_CODE
);
617 /* Take any action which is expected to happen after the diagnostic
618 is written out. This function does not always return. */
620 diagnostic_action_after_output (diagnostic_context
*context
,
621 diagnostic_t diag_kind
)
633 if (context
->abort_on_error
)
635 if (context
->fatal_errors
)
637 fnotice (stderr
, "compilation terminated due to -Wfatal-errors.\n");
638 diagnostic_finish (context
);
639 exit (FATAL_EXIT_CODE
);
646 struct backtrace_state
*state
= NULL
;
647 if (diag_kind
== DK_ICE
)
648 state
= backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
651 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
654 if (context
->abort_on_error
)
657 fnotice (stderr
, "Please submit a full bug report,\n"
658 "with preprocessed source if appropriate.\n");
661 ("Please include the complete backtrace "
662 "with any bug report.\n"));
663 fnotice (stderr
, "See %s for instructions.\n", bug_report_url
);
665 exit (ICE_EXIT_CODE
);
669 if (context
->abort_on_error
)
671 diagnostic_finish (context
);
672 fnotice (stderr
, "compilation terminated.\n");
673 exit (FATAL_EXIT_CODE
);
680 /* True if the last module or file in which a diagnostic was reported is
681 different from the current one. */
684 last_module_changed_p (diagnostic_context
*context
,
685 const line_map_ordinary
*map
)
687 return context
->last_module
!= map
;
690 /* Remember the current module or file as being the last one in which we
691 report a diagnostic. */
694 set_last_module (diagnostic_context
*context
, const line_map_ordinary
*map
)
696 context
->last_module
= map
;
700 diagnostic_report_current_module (diagnostic_context
*context
, location_t where
)
702 const line_map_ordinary
*map
= NULL
;
704 if (pp_needs_newline (context
->printer
))
706 pp_newline (context
->printer
);
707 pp_needs_newline (context
->printer
) = false;
710 if (where
<= BUILTINS_LOCATION
)
713 linemap_resolve_location (line_table
, where
,
714 LRK_MACRO_DEFINITION_LOCATION
,
717 if (map
&& last_module_changed_p (context
, map
))
719 set_last_module (context
, map
);
720 if (! MAIN_FILE_P (map
))
722 bool first
= true, need_inc
= true, was_module
= MAP_MODULE_P (map
);
723 expanded_location s
= {};
726 where
= linemap_included_from (map
);
727 map
= linemap_included_from_linemap (line_table
, map
);
728 bool is_module
= MAP_MODULE_P (map
);
729 s
.file
= LINEMAP_FILE (map
);
730 s
.line
= SOURCE_LINE (map
, where
);
732 if (first
&& context
->show_column
)
734 s
.column
= SOURCE_COLUMN (map
, where
);
735 col
= diagnostic_converted_column (context
, s
);
737 const char *line_col
= maybe_line_and_column (s
.line
, col
);
738 static const char *const msgs
[] =
742 N_("In file included from"), /* 2 */
743 N_(" included from"),
744 N_("In module"), /* 4 */
746 N_("In module imported at"), /* 6 */
750 unsigned index
= (was_module
? 6 : is_module
? 4
751 : need_inc
? 2 : 0) + !first
;
753 pp_verbatim (context
->printer
, "%s%s %r%s%s%R",
754 first
? "" : was_module
? ", " : ",\n",
756 "locus", s
.file
, line_col
);
757 first
= false, need_inc
= was_module
, was_module
= is_module
;
759 while (! MAIN_FILE_P (map
));
760 pp_verbatim (context
->printer
, ":");
761 pp_newline (context
->printer
);
766 /* If DIAGNOSTIC has a diagnostic_path and CONTEXT supports printing paths,
770 diagnostic_show_any_path (diagnostic_context
*context
,
771 diagnostic_info
*diagnostic
)
773 const diagnostic_path
*path
= diagnostic
->richloc
->get_path ();
777 if (context
->print_path
)
778 context
->print_path (context
, path
);
781 /* Return true if the events in this path involve more than one
782 function, or false if it is purely intraprocedural. */
785 diagnostic_path::interprocedural_p () const
787 const unsigned num
= num_events ();
788 for (unsigned i
= 0; i
< num
; i
++)
790 if (get_event (i
).get_fndecl () != get_event (0).get_fndecl ())
792 if (get_event (i
).get_stack_depth () != get_event (0).get_stack_depth ())
799 default_diagnostic_starter (diagnostic_context
*context
,
800 diagnostic_info
*diagnostic
)
802 diagnostic_report_current_module (context
, diagnostic_location (diagnostic
));
803 pp_set_prefix (context
->printer
, diagnostic_build_prefix (context
,
808 default_diagnostic_start_span_fn (diagnostic_context
*context
,
809 expanded_location exploc
)
811 char *text
= diagnostic_get_location_text (context
, exploc
);
812 pp_string (context
->printer
, text
);
814 pp_newline (context
->printer
);
818 default_diagnostic_finalizer (diagnostic_context
*context
,
819 diagnostic_info
*diagnostic
,
822 char *saved_prefix
= pp_take_prefix (context
->printer
);
823 pp_set_prefix (context
->printer
, NULL
);
824 pp_newline (context
->printer
);
825 diagnostic_show_locus (context
, diagnostic
->richloc
, diagnostic
->kind
);
826 pp_set_prefix (context
->printer
, saved_prefix
);
827 pp_flush (context
->printer
);
830 /* Interface to specify diagnostic kind overrides. Returns the
831 previous setting, or DK_UNSPECIFIED if the parameters are out of
832 range. If OPTION_INDEX is zero, the new setting is for all the
835 diagnostic_classify_diagnostic (diagnostic_context
*context
,
837 diagnostic_t new_kind
,
840 diagnostic_t old_kind
;
843 || option_index
>= context
->n_opts
844 || new_kind
>= DK_LAST_DIAGNOSTIC_KIND
)
845 return DK_UNSPECIFIED
;
847 old_kind
= context
->classify_diagnostic
[option_index
];
849 /* Handle pragmas separately, since we need to keep track of *where*
851 if (where
!= UNKNOWN_LOCATION
)
855 /* Record the command-line status, so we can reset it back on DK_POP. */
856 if (old_kind
== DK_UNSPECIFIED
)
858 old_kind
= !context
->option_enabled (option_index
,
860 context
->option_state
)
861 ? DK_IGNORED
: (context
->warning_as_error_requested
862 ? DK_ERROR
: DK_WARNING
);
863 context
->classify_diagnostic
[option_index
] = old_kind
;
866 for (i
= context
->n_classification_history
- 1; i
>= 0; i
--)
867 if (context
->classification_history
[i
].option
== option_index
)
869 old_kind
= context
->classification_history
[i
].kind
;
873 i
= context
->n_classification_history
;
874 context
->classification_history
=
875 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
876 * sizeof (diagnostic_classification_change_t
));
877 context
->classification_history
[i
].location
= where
;
878 context
->classification_history
[i
].option
= option_index
;
879 context
->classification_history
[i
].kind
= new_kind
;
880 context
->n_classification_history
++;
883 context
->classify_diagnostic
[option_index
] = new_kind
;
888 /* Save all diagnostic classifications in a stack. */
890 diagnostic_push_diagnostics (diagnostic_context
*context
, location_t where ATTRIBUTE_UNUSED
)
892 context
->push_list
= (int *) xrealloc (context
->push_list
, (context
->n_push
+ 1) * sizeof (int));
893 context
->push_list
[context
->n_push
++] = context
->n_classification_history
;
896 /* Restore the topmost classification set off the stack. If the stack
897 is empty, revert to the state based on command line parameters. */
899 diagnostic_pop_diagnostics (diagnostic_context
*context
, location_t where
)
905 jump_to
= context
->push_list
[-- context
->n_push
];
909 i
= context
->n_classification_history
;
910 context
->classification_history
=
911 (diagnostic_classification_change_t
*) xrealloc (context
->classification_history
, (i
+ 1)
912 * sizeof (diagnostic_classification_change_t
));
913 context
->classification_history
[i
].location
= where
;
914 context
->classification_history
[i
].option
= jump_to
;
915 context
->classification_history
[i
].kind
= DK_POP
;
916 context
->n_classification_history
++;
919 /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
920 escaping rules for -fdiagnostics-parseable-fixits. */
923 print_escaped_string (pretty_printer
*pp
, const char *text
)
928 pp_character (pp
, '"');
929 for (const char *ch
= text
; *ch
; ch
++)
934 /* Escape backslash as two backslashes. */
935 pp_string (pp
, "\\\\");
938 /* Escape tab as "\t". */
939 pp_string (pp
, "\\t");
942 /* Escape newline as "\n". */
943 pp_string (pp
, "\\n");
946 /* Escape doublequotes as \". */
947 pp_string (pp
, "\\\"");
951 pp_character (pp
, *ch
);
953 /* Use octal for non-printable chars. */
955 unsigned char c
= (*ch
& 0xff);
956 pp_printf (pp
, "\\%o%o%o", (c
/ 64), (c
/ 8) & 007, c
& 007);
961 pp_character (pp
, '"');
964 /* Implementation of -fdiagnostics-parseable-fixits and
965 GCC_EXTRA_DIAGNOSTIC_OUTPUT.
966 Print a machine-parseable version of all fixits in RICHLOC to PP,
967 using COLUMN_UNIT to express columns.
968 Use TABSTOP when handling DIAGNOSTICS_COLUMN_UNIT_DISPLAY. */
971 print_parseable_fixits (pretty_printer
*pp
, rich_location
*richloc
,
972 enum diagnostics_column_unit column_unit
,
976 gcc_assert (richloc
);
978 char *saved_prefix
= pp_take_prefix (pp
);
979 pp_set_prefix (pp
, NULL
);
981 for (unsigned i
= 0; i
< richloc
->get_num_fixit_hints (); i
++)
983 const fixit_hint
*hint
= richloc
->get_fixit_hint (i
);
984 location_t start_loc
= hint
->get_start_loc ();
985 expanded_location start_exploc
= expand_location (start_loc
);
986 pp_string (pp
, "fix-it:");
987 print_escaped_string (pp
, start_exploc
.file
);
988 /* For compatibility with clang, print as a half-open range. */
989 location_t next_loc
= hint
->get_next_loc ();
990 expanded_location next_exploc
= expand_location (next_loc
);
992 = convert_column_unit (column_unit
, tabstop
, start_exploc
);
994 = convert_column_unit (column_unit
, tabstop
, next_exploc
);
995 pp_printf (pp
, ":{%i:%i-%i:%i}:",
996 start_exploc
.line
, start_col
,
997 next_exploc
.line
, next_col
);
998 print_escaped_string (pp
, hint
->get_string ());
1002 pp_set_prefix (pp
, saved_prefix
);
1005 /* Update the inlining info in CONTEXT for a DIAGNOSTIC. */
1008 get_any_inlining_info (diagnostic_context
*context
,
1009 diagnostic_info
*diagnostic
)
1011 auto &ilocs
= diagnostic
->m_iinfo
.m_ilocs
;
1013 if (context
->set_locations_cb
)
1014 /* Retrieve the locations into which the expression about to be
1015 diagnosed has been inlined, including those of all the callers
1016 all the way down the inlining stack. */
1017 context
->set_locations_cb (context
, diagnostic
);
1020 /* When there's no callback use just the one location provided
1021 by the caller of the diagnostic function. */
1022 location_t loc
= diagnostic_location (diagnostic
);
1023 ilocs
.safe_push (loc
);
1024 diagnostic
->m_iinfo
.m_allsyslocs
= in_system_header_at (loc
);
1028 /* Update the kind of DIAGNOSTIC based on its location(s), including
1029 any of those in its inlining stack, relative to any
1030 #pragma GCC diagnostic
1031 directives recorded within CONTEXT.
1033 Return the new kind of DIAGNOSTIC if it was updated, or DK_UNSPECIFIED
1037 update_effective_level_from_pragmas (diagnostic_context
*context
,
1038 diagnostic_info
*diagnostic
)
1040 if (diagnostic
->m_iinfo
.m_allsyslocs
&& !context
->dc_warn_system_headers
)
1042 /* Ignore the diagnostic if all the inlined locations are
1043 in system headers and -Wno-system-headers is in effect. */
1044 diagnostic
->kind
= DK_IGNORED
;
1048 if (context
->n_classification_history
<= 0)
1049 return DK_UNSPECIFIED
;
1051 /* Iterate over the locations, checking the diagnostic disposition
1052 for the diagnostic at each. If it's explicitly set as opposed
1053 to unspecified, update the disposition for this instance of
1054 the diagnostic and return it. */
1055 for (location_t loc
: diagnostic
->m_iinfo
.m_ilocs
)
1057 /* FIXME: Stupid search. Optimize later. */
1058 for (int i
= context
->n_classification_history
- 1; i
>= 0; i
--)
1060 const diagnostic_classification_change_t
&hist
1061 = context
->classification_history
[i
];
1063 location_t pragloc
= hist
.location
;
1064 if (!linemap_location_before_p (line_table
, pragloc
, loc
))
1067 if (hist
.kind
== (int) DK_POP
)
1069 /* Move on to the next region. */
1074 int option
= hist
.option
;
1075 /* The option 0 is for all the diagnostics. */
1076 if (option
== 0 || option
== diagnostic
->option_index
)
1078 diagnostic_t kind
= hist
.kind
;
1079 if (kind
!= DK_UNSPECIFIED
)
1080 diagnostic
->kind
= kind
;
1086 return DK_UNSPECIFIED
;
1089 /* Generate a URL string describing CWE. The caller is responsible for
1090 freeing the string. */
1093 get_cwe_url (int cwe
)
1095 return xasprintf ("https://cwe.mitre.org/data/definitions/%i.html", cwe
);
1098 /* If DIAGNOSTIC has a CWE identifier, print it.
1100 For example, if the diagnostic metadata associates it with CWE-119,
1101 " [CWE-119]" will be printed, suitably colorized, and with a URL of a
1102 description of the security issue. */
1105 print_any_cwe (diagnostic_context
*context
,
1106 const diagnostic_info
*diagnostic
)
1108 if (diagnostic
->metadata
== NULL
)
1111 int cwe
= diagnostic
->metadata
->get_cwe ();
1114 pretty_printer
*pp
= context
->printer
;
1115 char *saved_prefix
= pp_take_prefix (context
->printer
);
1116 pp_string (pp
, " [");
1117 pp_string (pp
, colorize_start (pp_show_color (pp
),
1118 diagnostic_kind_color
[diagnostic
->kind
]));
1119 if (pp
->url_format
!= URL_FORMAT_NONE
)
1121 char *cwe_url
= get_cwe_url (cwe
);
1122 pp_begin_url (pp
, cwe_url
);
1125 pp_printf (pp
, "CWE-%i", cwe
);
1126 pp_set_prefix (context
->printer
, saved_prefix
);
1127 if (pp
->url_format
!= URL_FORMAT_NONE
)
1129 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1130 pp_character (pp
, ']');
1134 /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
1135 printer, e.g. " [-Werror=uninitialized]".
1136 Subroutine of diagnostic_report_diagnostic. */
1139 print_option_information (diagnostic_context
*context
,
1140 const diagnostic_info
*diagnostic
,
1141 diagnostic_t orig_diag_kind
)
1145 option_text
= context
->option_name (context
, diagnostic
->option_index
,
1146 orig_diag_kind
, diagnostic
->kind
);
1150 char *option_url
= NULL
;
1151 if (context
->get_option_url
1152 && context
->printer
->url_format
!= URL_FORMAT_NONE
)
1153 option_url
= context
->get_option_url (context
,
1154 diagnostic
->option_index
);
1155 pretty_printer
*pp
= context
->printer
;
1156 pp_string (pp
, " [");
1157 pp_string (pp
, colorize_start (pp_show_color (pp
),
1158 diagnostic_kind_color
[diagnostic
->kind
]));
1160 pp_begin_url (pp
, option_url
);
1161 pp_string (pp
, option_text
);
1167 pp_string (pp
, colorize_stop (pp_show_color (pp
)));
1168 pp_character (pp
, ']');
1173 /* Returns whether a DIAGNOSTIC should be printed, and adjusts diagnostic->kind
1174 as appropriate for #pragma GCC diagnostic and -Werror=foo. */
1177 diagnostic_enabled (diagnostic_context
*context
,
1178 diagnostic_info
*diagnostic
)
1180 /* Update the inlining stack for this diagnostic. */
1181 get_any_inlining_info (context
, diagnostic
);
1183 /* Diagnostics with no option or -fpermissive are always enabled. */
1184 if (!diagnostic
->option_index
1185 || diagnostic
->option_index
== permissive_error_option (context
))
1188 /* This tests if the user provided the appropriate -Wfoo or
1190 if (! context
->option_enabled (diagnostic
->option_index
,
1192 context
->option_state
))
1195 /* This tests for #pragma diagnostic changes. */
1196 diagnostic_t diag_class
1197 = update_effective_level_from_pragmas (context
, diagnostic
);
1199 /* This tests if the user provided the appropriate -Werror=foo
1201 if (diag_class
== DK_UNSPECIFIED
1202 && (context
->classify_diagnostic
[diagnostic
->option_index
]
1205 = context
->classify_diagnostic
[diagnostic
->option_index
];
1207 /* This allows for future extensions, like temporarily disabling
1208 warnings for ranges of source code. */
1209 if (diagnostic
->kind
== DK_IGNORED
)
1215 /* Returns whether warning OPT is enabled at LOC. */
1218 warning_enabled_at (location_t loc
, int opt
)
1220 if (!diagnostic_report_warnings_p (global_dc
, loc
))
1223 rich_location
richloc (line_table
, loc
);
1224 diagnostic_info diagnostic
= {};
1225 diagnostic
.option_index
= opt
;
1226 diagnostic
.richloc
= &richloc
;
1227 diagnostic
.message
.m_richloc
= &richloc
;
1228 diagnostic
.kind
= DK_WARNING
;
1229 return diagnostic_enabled (global_dc
, &diagnostic
);
1232 /* Report a diagnostic message (an error or a warning) as specified by
1233 DC. This function is *the* subroutine in terms of which front-ends
1234 should implement their specific diagnostic handling modules. The
1235 front-end independent format specifiers are exactly those described
1236 in the documentation of output_format.
1237 Return true if a diagnostic was printed, false otherwise. */
1240 diagnostic_report_diagnostic (diagnostic_context
*context
,
1241 diagnostic_info
*diagnostic
)
1243 location_t location
= diagnostic_location (diagnostic
);
1244 diagnostic_t orig_diag_kind
= diagnostic
->kind
;
1246 /* Give preference to being able to inhibit warnings, before they
1247 get reclassified to something else. */
1248 bool report_warning_p
= true;
1249 if (diagnostic
->kind
== DK_WARNING
|| diagnostic
->kind
== DK_PEDWARN
)
1251 if (context
->dc_inhibit_warnings
)
1253 /* Remember the result of the overall system header warning setting
1254 but proceed to also check the inlining context. */
1255 report_warning_p
= diagnostic_report_warnings_p (context
, location
);
1256 if (!report_warning_p
&& diagnostic
->kind
== DK_PEDWARN
)
1260 if (diagnostic
->kind
== DK_PEDWARN
)
1262 diagnostic
->kind
= pedantic_warning_kind (context
);
1263 /* We do this to avoid giving the message for -pedantic-errors. */
1264 orig_diag_kind
= diagnostic
->kind
;
1267 if (diagnostic
->kind
== DK_NOTE
&& context
->inhibit_notes_p
)
1270 if (context
->lock
> 0)
1272 /* If we're reporting an ICE in the middle of some other error,
1273 try to flush out the previous error, then let this one
1274 through. Don't do this more than once. */
1275 if ((diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1276 && context
->lock
== 1)
1277 pp_newline_and_flush (context
->printer
);
1279 error_recursion (context
);
1282 /* If the user requested that warnings be treated as errors, so be
1283 it. Note that we do this before the next block so that
1284 individual warnings can be overridden back to warnings with
1286 if (context
->warning_as_error_requested
1287 && diagnostic
->kind
== DK_WARNING
)
1288 diagnostic
->kind
= DK_ERROR
;
1290 diagnostic
->message
.x_data
= &diagnostic
->x_data
;
1292 /* Check to see if the diagnostic is enabled at the location and
1293 not disabled by #pragma GCC diagnostic anywhere along the inlining
1295 if (!diagnostic_enabled (context
, diagnostic
))
1298 if (!report_warning_p
&& diagnostic
->m_iinfo
.m_allsyslocs
)
1299 /* Bail if the warning is not to be reported because all locations
1300 in the inlining stack (if there is one) are in system headers. */
1303 if (diagnostic
->kind
!= DK_NOTE
&& diagnostic
->kind
!= DK_ICE
)
1304 diagnostic_check_max_errors (context
);
1308 if (diagnostic
->kind
== DK_ICE
|| diagnostic
->kind
== DK_ICE_NOBT
)
1310 /* When not checking, ICEs are converted to fatal errors when an
1311 error has already occurred. This is counteracted by
1314 && (diagnostic_kind_count (context
, DK_ERROR
) > 0
1315 || diagnostic_kind_count (context
, DK_SORRY
) > 0)
1316 && !context
->abort_on_error
)
1319 = expand_location (diagnostic_location (diagnostic
));
1320 fnotice (stderr
, "%s:%d: confused by earlier errors, bailing out\n",
1322 exit (ICE_EXIT_CODE
);
1324 if (context
->internal_error
)
1325 (*context
->internal_error
) (context
,
1326 diagnostic
->message
.format_spec
,
1327 diagnostic
->message
.args_ptr
);
1329 if (diagnostic
->kind
== DK_ERROR
&& orig_diag_kind
== DK_WARNING
)
1330 ++diagnostic_kind_count (context
, DK_WERROR
);
1332 ++diagnostic_kind_count (context
, diagnostic
->kind
);
1334 /* Is this the initial diagnostic within the stack of groups? */
1335 if (context
->diagnostic_group_emission_count
== 0)
1337 if (context
->begin_group_cb
)
1338 context
->begin_group_cb (context
);
1340 context
->diagnostic_group_emission_count
++;
1342 pp_format (context
->printer
, &diagnostic
->message
);
1343 (*diagnostic_starter (context
)) (context
, diagnostic
);
1344 pp_output_formatted_text (context
->printer
);
1345 if (context
->show_cwe
)
1346 print_any_cwe (context
, diagnostic
);
1347 if (context
->show_option_requested
)
1348 print_option_information (context
, diagnostic
, orig_diag_kind
);
1349 (*diagnostic_finalizer (context
)) (context
, diagnostic
, orig_diag_kind
);
1350 switch (context
->extra_output_kind
)
1354 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v1
:
1355 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1356 DIAGNOSTICS_COLUMN_UNIT_BYTE
,
1358 pp_flush (context
->printer
);
1360 case EXTRA_DIAGNOSTIC_OUTPUT_fixits_v2
:
1361 print_parseable_fixits (context
->printer
, diagnostic
->richloc
,
1362 DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
1364 pp_flush (context
->printer
);
1367 diagnostic_action_after_output (context
, diagnostic
->kind
);
1368 diagnostic
->x_data
= NULL
;
1370 if (context
->edit_context_ptr
)
1371 if (diagnostic
->richloc
->fixits_can_be_auto_applied_p ())
1372 context
->edit_context_ptr
->add_fixits (diagnostic
->richloc
);
1376 diagnostic_show_any_path (context
, diagnostic
);
1381 /* Get the number of digits in the decimal representation of VALUE. */
1384 num_digits (int value
)
1386 /* Perhaps simpler to use log10 for this, but doing it this way avoids
1387 using floating point. */
1388 gcc_assert (value
>= 0);
1402 /* Given a partial pathname as input, return another pathname that
1403 shares no directory elements with the pathname of __FILE__. This
1404 is used by fancy_abort() to print `Internal compiler error in expr.c'
1405 instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
1408 trim_filename (const char *name
)
1410 static const char this_file
[] = __FILE__
;
1411 const char *p
= name
, *q
= this_file
;
1413 /* First skip any "../" in each filename. This allows us to give a proper
1414 reference to a file in a subdirectory. */
1415 while (p
[0] == '.' && p
[1] == '.' && IS_DIR_SEPARATOR (p
[2]))
1418 while (q
[0] == '.' && q
[1] == '.' && IS_DIR_SEPARATOR (q
[2]))
1421 /* Now skip any parts the two filenames have in common. */
1422 while (*p
== *q
&& *p
!= 0 && *q
!= 0)
1425 /* Now go backwards until the previous directory separator. */
1426 while (p
> name
&& !IS_DIR_SEPARATOR (p
[-1]))
1432 /* Standard error reporting routines in increasing order of severity.
1433 All of these take arguments like printf. */
1435 /* Text to be emitted verbatim to the error message stream; this
1436 produces no prefix and disables line-wrapping. Use rarely. */
1438 verbatim (const char *gmsgid
, ...)
1443 va_start (ap
, gmsgid
);
1444 text
.err_no
= errno
;
1445 text
.args_ptr
= &ap
;
1446 text
.format_spec
= _(gmsgid
);
1448 pp_format_verbatim (global_dc
->printer
, &text
);
1449 pp_newline_and_flush (global_dc
->printer
);
1453 /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
1455 diagnostic_append_note (diagnostic_context
*context
,
1456 location_t location
,
1457 const char * gmsgid
, ...)
1459 diagnostic_info diagnostic
;
1461 rich_location
richloc (line_table
, location
);
1463 va_start (ap
, gmsgid
);
1464 diagnostic_set_info (&diagnostic
, gmsgid
, &ap
, &richloc
, DK_NOTE
);
1465 if (context
->inhibit_notes_p
)
1470 char *saved_prefix
= pp_take_prefix (context
->printer
);
1471 pp_set_prefix (context
->printer
,
1472 diagnostic_build_prefix (context
, &diagnostic
));
1473 pp_format (context
->printer
, &diagnostic
.message
);
1474 pp_output_formatted_text (context
->printer
);
1475 pp_destroy_prefix (context
->printer
);
1476 pp_set_prefix (context
->printer
, saved_prefix
);
1477 pp_newline (context
->printer
);
1478 diagnostic_show_locus (context
, &richloc
, DK_NOTE
);
1482 /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
1483 permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
1484 and internal_error_no_backtrace, as documented and defined below. */
1486 diagnostic_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1487 int opt
, const char *gmsgid
,
1488 va_list *ap
, diagnostic_t kind
)
1490 diagnostic_info diagnostic
;
1491 if (kind
== DK_PERMERROR
)
1493 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
,
1494 permissive_error_kind (global_dc
));
1495 diagnostic
.option_index
= permissive_error_option (global_dc
);
1499 diagnostic_set_info (&diagnostic
, gmsgid
, ap
, richloc
, kind
);
1500 if (kind
== DK_WARNING
|| kind
== DK_PEDWARN
)
1501 diagnostic
.option_index
= opt
;
1503 diagnostic
.metadata
= metadata
;
1504 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1507 /* Implement inform_n, warning_n, and error_n, as documented and
1510 diagnostic_n_impl (rich_location
*richloc
, const diagnostic_metadata
*metadata
,
1511 int opt
, unsigned HOST_WIDE_INT n
,
1512 const char *singular_gmsgid
,
1513 const char *plural_gmsgid
,
1514 va_list *ap
, diagnostic_t kind
)
1516 diagnostic_info diagnostic
;
1519 if (sizeof n
<= sizeof gtn
)
1522 /* Use the largest number ngettext can handle, otherwise
1523 preserve the six least significant decimal digits for
1524 languages where the plural form depends on them. */
1525 gtn
= n
<= ULONG_MAX
? n
: n
% 1000000LU + 1000000LU;
1527 const char *text
= ngettext (singular_gmsgid
, plural_gmsgid
, gtn
);
1528 diagnostic_set_info_translated (&diagnostic
, text
, ap
, richloc
, kind
);
1529 if (kind
== DK_WARNING
)
1530 diagnostic
.option_index
= opt
;
1531 diagnostic
.metadata
= metadata
;
1532 return diagnostic_report_diagnostic (global_dc
, &diagnostic
);
1535 /* Wrapper around diagnostic_impl taking a variable argument list. */
1538 emit_diagnostic (diagnostic_t kind
, location_t location
, int opt
,
1539 const char *gmsgid
, ...)
1541 auto_diagnostic_group d
;
1543 va_start (ap
, gmsgid
);
1544 rich_location
richloc (line_table
, location
);
1545 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1550 /* As above, but for rich_location *. */
1553 emit_diagnostic (diagnostic_t kind
, rich_location
*richloc
, int opt
,
1554 const char *gmsgid
, ...)
1556 auto_diagnostic_group d
;
1558 va_start (ap
, gmsgid
);
1559 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, kind
);
1564 /* Wrapper around diagnostic_impl taking a va_list parameter. */
1567 emit_diagnostic_valist (diagnostic_t kind
, location_t location
, int opt
,
1568 const char *gmsgid
, va_list *ap
)
1570 rich_location
richloc (line_table
, location
);
1571 return diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, ap
, kind
);
1574 /* An informative note at LOCATION. Use this for additional details on an error
1577 inform (location_t location
, const char *gmsgid
, ...)
1579 auto_diagnostic_group d
;
1581 va_start (ap
, gmsgid
);
1582 rich_location
richloc (line_table
, location
);
1583 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1587 /* Same as "inform" above, but at RICHLOC. */
1589 inform (rich_location
*richloc
, const char *gmsgid
, ...)
1591 gcc_assert (richloc
);
1593 auto_diagnostic_group d
;
1595 va_start (ap
, gmsgid
);
1596 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_NOTE
);
1600 /* An informative note at LOCATION. Use this for additional details on an
1603 inform_n (location_t location
, unsigned HOST_WIDE_INT n
,
1604 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1607 va_start (ap
, plural_gmsgid
);
1608 auto_diagnostic_group d
;
1609 rich_location
richloc (line_table
, location
);
1610 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1615 /* A warning at INPUT_LOCATION. Use this for code which is correct according
1616 to the relevant language specification but is likely to be buggy anyway.
1617 Returns true if the warning was printed, false if it was inhibited. */
1619 warning (int opt
, const char *gmsgid
, ...)
1621 auto_diagnostic_group d
;
1623 va_start (ap
, gmsgid
);
1624 rich_location
richloc (line_table
, input_location
);
1625 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1630 /* A warning at LOCATION. Use this for code which is correct according to the
1631 relevant language specification but is likely to be buggy anyway.
1632 Returns true if the warning was printed, false if it was inhibited. */
1635 warning_at (location_t location
, int opt
, const char *gmsgid
, ...)
1637 auto_diagnostic_group d
;
1639 va_start (ap
, gmsgid
);
1640 rich_location
richloc (line_table
, location
);
1641 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1646 /* Same as "warning at" above, but using RICHLOC. */
1649 warning_at (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1651 gcc_assert (richloc
);
1653 auto_diagnostic_group d
;
1655 va_start (ap
, gmsgid
);
1656 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_WARNING
);
1661 /* Same as "warning at" above, but using METADATA. */
1664 warning_meta (rich_location
*richloc
,
1665 const diagnostic_metadata
&metadata
,
1666 int opt
, const char *gmsgid
, ...)
1668 gcc_assert (richloc
);
1670 auto_diagnostic_group d
;
1672 va_start (ap
, gmsgid
);
1674 = diagnostic_impl (richloc
, &metadata
, opt
, gmsgid
, &ap
,
1680 /* Same as warning_n plural variant below, but using RICHLOC. */
1683 warning_n (rich_location
*richloc
, int opt
, unsigned HOST_WIDE_INT n
,
1684 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1686 gcc_assert (richloc
);
1688 auto_diagnostic_group d
;
1690 va_start (ap
, plural_gmsgid
);
1691 bool ret
= diagnostic_n_impl (richloc
, NULL
, opt
, n
,
1692 singular_gmsgid
, plural_gmsgid
,
1698 /* A warning at LOCATION. Use this for code which is correct according to the
1699 relevant language specification but is likely to be buggy anyway.
1700 Returns true if the warning was printed, false if it was inhibited. */
1703 warning_n (location_t location
, int opt
, unsigned HOST_WIDE_INT n
,
1704 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1706 auto_diagnostic_group d
;
1708 va_start (ap
, plural_gmsgid
);
1709 rich_location
richloc (line_table
, location
);
1710 bool ret
= diagnostic_n_impl (&richloc
, NULL
, opt
, n
,
1711 singular_gmsgid
, plural_gmsgid
,
1717 /* A "pedantic" warning at LOCATION: issues a warning unless
1718 -pedantic-errors was given on the command line, in which case it
1719 issues an error. Use this for diagnostics required by the relevant
1720 language standard, if you have chosen not to make them errors.
1722 Note that these diagnostics are issued independent of the setting
1723 of the -Wpedantic command-line switch. To get a warning enabled
1724 only with that switch, use either "if (pedantic) pedwarn
1725 (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
1726 pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
1728 Returns true if the warning was printed, false if it was inhibited. */
1731 pedwarn (location_t location
, int opt
, const char *gmsgid
, ...)
1733 auto_diagnostic_group d
;
1735 va_start (ap
, gmsgid
);
1736 rich_location
richloc (line_table
, location
);
1737 bool ret
= diagnostic_impl (&richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1742 /* Same as pedwarn above, but using RICHLOC. */
1745 pedwarn (rich_location
*richloc
, int opt
, const char *gmsgid
, ...)
1747 gcc_assert (richloc
);
1749 auto_diagnostic_group d
;
1751 va_start (ap
, gmsgid
);
1752 bool ret
= diagnostic_impl (richloc
, NULL
, opt
, gmsgid
, &ap
, DK_PEDWARN
);
1757 /* A "permissive" error at LOCATION: issues an error unless
1758 -fpermissive was given on the command line, in which case it issues
1759 a warning. Use this for things that really should be errors but we
1760 want to support legacy code.
1762 Returns true if the warning was printed, false if it was inhibited. */
1765 permerror (location_t location
, const char *gmsgid
, ...)
1767 auto_diagnostic_group d
;
1769 va_start (ap
, gmsgid
);
1770 rich_location
richloc (line_table
, location
);
1771 bool ret
= diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
1776 /* Same as "permerror" above, but at RICHLOC. */
1779 permerror (rich_location
*richloc
, const char *gmsgid
, ...)
1781 gcc_assert (richloc
);
1783 auto_diagnostic_group d
;
1785 va_start (ap
, gmsgid
);
1786 bool ret
= diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_PERMERROR
);
1791 /* A hard error: the code is definitely ill-formed, and an object file
1792 will not be produced. */
1794 error (const char *gmsgid
, ...)
1796 auto_diagnostic_group d
;
1798 va_start (ap
, gmsgid
);
1799 rich_location
richloc (line_table
, input_location
);
1800 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
1804 /* A hard error: the code is definitely ill-formed, and an object file
1805 will not be produced. */
1807 error_n (location_t location
, unsigned HOST_WIDE_INT n
,
1808 const char *singular_gmsgid
, const char *plural_gmsgid
, ...)
1810 auto_diagnostic_group d
;
1812 va_start (ap
, plural_gmsgid
);
1813 rich_location
richloc (line_table
, location
);
1814 diagnostic_n_impl (&richloc
, NULL
, -1, n
, singular_gmsgid
, plural_gmsgid
,
1819 /* Same as above, but use location LOC instead of input_location. */
1821 error_at (location_t loc
, const char *gmsgid
, ...)
1823 auto_diagnostic_group d
;
1825 va_start (ap
, gmsgid
);
1826 rich_location
richloc (line_table
, loc
);
1827 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
1831 /* Same as above, but use RICH_LOC. */
1834 error_at (rich_location
*richloc
, const char *gmsgid
, ...)
1836 gcc_assert (richloc
);
1838 auto_diagnostic_group d
;
1840 va_start (ap
, gmsgid
);
1841 diagnostic_impl (richloc
, NULL
, -1, gmsgid
, &ap
, DK_ERROR
);
1845 /* "Sorry, not implemented." Use for a language feature which is
1846 required by the relevant specification but not implemented by GCC.
1847 An object file will not be produced. */
1849 sorry (const char *gmsgid
, ...)
1851 auto_diagnostic_group d
;
1853 va_start (ap
, gmsgid
);
1854 rich_location
richloc (line_table
, input_location
);
1855 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
1859 /* Same as above, but use location LOC instead of input_location. */
1861 sorry_at (location_t loc
, const char *gmsgid
, ...)
1863 auto_diagnostic_group d
;
1865 va_start (ap
, gmsgid
);
1866 rich_location
richloc (line_table
, loc
);
1867 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_SORRY
);
1871 /* Return true if an error or a "sorry" has been seen. Various
1872 processing is disabled after errors. */
1876 return errorcount
|| sorrycount
;
1879 /* An error which is severe enough that we make no attempt to
1880 continue. Do not use this for internal consistency checks; that's
1881 internal_error. Use of this function should be rare. */
1883 fatal_error (location_t loc
, const char *gmsgid
, ...)
1885 auto_diagnostic_group d
;
1887 va_start (ap
, gmsgid
);
1888 rich_location
richloc (line_table
, loc
);
1889 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_FATAL
);
1895 /* An internal consistency check has failed. We make no attempt to
1896 continue. Note that unless there is debugging value to be had from
1897 a more specific message, or some other good reason, you should use
1898 abort () instead of calling this function directly. */
1900 internal_error (const char *gmsgid
, ...)
1902 auto_diagnostic_group d
;
1904 va_start (ap
, gmsgid
);
1905 rich_location
richloc (line_table
, input_location
);
1906 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE
);
1912 /* Like internal_error, but no backtrace will be printed. Used when
1913 the internal error does not happen at the current location, but happened
1916 internal_error_no_backtrace (const char *gmsgid
, ...)
1918 auto_diagnostic_group d
;
1920 va_start (ap
, gmsgid
);
1921 rich_location
richloc (line_table
, input_location
);
1922 diagnostic_impl (&richloc
, NULL
, -1, gmsgid
, &ap
, DK_ICE_NOBT
);
1928 /* Special case error functions. Most are implemented in terms of the
1929 above, or should be. */
1931 /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
1932 runs its second argument through gettext. */
1934 fnotice (FILE *file
, const char *cmsgid
, ...)
1938 va_start (ap
, cmsgid
);
1939 vfprintf (file
, _(cmsgid
), ap
);
1943 /* Inform the user that an error occurred while trying to report some
1944 other error. This indicates catastrophic internal inconsistencies,
1945 so give up now. But do try to flush out the previous error.
1946 This mustn't use internal_error, that will cause infinite recursion. */
1949 error_recursion (diagnostic_context
*context
)
1951 if (context
->lock
< 3)
1952 pp_newline_and_flush (context
->printer
);
1955 "Internal compiler error: Error reporting routines re-entered.\n");
1957 /* Call diagnostic_action_after_output to get the "please submit a bug
1959 diagnostic_action_after_output (context
, DK_ICE
);
1961 /* Do not use gcc_unreachable here; that goes through internal_error
1962 and therefore would cause infinite recursion. */
1966 /* Report an internal compiler error in a friendly manner. This is
1967 the function that gets called upon use of abort() in the source
1968 code generally, thanks to a special macro. */
1971 fancy_abort (const char *file
, int line
, const char *function
)
1973 /* If fancy_abort is called before the diagnostic subsystem is initialized,
1974 internal_error will crash internally in a way that prevents a
1975 useful message reaching the user.
1976 This can happen with libgccjit in the case of gcc_assert failures
1977 that occur outside of the libgccjit mutex that guards the rest of
1978 gcc's state, including global_dc (when global_dc may not be
1979 initialized yet, or might be in use by another thread).
1980 Handle such cases as gracefully as possible by falling back to a
1981 minimal abort handler that only relies on i18n. */
1982 if (global_dc
->printer
== NULL
)
1984 /* Print the error message. */
1985 fnotice (stderr
, diagnostic_kind_text
[DK_ICE
]);
1986 fnotice (stderr
, "in %s, at %s:%d", function
, trim_filename (file
), line
);
1987 fputc ('\n', stderr
);
1989 /* Attempt to print a backtrace. */
1990 struct backtrace_state
*state
1991 = backtrace_create_state (NULL
, 0, bt_err_callback
, NULL
);
1994 backtrace_full (state
, 2, bt_callback
, bt_err_callback
,
1997 /* We can't call warn_if_plugins or emergency_dump_function as these
1998 rely on GCC state that might not be initialized, or might be in
1999 use by another thread. */
2001 /* Abort the process. */
2005 internal_error ("in %s, at %s:%d", function
, trim_filename (file
), line
);
2008 /* class auto_diagnostic_group. */
2010 /* Constructor: "push" this group into global_dc. */
2012 auto_diagnostic_group::auto_diagnostic_group ()
2014 global_dc
->diagnostic_group_nesting_depth
++;
2017 /* Destructor: "pop" this group from global_dc. */
2019 auto_diagnostic_group::~auto_diagnostic_group ()
2021 if (--global_dc
->diagnostic_group_nesting_depth
== 0)
2023 /* Handle the case where we've popped the final diagnostic group.
2024 If any diagnostics were emitted, give the context a chance
2026 if (global_dc
->diagnostic_group_emission_count
> 0)
2028 if (global_dc
->end_group_cb
)
2029 global_dc
->end_group_cb (global_dc
);
2031 global_dc
->diagnostic_group_emission_count
= 0;
2035 /* Implementation of diagnostic_path::num_events vfunc for
2036 simple_diagnostic_path: simply get the number of events in the vec. */
2039 simple_diagnostic_path::num_events () const
2041 return m_events
.length ();
2044 /* Implementation of diagnostic_path::get_event vfunc for
2045 simple_diagnostic_path: simply return the event in the vec. */
2047 const diagnostic_event
&
2048 simple_diagnostic_path::get_event (int idx
) const
2050 return *m_events
[idx
];
2053 /* Add an event to this path at LOC within function FNDECL at
2056 Use m_context's printer to format FMT, as the text of the new
2059 Return the id of the new event. */
2061 diagnostic_event_id_t
2062 simple_diagnostic_path::add_event (location_t loc
, tree fndecl
, int depth
,
2063 const char *fmt
, ...)
2065 pretty_printer
*pp
= m_event_pp
;
2066 pp_clear_output_area (pp
);
2069 rich_location
rich_loc (line_table
, UNKNOWN_LOCATION
);
2075 ti
.format_spec
= _(fmt
);
2079 ti
.m_richloc
= &rich_loc
;
2081 pp_format (pp
, &ti
);
2082 pp_output_formatted_text (pp
);
2086 simple_diagnostic_event
*new_event
2087 = new simple_diagnostic_event (loc
, fndecl
, depth
, pp_formatted_text (pp
));
2088 m_events
.safe_push (new_event
);
2090 pp_clear_output_area (pp
);
2092 return diagnostic_event_id_t (m_events
.length () - 1);
2095 /* struct simple_diagnostic_event. */
2097 /* simple_diagnostic_event's ctor. */
2099 simple_diagnostic_event::simple_diagnostic_event (location_t loc
,
2103 : m_loc (loc
), m_fndecl (fndecl
), m_depth (depth
), m_desc (xstrdup (desc
))
2107 /* simple_diagnostic_event's dtor. */
2109 simple_diagnostic_event::~simple_diagnostic_event ()
2114 /* Print PATH by emitting a dummy "note" associated with it. */
2117 void debug (diagnostic_path
*path
)
2119 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2120 richloc
.set_path (path
);
2121 inform (&richloc
, "debug path");
2124 /* Really call the system 'abort'. This has to go right at the end of
2125 this file, so that there are no functions after it that call abort
2126 and get the system abort instead of our macro. */
2136 namespace selftest
{
2138 /* Helper function for test_print_escaped_string. */
2141 assert_print_escaped_string (const location
&loc
, const char *expected_output
,
2145 print_escaped_string (&pp
, input
);
2146 ASSERT_STREQ_AT (loc
, expected_output
, pp_formatted_text (&pp
));
2149 #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
2150 assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
2152 /* Tests of print_escaped_string. */
2155 test_print_escaped_string ()
2158 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
2160 /* Non-empty string. */
2161 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
2163 /* Various things that need to be escaped: */
2165 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
2168 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
2171 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
2174 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
2177 /* Non-printable characters: BEL: '\a': 0x07 */
2178 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
2180 /* Non-printable characters: vertical tab: '\v': 0x0b */
2181 ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
2185 /* Tests of print_parseable_fixits. */
2187 /* Verify that print_parseable_fixits emits the empty string if there
2191 test_print_parseable_fixits_none ()
2194 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2196 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2197 ASSERT_STREQ ("", pp_formatted_text (&pp
));
2200 /* Verify that print_parseable_fixits does the right thing if there
2201 is an insertion fixit hint. */
2204 test_print_parseable_fixits_insert ()
2207 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2209 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2210 linemap_line_start (line_table
, 5, 100);
2211 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2212 location_t where
= linemap_position_for_column (line_table
, 10);
2213 richloc
.add_fixit_insert_before (where
, "added content");
2215 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2216 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
2217 pp_formatted_text (&pp
));
2220 /* Verify that print_parseable_fixits does the right thing if there
2221 is an removal fixit hint. */
2224 test_print_parseable_fixits_remove ()
2227 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2229 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2230 linemap_line_start (line_table
, 5, 100);
2231 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2233 where
.m_start
= linemap_position_for_column (line_table
, 10);
2234 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2235 richloc
.add_fixit_remove (where
);
2237 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2238 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
2239 pp_formatted_text (&pp
));
2242 /* Verify that print_parseable_fixits does the right thing if there
2243 is an replacement fixit hint. */
2246 test_print_parseable_fixits_replace ()
2249 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2251 linemap_add (line_table
, LC_ENTER
, false, "test.c", 0);
2252 linemap_line_start (line_table
, 5, 100);
2253 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2255 where
.m_start
= linemap_position_for_column (line_table
, 10);
2256 where
.m_finish
= linemap_position_for_column (line_table
, 20);
2257 richloc
.add_fixit_replace (where
, "replacement");
2259 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
, 8);
2260 ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
2261 pp_formatted_text (&pp
));
2264 /* Verify that print_parseable_fixits correctly handles
2265 DIAGNOSTICS_COLUMN_UNIT_BYTE vs DIAGNOSTICS_COLUMN_UNIT_COLUMN. */
2268 test_print_parseable_fixits_bytes_vs_display_columns ()
2270 line_table_test ltt
;
2271 rich_location
richloc (line_table
, UNKNOWN_LOCATION
);
2273 /* 1-based byte offsets: 12345677778888999900001234567. */
2274 const char *const content
= "smile \xf0\x9f\x98\x82 colour\n";
2275 /* 1-based display cols: 123456[......7-8.....]9012345. */
2276 const int tabstop
= 8;
2278 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2279 const char *const fname
= tmp
.get_filename ();
2281 linemap_add (line_table
, LC_ENTER
, false, fname
, 0);
2282 linemap_line_start (line_table
, 1, 100);
2283 linemap_add (line_table
, LC_LEAVE
, false, NULL
, 0);
2285 where
.m_start
= linemap_position_for_column (line_table
, 12);
2286 where
.m_finish
= linemap_position_for_column (line_table
, 17);
2287 richloc
.add_fixit_replace (where
, "color");
2290 pretty_printer tmp_pp
;
2291 print_escaped_string (&tmp_pp
, fname
);
2292 char *escaped_fname
= xstrdup (pp_formatted_text (&tmp_pp
));
2294 const int buf_len
= strlen (escaped_fname
) + 100;
2295 char *const expected
= XNEWVEC (char, buf_len
);
2299 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_BYTE
,
2301 snprintf (expected
, buf_len
,
2302 "fix-it:%s:{1:12-1:18}:\"color\"\n", escaped_fname
);
2303 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2307 print_parseable_fixits (&pp
, &richloc
, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
,
2309 snprintf (expected
, buf_len
,
2310 "fix-it:%s:{1:10-1:16}:\"color\"\n", escaped_fname
);
2311 ASSERT_STREQ (expected
, pp_formatted_text (&pp
));
2314 XDELETEVEC (expected
);
2315 free (escaped_fname
);
2319 diagnostic_get_location_text (..., SHOW_COLUMN)
2320 generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
2321 colorization disabled. */
2324 assert_location_text (const char *expected_loc_text
,
2325 const char *filename
, int line
, int column
,
2328 enum diagnostics_column_unit column_unit
2329 = DIAGNOSTICS_COLUMN_UNIT_BYTE
)
2331 test_diagnostic_context dc
;
2332 dc
.show_column
= show_column
;
2333 dc
.column_unit
= column_unit
;
2334 dc
.column_origin
= origin
;
2336 expanded_location xloc
;
2337 xloc
.file
= filename
;
2339 xloc
.column
= column
;
2343 char *actual_loc_text
= diagnostic_get_location_text (&dc
, xloc
);
2344 ASSERT_STREQ (expected_loc_text
, actual_loc_text
);
2345 free (actual_loc_text
);
2348 /* Verify that diagnostic_get_location_text works as expected. */
2351 test_diagnostic_get_location_text ()
2353 const char *old_progname
= progname
;
2354 progname
= "PROGNAME";
2355 assert_location_text ("PROGNAME:", NULL
, 0, 0, true);
2356 assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
2357 assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
2358 assert_location_text ("foo.c:42:9:", "foo.c", 42, 10, true, 0);
2359 assert_location_text ("foo.c:42:1010:", "foo.c", 42, 10, true, 1001);
2360 for (int origin
= 0; origin
!= 2; ++origin
)
2361 assert_location_text ("foo.c:42:", "foo.c", 42, 0, true, origin
);
2362 assert_location_text ("foo.c:", "foo.c", 0, 10, true);
2363 assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
2364 assert_location_text ("foo.c:", "foo.c", 0, 10, false);
2366 maybe_line_and_column (INT_MAX
, INT_MAX
);
2367 maybe_line_and_column (INT_MIN
, INT_MIN
);
2370 /* In order to test display columns vs byte columns, we need to create a
2371 file for location_get_source_line() to read. */
2373 const char *const content
= "smile \xf0\x9f\x98\x82\n";
2374 const int line_bytes
= strlen (content
) - 1;
2375 const int def_tabstop
= 8;
2376 const int display_width
= cpp_display_width (content
, line_bytes
,
2378 ASSERT_EQ (line_bytes
- 2, display_width
);
2379 temp_source_file
tmp (SELFTEST_LOCATION
, ".c", content
);
2380 const char *const fname
= tmp
.get_filename ();
2381 const int buf_len
= strlen (fname
) + 16;
2382 char *const expected
= XNEWVEC (char, buf_len
);
2384 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
);
2385 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2386 1, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2388 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, line_bytes
- 1);
2389 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2390 0, DIAGNOSTICS_COLUMN_UNIT_BYTE
);
2392 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
);
2393 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2394 1, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2396 snprintf (expected
, buf_len
, "%s:1:%d:", fname
, display_width
- 1);
2397 assert_location_text (expected
, fname
, 1, line_bytes
, true,
2398 0, DIAGNOSTICS_COLUMN_UNIT_DISPLAY
);
2400 XDELETEVEC (expected
);
2404 progname
= old_progname
;
2407 /* Selftest for num_digits. */
2412 ASSERT_EQ (1, num_digits (0));
2413 ASSERT_EQ (1, num_digits (9));
2414 ASSERT_EQ (2, num_digits (10));
2415 ASSERT_EQ (2, num_digits (99));
2416 ASSERT_EQ (3, num_digits (100));
2417 ASSERT_EQ (3, num_digits (999));
2418 ASSERT_EQ (4, num_digits (1000));
2419 ASSERT_EQ (4, num_digits (9999));
2420 ASSERT_EQ (5, num_digits (10000));
2421 ASSERT_EQ (5, num_digits (99999));
2422 ASSERT_EQ (6, num_digits (100000));
2423 ASSERT_EQ (6, num_digits (999999));
2424 ASSERT_EQ (7, num_digits (1000000));
2425 ASSERT_EQ (7, num_digits (9999999));
2426 ASSERT_EQ (8, num_digits (10000000));
2427 ASSERT_EQ (8, num_digits (99999999));
2430 /* Run all of the selftests within this file. */
2433 diagnostic_c_tests ()
2435 test_print_escaped_string ();
2436 test_print_parseable_fixits_none ();
2437 test_print_parseable_fixits_insert ();
2438 test_print_parseable_fixits_remove ();
2439 test_print_parseable_fixits_replace ();
2440 test_print_parseable_fixits_bytes_vs_display_columns ();
2441 test_diagnostic_get_location_text ();
2446 } // namespace selftest
2448 #endif /* #if CHECKING_P */
2451 # pragma GCC diagnostic pop