138fd1498Szrj /* Language-independent diagnostic subroutines for the GNU Compiler Collection
238fd1498Szrj Copyright (C) 1999-2018 Free Software Foundation, Inc.
338fd1498Szrj Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
438fd1498Szrj
538fd1498Szrj This file is part of GCC.
638fd1498Szrj
738fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
838fd1498Szrj the terms of the GNU General Public License as published by the Free
938fd1498Szrj Software Foundation; either version 3, or (at your option) any later
1038fd1498Szrj version.
1138fd1498Szrj
1238fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
1338fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
1438fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
1538fd1498Szrj for more details.
1638fd1498Szrj
1738fd1498Szrj You should have received a copy of the GNU General Public License
1838fd1498Szrj along with GCC; see the file COPYING3. If not see
1938fd1498Szrj <http://www.gnu.org/licenses/>. */
2038fd1498Szrj
2138fd1498Szrj
2238fd1498Szrj /* This file implements the language independent aspect of diagnostic
2338fd1498Szrj message module. */
2438fd1498Szrj
2538fd1498Szrj #include "config.h"
2638fd1498Szrj #include "system.h"
2738fd1498Szrj #include "coretypes.h"
2838fd1498Szrj #include "version.h"
2938fd1498Szrj #include "demangle.h"
3038fd1498Szrj #include "intl.h"
3138fd1498Szrj #include "backtrace.h"
3238fd1498Szrj #include "diagnostic.h"
3338fd1498Szrj #include "diagnostic-color.h"
3438fd1498Szrj #include "edit-context.h"
3538fd1498Szrj #include "selftest.h"
3638fd1498Szrj #include "selftest-diagnostic.h"
3738fd1498Szrj
3838fd1498Szrj #ifdef HAVE_TERMIOS_H
3938fd1498Szrj # include <termios.h>
4038fd1498Szrj #endif
4138fd1498Szrj
4238fd1498Szrj #ifdef GWINSZ_IN_SYS_IOCTL
4338fd1498Szrj # include <sys/ioctl.h>
4438fd1498Szrj #endif
4538fd1498Szrj
4638fd1498Szrj #define pedantic_warning_kind(DC) \
4738fd1498Szrj ((DC)->pedantic_errors ? DK_ERROR : DK_WARNING)
4838fd1498Szrj #define permissive_error_kind(DC) ((DC)->permissive ? DK_WARNING : DK_ERROR)
4938fd1498Szrj #define permissive_error_option(DC) ((DC)->opt_permissive)
5038fd1498Szrj
5138fd1498Szrj /* Prototypes. */
5238fd1498Szrj static bool diagnostic_impl (rich_location *, int, const char *,
5338fd1498Szrj va_list *, diagnostic_t) ATTRIBUTE_GCC_DIAG(3,0);
5438fd1498Szrj static bool diagnostic_n_impl (rich_location *, int, unsigned HOST_WIDE_INT,
5538fd1498Szrj const char *, const char *, va_list *,
5638fd1498Szrj diagnostic_t) ATTRIBUTE_GCC_DIAG(5,0);
5738fd1498Szrj
5838fd1498Szrj static void error_recursion (diagnostic_context *) ATTRIBUTE_NORETURN;
5938fd1498Szrj static void real_abort (void) ATTRIBUTE_NORETURN;
6038fd1498Szrj
6138fd1498Szrj /* Name of program invoked, sans directories. */
6238fd1498Szrj
6338fd1498Szrj const char *progname;
6438fd1498Szrj
6538fd1498Szrj /* A diagnostic_context surrogate for stderr. */
6638fd1498Szrj static diagnostic_context global_diagnostic_context;
6738fd1498Szrj diagnostic_context *global_dc = &global_diagnostic_context;
6838fd1498Szrj
6938fd1498Szrj /* Return a malloc'd string containing MSG formatted a la printf. The
7038fd1498Szrj caller is responsible for freeing the memory. */
7138fd1498Szrj char *
build_message_string(const char * msg,...)7238fd1498Szrj build_message_string (const char *msg, ...)
7338fd1498Szrj {
7438fd1498Szrj char *str;
7538fd1498Szrj va_list ap;
7638fd1498Szrj
7738fd1498Szrj va_start (ap, msg);
7838fd1498Szrj str = xvasprintf (msg, ap);
7938fd1498Szrj va_end (ap);
8038fd1498Szrj
8138fd1498Szrj return str;
8238fd1498Szrj }
8338fd1498Szrj
8438fd1498Szrj /* Same as diagnostic_build_prefix, but only the source FILE is given. */
8538fd1498Szrj char *
file_name_as_prefix(diagnostic_context * context,const char * f)8638fd1498Szrj file_name_as_prefix (diagnostic_context *context, const char *f)
8738fd1498Szrj {
8838fd1498Szrj const char *locus_cs
8938fd1498Szrj = colorize_start (pp_show_color (context->printer), "locus");
9038fd1498Szrj const char *locus_ce = colorize_stop (pp_show_color (context->printer));
9138fd1498Szrj return build_message_string ("%s%s:%s ", locus_cs, f, locus_ce);
9238fd1498Szrj }
9338fd1498Szrj
9438fd1498Szrj
9538fd1498Szrj
9638fd1498Szrj /* Return the value of the getenv("COLUMNS") as an integer. If the
9738fd1498Szrj value is not set to a positive integer, use ioctl to get the
9838fd1498Szrj terminal width. If it fails, return INT_MAX. */
9938fd1498Szrj int
get_terminal_width(void)10038fd1498Szrj get_terminal_width (void)
10138fd1498Szrj {
10238fd1498Szrj const char * s = getenv ("COLUMNS");
10338fd1498Szrj if (s != NULL) {
10438fd1498Szrj int n = atoi (s);
10538fd1498Szrj if (n > 0)
10638fd1498Szrj return n;
10738fd1498Szrj }
10838fd1498Szrj
10938fd1498Szrj #ifdef TIOCGWINSZ
11038fd1498Szrj struct winsize w;
11138fd1498Szrj w.ws_col = 0;
11238fd1498Szrj if (ioctl (0, TIOCGWINSZ, &w) == 0 && w.ws_col > 0)
11338fd1498Szrj return w.ws_col;
11438fd1498Szrj #endif
11538fd1498Szrj
11638fd1498Szrj return INT_MAX;
11738fd1498Szrj }
11838fd1498Szrj
11938fd1498Szrj /* Set caret_max_width to value. */
12038fd1498Szrj void
diagnostic_set_caret_max_width(diagnostic_context * context,int value)12138fd1498Szrj diagnostic_set_caret_max_width (diagnostic_context *context, int value)
12238fd1498Szrj {
12338fd1498Szrj /* One minus to account for the leading empty space. */
12438fd1498Szrj value = value ? value - 1
12538fd1498Szrj : (isatty (fileno (pp_buffer (context->printer)->stream))
12638fd1498Szrj ? get_terminal_width () - 1: INT_MAX);
12738fd1498Szrj
12838fd1498Szrj if (value <= 0)
12938fd1498Szrj value = INT_MAX;
13038fd1498Szrj
13138fd1498Szrj context->caret_max_width = value;
13238fd1498Szrj }
13338fd1498Szrj
13438fd1498Szrj /* Initialize the diagnostic message outputting machinery. */
13538fd1498Szrj void
diagnostic_initialize(diagnostic_context * context,int n_opts)13638fd1498Szrj diagnostic_initialize (diagnostic_context *context, int n_opts)
13738fd1498Szrj {
13838fd1498Szrj int i;
13938fd1498Szrj
14038fd1498Szrj /* Allocate a basic pretty-printer. Clients will replace this a
14138fd1498Szrj much more elaborated pretty-printer if they wish. */
14238fd1498Szrj context->printer = XNEW (pretty_printer);
14338fd1498Szrj new (context->printer) pretty_printer ();
14438fd1498Szrj
14538fd1498Szrj memset (context->diagnostic_count, 0, sizeof context->diagnostic_count);
14638fd1498Szrj context->warning_as_error_requested = false;
14738fd1498Szrj context->n_opts = n_opts;
14838fd1498Szrj context->classify_diagnostic = XNEWVEC (diagnostic_t, n_opts);
14938fd1498Szrj for (i = 0; i < n_opts; i++)
15038fd1498Szrj context->classify_diagnostic[i] = DK_UNSPECIFIED;
15138fd1498Szrj context->show_caret = false;
15238fd1498Szrj diagnostic_set_caret_max_width (context, pp_line_cutoff (context->printer));
15338fd1498Szrj for (i = 0; i < rich_location::STATICALLY_ALLOCATED_RANGES; i++)
15438fd1498Szrj context->caret_chars[i] = '^';
15538fd1498Szrj context->show_option_requested = false;
15638fd1498Szrj context->abort_on_error = false;
15738fd1498Szrj context->show_column = false;
15838fd1498Szrj context->pedantic_errors = false;
15938fd1498Szrj context->permissive = false;
16038fd1498Szrj context->opt_permissive = 0;
16138fd1498Szrj context->fatal_errors = false;
16238fd1498Szrj context->dc_inhibit_warnings = false;
16338fd1498Szrj context->dc_warn_system_headers = false;
16438fd1498Szrj context->max_errors = 0;
16538fd1498Szrj context->internal_error = NULL;
16638fd1498Szrj diagnostic_starter (context) = default_diagnostic_starter;
16738fd1498Szrj context->start_span = default_diagnostic_start_span_fn;
16838fd1498Szrj diagnostic_finalizer (context) = default_diagnostic_finalizer;
16938fd1498Szrj context->option_enabled = NULL;
17038fd1498Szrj context->option_state = NULL;
17138fd1498Szrj context->option_name = NULL;
17238fd1498Szrj context->last_location = UNKNOWN_LOCATION;
17338fd1498Szrj context->last_module = 0;
17438fd1498Szrj context->x_data = NULL;
17538fd1498Szrj context->lock = 0;
17638fd1498Szrj context->inhibit_notes_p = false;
17738fd1498Szrj context->colorize_source_p = false;
17838fd1498Szrj context->show_ruler_p = false;
17938fd1498Szrj context->parseable_fixits_p = false;
18038fd1498Szrj context->edit_context_ptr = NULL;
18138fd1498Szrj }
18238fd1498Szrj
18338fd1498Szrj /* Maybe initialize the color support. We require clients to do this
18438fd1498Szrj explicitly, since most clients don't want color. When called
18538fd1498Szrj without a VALUE, it initializes with DIAGNOSTICS_COLOR_DEFAULT. */
18638fd1498Szrj
18738fd1498Szrj void
diagnostic_color_init(diagnostic_context * context,int value)18838fd1498Szrj diagnostic_color_init (diagnostic_context *context, int value /*= -1 */)
18938fd1498Szrj {
19038fd1498Szrj /* value == -1 is the default value. */
19138fd1498Szrj if (value < 0)
19238fd1498Szrj {
19338fd1498Szrj /* If DIAGNOSTICS_COLOR_DEFAULT is -1, default to
19438fd1498Szrj -fdiagnostics-color=auto if GCC_COLORS is in the environment,
19538fd1498Szrj otherwise default to -fdiagnostics-color=never, for other
19638fd1498Szrj values default to that
19738fd1498Szrj -fdiagnostics-color={never,auto,always}. */
19838fd1498Szrj if (DIAGNOSTICS_COLOR_DEFAULT == -1)
19938fd1498Szrj {
20038fd1498Szrj if (!getenv ("GCC_COLORS"))
20138fd1498Szrj return;
20238fd1498Szrj value = DIAGNOSTICS_COLOR_AUTO;
20338fd1498Szrj }
20438fd1498Szrj else
20538fd1498Szrj value = DIAGNOSTICS_COLOR_DEFAULT;
20638fd1498Szrj }
20738fd1498Szrj pp_show_color (context->printer)
20838fd1498Szrj = colorize_init ((diagnostic_color_rule_t) value);
20938fd1498Szrj }
21038fd1498Szrj
21138fd1498Szrj /* Do any cleaning up required after the last diagnostic is emitted. */
21238fd1498Szrj
21338fd1498Szrj void
diagnostic_finish(diagnostic_context * context)21438fd1498Szrj diagnostic_finish (diagnostic_context *context)
21538fd1498Szrj {
21638fd1498Szrj /* Some of the errors may actually have been warnings. */
21738fd1498Szrj if (diagnostic_kind_count (context, DK_WERROR))
21838fd1498Szrj {
21938fd1498Szrj /* -Werror was given. */
22038fd1498Szrj if (context->warning_as_error_requested)
22138fd1498Szrj pp_verbatim (context->printer,
22238fd1498Szrj _("%s: all warnings being treated as errors"),
22338fd1498Szrj progname);
22438fd1498Szrj /* At least one -Werror= was given. */
22538fd1498Szrj else
22638fd1498Szrj pp_verbatim (context->printer,
22738fd1498Szrj _("%s: some warnings being treated as errors"),
22838fd1498Szrj progname);
22938fd1498Szrj pp_newline_and_flush (context->printer);
23038fd1498Szrj }
23138fd1498Szrj
23238fd1498Szrj diagnostic_file_cache_fini ();
23338fd1498Szrj
23438fd1498Szrj XDELETEVEC (context->classify_diagnostic);
23538fd1498Szrj context->classify_diagnostic = NULL;
23638fd1498Szrj
23738fd1498Szrj /* diagnostic_initialize allocates context->printer using XNEW
23838fd1498Szrj and placement-new. */
23938fd1498Szrj context->printer->~pretty_printer ();
24038fd1498Szrj XDELETE (context->printer);
24138fd1498Szrj context->printer = NULL;
24238fd1498Szrj
24338fd1498Szrj if (context->edit_context_ptr)
24438fd1498Szrj {
24538fd1498Szrj delete context->edit_context_ptr;
24638fd1498Szrj context->edit_context_ptr = NULL;
24738fd1498Szrj }
24838fd1498Szrj }
24938fd1498Szrj
25038fd1498Szrj /* Initialize DIAGNOSTIC, where the message MSG has already been
25138fd1498Szrj translated. */
25238fd1498Szrj void
diagnostic_set_info_translated(diagnostic_info * diagnostic,const char * msg,va_list * args,rich_location * richloc,diagnostic_t kind)25338fd1498Szrj diagnostic_set_info_translated (diagnostic_info *diagnostic, const char *msg,
25438fd1498Szrj va_list *args, rich_location *richloc,
25538fd1498Szrj diagnostic_t kind)
25638fd1498Szrj {
25738fd1498Szrj gcc_assert (richloc);
25838fd1498Szrj diagnostic->message.err_no = errno;
25938fd1498Szrj diagnostic->message.args_ptr = args;
26038fd1498Szrj diagnostic->message.format_spec = msg;
26138fd1498Szrj diagnostic->message.m_richloc = richloc;
26238fd1498Szrj diagnostic->richloc = richloc;
26338fd1498Szrj diagnostic->kind = kind;
26438fd1498Szrj diagnostic->option_index = 0;
26538fd1498Szrj }
26638fd1498Szrj
26738fd1498Szrj /* Initialize DIAGNOSTIC, where the message GMSGID has not yet been
26838fd1498Szrj translated. */
26938fd1498Szrj void
diagnostic_set_info(diagnostic_info * diagnostic,const char * gmsgid,va_list * args,rich_location * richloc,diagnostic_t kind)27038fd1498Szrj diagnostic_set_info (diagnostic_info *diagnostic, const char *gmsgid,
27138fd1498Szrj va_list *args, rich_location *richloc,
27238fd1498Szrj diagnostic_t kind)
27338fd1498Szrj {
27438fd1498Szrj gcc_assert (richloc);
27538fd1498Szrj diagnostic_set_info_translated (diagnostic, _(gmsgid), args, richloc, kind);
27638fd1498Szrj }
27738fd1498Szrj
27838fd1498Szrj static const char *const diagnostic_kind_color[] = {
27938fd1498Szrj #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
28038fd1498Szrj #include "diagnostic.def"
28138fd1498Szrj #undef DEFINE_DIAGNOSTIC_KIND
28238fd1498Szrj NULL
28338fd1498Szrj };
28438fd1498Szrj
28538fd1498Szrj /* Get a color name for diagnostics of type KIND
28638fd1498Szrj Result could be NULL. */
28738fd1498Szrj
28838fd1498Szrj const char *
diagnostic_get_color_for_kind(diagnostic_t kind)28938fd1498Szrj diagnostic_get_color_for_kind (diagnostic_t kind)
29038fd1498Szrj {
29138fd1498Szrj return diagnostic_kind_color[kind];
29238fd1498Szrj }
29338fd1498Szrj
29438fd1498Szrj /* Return a formatted line and column ':%line:%column'. Elided if
29538fd1498Szrj zero. The result is a statically allocated buffer. */
29638fd1498Szrj
29738fd1498Szrj static const char *
maybe_line_and_column(int line,int col)29838fd1498Szrj maybe_line_and_column (int line, int col)
29938fd1498Szrj {
30038fd1498Szrj static char result[32];
30138fd1498Szrj
30238fd1498Szrj if (line)
30338fd1498Szrj {
30438fd1498Szrj size_t l = snprintf (result, sizeof (result),
30538fd1498Szrj col ? ":%d:%d" : ":%d", line, col);
30638fd1498Szrj gcc_checking_assert (l < sizeof (result));
30738fd1498Szrj }
30838fd1498Szrj else
30938fd1498Szrj result[0] = 0;
31038fd1498Szrj return result;
31138fd1498Szrj }
31238fd1498Szrj
31338fd1498Szrj /* Return a malloc'd string describing a location e.g. "foo.c:42:10".
31438fd1498Szrj The caller is responsible for freeing the memory. */
31538fd1498Szrj
31638fd1498Szrj static char *
diagnostic_get_location_text(diagnostic_context * context,expanded_location s)31738fd1498Szrj diagnostic_get_location_text (diagnostic_context *context,
31838fd1498Szrj expanded_location s)
31938fd1498Szrj {
32038fd1498Szrj pretty_printer *pp = context->printer;
32138fd1498Szrj const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
32238fd1498Szrj const char *locus_ce = colorize_stop (pp_show_color (pp));
32338fd1498Szrj const char *file = s.file ? s.file : progname;
32438fd1498Szrj int line = strcmp (file, N_("<built-in>")) ? s.line : 0;
32538fd1498Szrj int col = context->show_column ? s.column : 0;
32638fd1498Szrj
32738fd1498Szrj const char *line_col = maybe_line_and_column (line, col);
32838fd1498Szrj return build_message_string ("%s%s%s:%s", locus_cs, file,
32938fd1498Szrj line_col, locus_ce);
33038fd1498Szrj }
33138fd1498Szrj
33238fd1498Szrj /* Return a malloc'd string describing a location and the severity of the
33338fd1498Szrj diagnostic, e.g. "foo.c:42:10: error: ". The caller is responsible for
33438fd1498Szrj freeing the memory. */
33538fd1498Szrj char *
diagnostic_build_prefix(diagnostic_context * context,const diagnostic_info * diagnostic)33638fd1498Szrj diagnostic_build_prefix (diagnostic_context *context,
33738fd1498Szrj const diagnostic_info *diagnostic)
33838fd1498Szrj {
33938fd1498Szrj static const char *const diagnostic_kind_text[] = {
34038fd1498Szrj #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
34138fd1498Szrj #include "diagnostic.def"
34238fd1498Szrj #undef DEFINE_DIAGNOSTIC_KIND
34338fd1498Szrj "must-not-happen"
34438fd1498Szrj };
34538fd1498Szrj gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
34638fd1498Szrj
34738fd1498Szrj const char *text = _(diagnostic_kind_text[diagnostic->kind]);
34838fd1498Szrj const char *text_cs = "", *text_ce = "";
34938fd1498Szrj pretty_printer *pp = context->printer;
35038fd1498Szrj
35138fd1498Szrj if (diagnostic_kind_color[diagnostic->kind])
35238fd1498Szrj {
35338fd1498Szrj text_cs = colorize_start (pp_show_color (pp),
35438fd1498Szrj diagnostic_kind_color[diagnostic->kind]);
35538fd1498Szrj text_ce = colorize_stop (pp_show_color (pp));
35638fd1498Szrj }
35738fd1498Szrj
35838fd1498Szrj expanded_location s = diagnostic_expand_location (diagnostic);
35938fd1498Szrj char *location_text = diagnostic_get_location_text (context, s);
36038fd1498Szrj
36138fd1498Szrj char *result = build_message_string ("%s %s%s%s", location_text,
36238fd1498Szrj text_cs, text, text_ce);
36338fd1498Szrj free (location_text);
36438fd1498Szrj return result;
36538fd1498Szrj }
36638fd1498Szrj
36738fd1498Szrj /* Functions at which to stop the backtrace print. It's not
36838fd1498Szrj particularly helpful to print the callers of these functions. */
36938fd1498Szrj
37038fd1498Szrj static const char * const bt_stop[] =
37138fd1498Szrj {
37238fd1498Szrj "main",
37338fd1498Szrj "toplev::main",
37438fd1498Szrj "execute_one_pass",
37538fd1498Szrj "compile_file",
37638fd1498Szrj };
37738fd1498Szrj
37838fd1498Szrj /* A callback function passed to the backtrace_full function. */
37938fd1498Szrj
38038fd1498Szrj static int
bt_callback(void * data,uintptr_t pc,const char * filename,int lineno,const char * function)38138fd1498Szrj bt_callback (void *data, uintptr_t pc, const char *filename, int lineno,
38238fd1498Szrj const char *function)
38338fd1498Szrj {
38438fd1498Szrj int *pcount = (int *) data;
38538fd1498Szrj
38638fd1498Szrj /* If we don't have any useful information, don't print
38738fd1498Szrj anything. */
38838fd1498Szrj if (filename == NULL && function == NULL)
38938fd1498Szrj return 0;
39038fd1498Szrj
39138fd1498Szrj /* Skip functions in diagnostic.c. */
39238fd1498Szrj if (*pcount == 0
39338fd1498Szrj && filename != NULL
39438fd1498Szrj && strcmp (lbasename (filename), "diagnostic.c") == 0)
39538fd1498Szrj return 0;
39638fd1498Szrj
39738fd1498Szrj /* Print up to 20 functions. We could make this a --param, but
39838fd1498Szrj since this is only for debugging just use a constant for now. */
39938fd1498Szrj if (*pcount >= 20)
40038fd1498Szrj {
40138fd1498Szrj /* Returning a non-zero value stops the backtrace. */
40238fd1498Szrj return 1;
40338fd1498Szrj }
40438fd1498Szrj ++*pcount;
40538fd1498Szrj
40638fd1498Szrj char *alc = NULL;
40738fd1498Szrj if (function != NULL)
40838fd1498Szrj {
40938fd1498Szrj char *str = cplus_demangle_v3 (function,
41038fd1498Szrj (DMGL_VERBOSE | DMGL_ANSI
41138fd1498Szrj | DMGL_GNU_V3 | DMGL_PARAMS));
41238fd1498Szrj if (str != NULL)
41338fd1498Szrj {
41438fd1498Szrj alc = str;
41538fd1498Szrj function = str;
41638fd1498Szrj }
41738fd1498Szrj
41838fd1498Szrj for (size_t i = 0; i < ARRAY_SIZE (bt_stop); ++i)
41938fd1498Szrj {
42038fd1498Szrj size_t len = strlen (bt_stop[i]);
42138fd1498Szrj if (strncmp (function, bt_stop[i], len) == 0
42238fd1498Szrj && (function[len] == '\0' || function[len] == '('))
42338fd1498Szrj {
42438fd1498Szrj if (alc != NULL)
42538fd1498Szrj free (alc);
42638fd1498Szrj /* Returning a non-zero value stops the backtrace. */
42738fd1498Szrj return 1;
42838fd1498Szrj }
42938fd1498Szrj }
43038fd1498Szrj }
43138fd1498Szrj
43238fd1498Szrj fprintf (stderr, "0x%lx %s\n\t%s:%d\n",
43338fd1498Szrj (unsigned long) pc,
43438fd1498Szrj function == NULL ? "???" : function,
43538fd1498Szrj filename == NULL ? "???" : filename,
43638fd1498Szrj lineno);
43738fd1498Szrj
43838fd1498Szrj if (alc != NULL)
43938fd1498Szrj free (alc);
44038fd1498Szrj
44138fd1498Szrj return 0;
44238fd1498Szrj }
44338fd1498Szrj
44438fd1498Szrj /* A callback function passed to the backtrace_full function. This is
44538fd1498Szrj called if backtrace_full has an error. */
44638fd1498Szrj
44738fd1498Szrj static void
bt_err_callback(void * data ATTRIBUTE_UNUSED,const char * msg,int errnum)44838fd1498Szrj bt_err_callback (void *data ATTRIBUTE_UNUSED, const char *msg, int errnum)
44938fd1498Szrj {
45038fd1498Szrj if (errnum < 0)
45138fd1498Szrj {
45238fd1498Szrj /* This means that no debug info was available. Just quietly
45338fd1498Szrj skip printing backtrace info. */
45438fd1498Szrj return;
45538fd1498Szrj }
45638fd1498Szrj fprintf (stderr, "%s%s%s\n", msg, errnum == 0 ? "" : ": ",
45738fd1498Szrj errnum == 0 ? "" : xstrerror (errnum));
45838fd1498Szrj }
45938fd1498Szrj
46038fd1498Szrj /* Check if we've met the maximum error limit, and if so fatally exit
46138fd1498Szrj with a message. CONTEXT is the context to check, and FLUSH
46238fd1498Szrj indicates whether a diagnostic_finish call is needed. */
46338fd1498Szrj
46438fd1498Szrj void
diagnostic_check_max_errors(diagnostic_context * context,bool flush)46538fd1498Szrj diagnostic_check_max_errors (diagnostic_context *context, bool flush)
46638fd1498Szrj {
46738fd1498Szrj if (!context->max_errors)
46838fd1498Szrj return;
46938fd1498Szrj
47038fd1498Szrj int count = (diagnostic_kind_count (context, DK_ERROR)
47138fd1498Szrj + diagnostic_kind_count (context, DK_SORRY)
47238fd1498Szrj + diagnostic_kind_count (context, DK_WERROR));
47338fd1498Szrj
47438fd1498Szrj if (count >= context->max_errors)
47538fd1498Szrj {
47638fd1498Szrj fnotice (stderr,
47738fd1498Szrj "compilation terminated due to -fmax-errors=%u.\n",
47838fd1498Szrj context->max_errors);
47938fd1498Szrj if (flush)
48038fd1498Szrj diagnostic_finish (context);
48138fd1498Szrj exit (FATAL_EXIT_CODE);
48238fd1498Szrj }
48338fd1498Szrj }
48438fd1498Szrj
48538fd1498Szrj /* Take any action which is expected to happen after the diagnostic
48638fd1498Szrj is written out. This function does not always return. */
48738fd1498Szrj void
diagnostic_action_after_output(diagnostic_context * context,diagnostic_t diag_kind)48838fd1498Szrj diagnostic_action_after_output (diagnostic_context *context,
48938fd1498Szrj diagnostic_t diag_kind)
49038fd1498Szrj {
49138fd1498Szrj switch (diag_kind)
49238fd1498Szrj {
49338fd1498Szrj case DK_DEBUG:
49438fd1498Szrj case DK_NOTE:
49538fd1498Szrj case DK_ANACHRONISM:
49638fd1498Szrj case DK_WARNING:
49738fd1498Szrj break;
49838fd1498Szrj
49938fd1498Szrj case DK_ERROR:
50038fd1498Szrj case DK_SORRY:
50138fd1498Szrj if (context->abort_on_error)
50238fd1498Szrj real_abort ();
50338fd1498Szrj if (context->fatal_errors)
50438fd1498Szrj {
50538fd1498Szrj fnotice (stderr, "compilation terminated due to -Wfatal-errors.\n");
50638fd1498Szrj diagnostic_finish (context);
50738fd1498Szrj exit (FATAL_EXIT_CODE);
50838fd1498Szrj }
50938fd1498Szrj break;
51038fd1498Szrj
51138fd1498Szrj case DK_ICE:
51238fd1498Szrj case DK_ICE_NOBT:
51338fd1498Szrj {
51438fd1498Szrj struct backtrace_state *state = NULL;
51538fd1498Szrj if (diag_kind == DK_ICE)
51638fd1498Szrj state = backtrace_create_state (NULL, 0, bt_err_callback, NULL);
51738fd1498Szrj int count = 0;
51838fd1498Szrj if (state != NULL)
51938fd1498Szrj backtrace_full (state, 2, bt_callback, bt_err_callback,
52038fd1498Szrj (void *) &count);
52138fd1498Szrj
52238fd1498Szrj if (context->abort_on_error)
52338fd1498Szrj real_abort ();
52438fd1498Szrj
52538fd1498Szrj fnotice (stderr, "Please submit a full bug report,\n"
52638fd1498Szrj "with preprocessed source if appropriate.\n");
52738fd1498Szrj if (count > 0)
52838fd1498Szrj fnotice (stderr,
52938fd1498Szrj ("Please include the complete backtrace "
53038fd1498Szrj "with any bug report.\n"));
53138fd1498Szrj fnotice (stderr, "See %s for instructions.\n", bug_report_url);
53238fd1498Szrj
53338fd1498Szrj exit (ICE_EXIT_CODE);
53438fd1498Szrj }
53538fd1498Szrj
53638fd1498Szrj case DK_FATAL:
53738fd1498Szrj if (context->abort_on_error)
53838fd1498Szrj real_abort ();
53938fd1498Szrj diagnostic_finish (context);
54038fd1498Szrj fnotice (stderr, "compilation terminated.\n");
54138fd1498Szrj exit (FATAL_EXIT_CODE);
54238fd1498Szrj
54338fd1498Szrj default:
54438fd1498Szrj gcc_unreachable ();
54538fd1498Szrj }
54638fd1498Szrj }
54738fd1498Szrj
54838fd1498Szrj /* True if the last module or file in which a diagnostic was reported is
54938fd1498Szrj different from the current one. */
55038fd1498Szrj
55138fd1498Szrj static bool
last_module_changed_p(diagnostic_context * context,const line_map_ordinary * map)55238fd1498Szrj last_module_changed_p (diagnostic_context *context,
55338fd1498Szrj const line_map_ordinary *map)
55438fd1498Szrj {
55538fd1498Szrj return context->last_module != map;
55638fd1498Szrj }
55738fd1498Szrj
55838fd1498Szrj /* Remember the current module or file as being the last one in which we
55938fd1498Szrj report a diagnostic. */
56038fd1498Szrj
56138fd1498Szrj static void
set_last_module(diagnostic_context * context,const line_map_ordinary * map)56238fd1498Szrj set_last_module (diagnostic_context *context, const line_map_ordinary *map)
56338fd1498Szrj {
56438fd1498Szrj context->last_module = map;
56538fd1498Szrj }
56638fd1498Szrj
56738fd1498Szrj void
diagnostic_report_current_module(diagnostic_context * context,location_t where)56838fd1498Szrj diagnostic_report_current_module (diagnostic_context *context, location_t where)
56938fd1498Szrj {
57038fd1498Szrj const line_map_ordinary *map = NULL;
57138fd1498Szrj
57238fd1498Szrj if (pp_needs_newline (context->printer))
57338fd1498Szrj {
57438fd1498Szrj pp_newline (context->printer);
57538fd1498Szrj pp_needs_newline (context->printer) = false;
57638fd1498Szrj }
57738fd1498Szrj
57838fd1498Szrj if (where <= BUILTINS_LOCATION)
57938fd1498Szrj return;
58038fd1498Szrj
58138fd1498Szrj linemap_resolve_location (line_table, where,
58238fd1498Szrj LRK_MACRO_DEFINITION_LOCATION,
58338fd1498Szrj &map);
58438fd1498Szrj
58538fd1498Szrj if (map && last_module_changed_p (context, map))
58638fd1498Szrj {
58738fd1498Szrj set_last_module (context, map);
58838fd1498Szrj if (! MAIN_FILE_P (map))
58938fd1498Szrj {
59038fd1498Szrj map = INCLUDED_FROM (line_table, map);
59138fd1498Szrj const char *line_col
59238fd1498Szrj = maybe_line_and_column (LAST_SOURCE_LINE (map),
59338fd1498Szrj context->show_column
59438fd1498Szrj ? LAST_SOURCE_COLUMN (map) : 0);
59538fd1498Szrj pp_verbatim (context->printer,
59638fd1498Szrj "In file included from %r%s%s%R", "locus",
59738fd1498Szrj LINEMAP_FILE (map), line_col);
59838fd1498Szrj while (! MAIN_FILE_P (map))
59938fd1498Szrj {
60038fd1498Szrj map = INCLUDED_FROM (line_table, map);
60138fd1498Szrj line_col = maybe_line_and_column (LAST_SOURCE_LINE (map), 0);
60238fd1498Szrj pp_verbatim (context->printer,
60338fd1498Szrj ",\n from %r%s%s%R", "locus",
60438fd1498Szrj LINEMAP_FILE (map), line_col);
60538fd1498Szrj }
60638fd1498Szrj pp_verbatim (context->printer, ":");
60738fd1498Szrj pp_newline (context->printer);
60838fd1498Szrj }
60938fd1498Szrj }
61038fd1498Szrj }
61138fd1498Szrj
61238fd1498Szrj void
default_diagnostic_starter(diagnostic_context * context,diagnostic_info * diagnostic)61338fd1498Szrj default_diagnostic_starter (diagnostic_context *context,
61438fd1498Szrj diagnostic_info *diagnostic)
61538fd1498Szrj {
61638fd1498Szrj diagnostic_report_current_module (context, diagnostic_location (diagnostic));
61738fd1498Szrj pp_set_prefix (context->printer, diagnostic_build_prefix (context,
61838fd1498Szrj diagnostic));
61938fd1498Szrj }
62038fd1498Szrj
62138fd1498Szrj void
default_diagnostic_start_span_fn(diagnostic_context * context,expanded_location exploc)62238fd1498Szrj default_diagnostic_start_span_fn (diagnostic_context *context,
62338fd1498Szrj expanded_location exploc)
62438fd1498Szrj {
62538fd1498Szrj pp_set_prefix (context->printer,
62638fd1498Szrj diagnostic_get_location_text (context, exploc));
62738fd1498Szrj pp_string (context->printer, "");
62838fd1498Szrj pp_newline (context->printer);
62938fd1498Szrj }
63038fd1498Szrj
63138fd1498Szrj void
default_diagnostic_finalizer(diagnostic_context * context,diagnostic_info * diagnostic)63238fd1498Szrj default_diagnostic_finalizer (diagnostic_context *context,
63338fd1498Szrj diagnostic_info *diagnostic)
63438fd1498Szrj {
63538fd1498Szrj diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
63638fd1498Szrj pp_destroy_prefix (context->printer);
63738fd1498Szrj pp_flush (context->printer);
63838fd1498Szrj }
63938fd1498Szrj
64038fd1498Szrj /* Interface to specify diagnostic kind overrides. Returns the
64138fd1498Szrj previous setting, or DK_UNSPECIFIED if the parameters are out of
64238fd1498Szrj range. If OPTION_INDEX is zero, the new setting is for all the
64338fd1498Szrj diagnostics. */
64438fd1498Szrj diagnostic_t
diagnostic_classify_diagnostic(diagnostic_context * context,int option_index,diagnostic_t new_kind,location_t where)64538fd1498Szrj diagnostic_classify_diagnostic (diagnostic_context *context,
64638fd1498Szrj int option_index,
64738fd1498Szrj diagnostic_t new_kind,
64838fd1498Szrj location_t where)
64938fd1498Szrj {
65038fd1498Szrj diagnostic_t old_kind;
65138fd1498Szrj
65238fd1498Szrj if (option_index < 0
65338fd1498Szrj || option_index >= context->n_opts
65438fd1498Szrj || new_kind >= DK_LAST_DIAGNOSTIC_KIND)
65538fd1498Szrj return DK_UNSPECIFIED;
65638fd1498Szrj
65738fd1498Szrj old_kind = context->classify_diagnostic[option_index];
65838fd1498Szrj
65938fd1498Szrj /* Handle pragmas separately, since we need to keep track of *where*
66038fd1498Szrj the pragmas were. */
66138fd1498Szrj if (where != UNKNOWN_LOCATION)
66238fd1498Szrj {
66338fd1498Szrj int i;
66438fd1498Szrj
66538fd1498Szrj /* Record the command-line status, so we can reset it back on DK_POP. */
66638fd1498Szrj if (old_kind == DK_UNSPECIFIED)
66738fd1498Szrj {
66838fd1498Szrj old_kind = !context->option_enabled (option_index,
66938fd1498Szrj context->option_state)
67038fd1498Szrj ? DK_IGNORED : (context->warning_as_error_requested
67138fd1498Szrj ? DK_ERROR : DK_WARNING);
67238fd1498Szrj context->classify_diagnostic[option_index] = old_kind;
67338fd1498Szrj }
67438fd1498Szrj
67538fd1498Szrj for (i = context->n_classification_history - 1; i >= 0; i --)
67638fd1498Szrj if (context->classification_history[i].option == option_index)
67738fd1498Szrj {
67838fd1498Szrj old_kind = context->classification_history[i].kind;
67938fd1498Szrj break;
68038fd1498Szrj }
68138fd1498Szrj
68238fd1498Szrj i = context->n_classification_history;
68338fd1498Szrj context->classification_history =
68438fd1498Szrj (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
68538fd1498Szrj * sizeof (diagnostic_classification_change_t));
68638fd1498Szrj context->classification_history[i].location = where;
68738fd1498Szrj context->classification_history[i].option = option_index;
68838fd1498Szrj context->classification_history[i].kind = new_kind;
68938fd1498Szrj context->n_classification_history ++;
69038fd1498Szrj }
69138fd1498Szrj else
69238fd1498Szrj context->classify_diagnostic[option_index] = new_kind;
69338fd1498Szrj
69438fd1498Szrj return old_kind;
69538fd1498Szrj }
69638fd1498Szrj
69738fd1498Szrj /* Save all diagnostic classifications in a stack. */
69838fd1498Szrj void
diagnostic_push_diagnostics(diagnostic_context * context,location_t where ATTRIBUTE_UNUSED)69938fd1498Szrj diagnostic_push_diagnostics (diagnostic_context *context, location_t where ATTRIBUTE_UNUSED)
70038fd1498Szrj {
70138fd1498Szrj context->push_list = (int *) xrealloc (context->push_list, (context->n_push + 1) * sizeof (int));
70238fd1498Szrj context->push_list[context->n_push ++] = context->n_classification_history;
70338fd1498Szrj }
70438fd1498Szrj
70538fd1498Szrj /* Restore the topmost classification set off the stack. If the stack
70638fd1498Szrj is empty, revert to the state based on command line parameters. */
70738fd1498Szrj void
diagnostic_pop_diagnostics(diagnostic_context * context,location_t where)70838fd1498Szrj diagnostic_pop_diagnostics (diagnostic_context *context, location_t where)
70938fd1498Szrj {
71038fd1498Szrj int jump_to;
71138fd1498Szrj int i;
71238fd1498Szrj
71338fd1498Szrj if (context->n_push)
71438fd1498Szrj jump_to = context->push_list [-- context->n_push];
71538fd1498Szrj else
71638fd1498Szrj jump_to = 0;
71738fd1498Szrj
71838fd1498Szrj i = context->n_classification_history;
71938fd1498Szrj context->classification_history =
72038fd1498Szrj (diagnostic_classification_change_t *) xrealloc (context->classification_history, (i + 1)
72138fd1498Szrj * sizeof (diagnostic_classification_change_t));
72238fd1498Szrj context->classification_history[i].location = where;
72338fd1498Szrj context->classification_history[i].option = jump_to;
72438fd1498Szrj context->classification_history[i].kind = DK_POP;
72538fd1498Szrj context->n_classification_history ++;
72638fd1498Szrj }
72738fd1498Szrj
72838fd1498Szrj /* Helper function for print_parseable_fixits. Print TEXT to PP, obeying the
72938fd1498Szrj escaping rules for -fdiagnostics-parseable-fixits. */
73038fd1498Szrj
73138fd1498Szrj static void
print_escaped_string(pretty_printer * pp,const char * text)73238fd1498Szrj print_escaped_string (pretty_printer *pp, const char *text)
73338fd1498Szrj {
73438fd1498Szrj gcc_assert (pp);
73538fd1498Szrj gcc_assert (text);
73638fd1498Szrj
73738fd1498Szrj pp_character (pp, '"');
73838fd1498Szrj for (const char *ch = text; *ch; ch++)
73938fd1498Szrj {
74038fd1498Szrj switch (*ch)
74138fd1498Szrj {
74238fd1498Szrj case '\\':
74338fd1498Szrj /* Escape backslash as two backslashes. */
74438fd1498Szrj pp_string (pp, "\\\\");
74538fd1498Szrj break;
74638fd1498Szrj case '\t':
74738fd1498Szrj /* Escape tab as "\t". */
74838fd1498Szrj pp_string (pp, "\\t");
74938fd1498Szrj break;
75038fd1498Szrj case '\n':
75138fd1498Szrj /* Escape newline as "\n". */
75238fd1498Szrj pp_string (pp, "\\n");
75338fd1498Szrj break;
75438fd1498Szrj case '"':
75538fd1498Szrj /* Escape doublequotes as \". */
75638fd1498Szrj pp_string (pp, "\\\"");
75738fd1498Szrj break;
75838fd1498Szrj default:
75938fd1498Szrj if (ISPRINT (*ch))
76038fd1498Szrj pp_character (pp, *ch);
76138fd1498Szrj else
76238fd1498Szrj /* Use octal for non-printable chars. */
76338fd1498Szrj {
76438fd1498Szrj unsigned char c = (*ch & 0xff);
76538fd1498Szrj pp_printf (pp, "\\%o%o%o", (c / 64), (c / 8) & 007, c & 007);
76638fd1498Szrj }
76738fd1498Szrj break;
76838fd1498Szrj }
76938fd1498Szrj }
77038fd1498Szrj pp_character (pp, '"');
77138fd1498Szrj }
77238fd1498Szrj
77338fd1498Szrj /* Implementation of -fdiagnostics-parseable-fixits. Print a
77438fd1498Szrj machine-parseable version of all fixits in RICHLOC to PP. */
77538fd1498Szrj
77638fd1498Szrj static void
print_parseable_fixits(pretty_printer * pp,rich_location * richloc)77738fd1498Szrj print_parseable_fixits (pretty_printer *pp, rich_location *richloc)
77838fd1498Szrj {
77938fd1498Szrj gcc_assert (pp);
78038fd1498Szrj gcc_assert (richloc);
78138fd1498Szrj
78238fd1498Szrj for (unsigned i = 0; i < richloc->get_num_fixit_hints (); i++)
78338fd1498Szrj {
78438fd1498Szrj const fixit_hint *hint = richloc->get_fixit_hint (i);
78538fd1498Szrj source_location start_loc = hint->get_start_loc ();
78638fd1498Szrj expanded_location start_exploc = expand_location (start_loc);
78738fd1498Szrj pp_string (pp, "fix-it:");
78838fd1498Szrj print_escaped_string (pp, start_exploc.file);
78938fd1498Szrj /* For compatibility with clang, print as a half-open range. */
79038fd1498Szrj source_location next_loc = hint->get_next_loc ();
79138fd1498Szrj expanded_location next_exploc = expand_location (next_loc);
79238fd1498Szrj pp_printf (pp, ":{%i:%i-%i:%i}:",
79338fd1498Szrj start_exploc.line, start_exploc.column,
79438fd1498Szrj next_exploc.line, next_exploc.column);
79538fd1498Szrj print_escaped_string (pp, hint->get_string ());
79638fd1498Szrj pp_newline (pp);
79738fd1498Szrj }
79838fd1498Szrj }
79938fd1498Szrj
80038fd1498Szrj /* Update the diag_class of DIAGNOSTIC based on its location
80138fd1498Szrj relative to any
80238fd1498Szrj #pragma GCC diagnostic
80338fd1498Szrj directives recorded within CONTEXT.
80438fd1498Szrj
80538fd1498Szrj Return the new diag_class of DIAGNOSTIC if it was updated, or
80638fd1498Szrj DK_UNSPECIFIED otherwise. */
80738fd1498Szrj
80838fd1498Szrj static diagnostic_t
update_effective_level_from_pragmas(diagnostic_context * context,diagnostic_info * diagnostic)80938fd1498Szrj update_effective_level_from_pragmas (diagnostic_context *context,
81038fd1498Szrj diagnostic_info *diagnostic)
81138fd1498Szrj {
81238fd1498Szrj diagnostic_t diag_class = DK_UNSPECIFIED;
81338fd1498Szrj
81438fd1498Szrj if (context->n_classification_history > 0)
81538fd1498Szrj {
81638fd1498Szrj location_t location = diagnostic_location (diagnostic);
81738fd1498Szrj
81838fd1498Szrj /* FIXME: Stupid search. Optimize later. */
81938fd1498Szrj for (int i = context->n_classification_history - 1; i >= 0; i --)
82038fd1498Szrj {
82138fd1498Szrj if (linemap_location_before_p
82238fd1498Szrj (line_table,
82338fd1498Szrj context->classification_history[i].location,
82438fd1498Szrj location))
82538fd1498Szrj {
82638fd1498Szrj if (context->classification_history[i].kind == (int) DK_POP)
82738fd1498Szrj {
82838fd1498Szrj i = context->classification_history[i].option;
82938fd1498Szrj continue;
83038fd1498Szrj }
83138fd1498Szrj int option = context->classification_history[i].option;
83238fd1498Szrj /* The option 0 is for all the diagnostics. */
83338fd1498Szrj if (option == 0 || option == diagnostic->option_index)
83438fd1498Szrj {
83538fd1498Szrj diag_class = context->classification_history[i].kind;
83638fd1498Szrj if (diag_class != DK_UNSPECIFIED)
83738fd1498Szrj diagnostic->kind = diag_class;
83838fd1498Szrj break;
83938fd1498Szrj }
84038fd1498Szrj }
84138fd1498Szrj }
84238fd1498Szrj }
84338fd1498Szrj
84438fd1498Szrj return diag_class;
84538fd1498Szrj }
84638fd1498Szrj
84738fd1498Szrj /* Print any metadata about the option used to control DIAGNOSTIC to CONTEXT's
84838fd1498Szrj printer, e.g. " [-Werror=uninitialized]".
84938fd1498Szrj Subroutine of diagnostic_report_diagnostic. */
85038fd1498Szrj
85138fd1498Szrj static void
print_option_information(diagnostic_context * context,const diagnostic_info * diagnostic,diagnostic_t orig_diag_kind)85238fd1498Szrj print_option_information (diagnostic_context *context,
85338fd1498Szrj const diagnostic_info *diagnostic,
85438fd1498Szrj diagnostic_t orig_diag_kind)
85538fd1498Szrj {
85638fd1498Szrj char *option_text;
85738fd1498Szrj
85838fd1498Szrj option_text = context->option_name (context, diagnostic->option_index,
85938fd1498Szrj orig_diag_kind, diagnostic->kind);
86038fd1498Szrj
86138fd1498Szrj if (option_text)
86238fd1498Szrj {
86338fd1498Szrj pretty_printer *pp = context->printer;
86438fd1498Szrj pp_string (pp, " [");
86538fd1498Szrj pp_string (pp, colorize_start (pp_show_color (pp),
86638fd1498Szrj diagnostic_kind_color[diagnostic->kind]));
86738fd1498Szrj pp_string (pp, option_text);
86838fd1498Szrj pp_string (pp, colorize_stop (pp_show_color (pp)));
86938fd1498Szrj pp_character (pp, ']');
87038fd1498Szrj free (option_text);
87138fd1498Szrj }
87238fd1498Szrj }
87338fd1498Szrj
87438fd1498Szrj /* Report a diagnostic message (an error or a warning) as specified by
87538fd1498Szrj DC. This function is *the* subroutine in terms of which front-ends
87638fd1498Szrj should implement their specific diagnostic handling modules. The
87738fd1498Szrj front-end independent format specifiers are exactly those described
87838fd1498Szrj in the documentation of output_format.
87938fd1498Szrj Return true if a diagnostic was printed, false otherwise. */
88038fd1498Szrj
88138fd1498Szrj bool
diagnostic_report_diagnostic(diagnostic_context * context,diagnostic_info * diagnostic)88238fd1498Szrj diagnostic_report_diagnostic (diagnostic_context *context,
88338fd1498Szrj diagnostic_info *diagnostic)
88438fd1498Szrj {
88538fd1498Szrj location_t location = diagnostic_location (diagnostic);
88638fd1498Szrj diagnostic_t orig_diag_kind = diagnostic->kind;
88738fd1498Szrj
88838fd1498Szrj /* Give preference to being able to inhibit warnings, before they
88938fd1498Szrj get reclassified to something else. */
89038fd1498Szrj if ((diagnostic->kind == DK_WARNING || diagnostic->kind == DK_PEDWARN)
89138fd1498Szrj && !diagnostic_report_warnings_p (context, location))
89238fd1498Szrj return false;
89338fd1498Szrj
89438fd1498Szrj if (diagnostic->kind == DK_PEDWARN)
89538fd1498Szrj {
89638fd1498Szrj diagnostic->kind = pedantic_warning_kind (context);
89738fd1498Szrj /* We do this to avoid giving the message for -pedantic-errors. */
89838fd1498Szrj orig_diag_kind = diagnostic->kind;
89938fd1498Szrj }
90038fd1498Szrj
90138fd1498Szrj if (diagnostic->kind == DK_NOTE && context->inhibit_notes_p)
90238fd1498Szrj return false;
90338fd1498Szrj
90438fd1498Szrj if (context->lock > 0)
90538fd1498Szrj {
90638fd1498Szrj /* If we're reporting an ICE in the middle of some other error,
90738fd1498Szrj try to flush out the previous error, then let this one
90838fd1498Szrj through. Don't do this more than once. */
90938fd1498Szrj if ((diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
91038fd1498Szrj && context->lock == 1)
91138fd1498Szrj pp_newline_and_flush (context->printer);
91238fd1498Szrj else
91338fd1498Szrj error_recursion (context);
91438fd1498Szrj }
91538fd1498Szrj
91638fd1498Szrj /* If the user requested that warnings be treated as errors, so be
91738fd1498Szrj it. Note that we do this before the next block so that
91838fd1498Szrj individual warnings can be overridden back to warnings with
91938fd1498Szrj -Wno-error=*. */
92038fd1498Szrj if (context->warning_as_error_requested
92138fd1498Szrj && diagnostic->kind == DK_WARNING)
92238fd1498Szrj diagnostic->kind = DK_ERROR;
92338fd1498Szrj
92438fd1498Szrj if (diagnostic->option_index
92538fd1498Szrj && diagnostic->option_index != permissive_error_option (context))
92638fd1498Szrj {
92738fd1498Szrj /* This tests if the user provided the appropriate -Wfoo or
92838fd1498Szrj -Wno-foo option. */
92938fd1498Szrj if (! context->option_enabled (diagnostic->option_index,
93038fd1498Szrj context->option_state))
93138fd1498Szrj return false;
93238fd1498Szrj
93338fd1498Szrj /* This tests for #pragma diagnostic changes. */
93438fd1498Szrj diagnostic_t diag_class
93538fd1498Szrj = update_effective_level_from_pragmas (context, diagnostic);
93638fd1498Szrj
93738fd1498Szrj /* This tests if the user provided the appropriate -Werror=foo
93838fd1498Szrj option. */
93938fd1498Szrj if (diag_class == DK_UNSPECIFIED
94038fd1498Szrj && (context->classify_diagnostic[diagnostic->option_index]
94138fd1498Szrj != DK_UNSPECIFIED))
94238fd1498Szrj diagnostic->kind
94338fd1498Szrj = context->classify_diagnostic[diagnostic->option_index];
94438fd1498Szrj
94538fd1498Szrj /* This allows for future extensions, like temporarily disabling
94638fd1498Szrj warnings for ranges of source code. */
94738fd1498Szrj if (diagnostic->kind == DK_IGNORED)
94838fd1498Szrj return false;
94938fd1498Szrj }
95038fd1498Szrj
95138fd1498Szrj if (diagnostic->kind != DK_NOTE)
95238fd1498Szrj diagnostic_check_max_errors (context);
95338fd1498Szrj
95438fd1498Szrj context->lock++;
95538fd1498Szrj
95638fd1498Szrj if (diagnostic->kind == DK_ICE || diagnostic->kind == DK_ICE_NOBT)
95738fd1498Szrj {
95838fd1498Szrj /* When not checking, ICEs are converted to fatal errors when an
95938fd1498Szrj error has already occurred. This is counteracted by
96038fd1498Szrj abort_on_error. */
96138fd1498Szrj if (!CHECKING_P
96238fd1498Szrj && (diagnostic_kind_count (context, DK_ERROR) > 0
96338fd1498Szrj || diagnostic_kind_count (context, DK_SORRY) > 0)
96438fd1498Szrj && !context->abort_on_error)
96538fd1498Szrj {
96638fd1498Szrj expanded_location s
96738fd1498Szrj = expand_location (diagnostic_location (diagnostic));
96838fd1498Szrj fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
96938fd1498Szrj s.file, s.line);
97038fd1498Szrj exit (ICE_EXIT_CODE);
97138fd1498Szrj }
97238fd1498Szrj if (context->internal_error)
97338fd1498Szrj (*context->internal_error) (context,
97438fd1498Szrj diagnostic->message.format_spec,
97538fd1498Szrj diagnostic->message.args_ptr);
97638fd1498Szrj }
97738fd1498Szrj if (diagnostic->kind == DK_ERROR && orig_diag_kind == DK_WARNING)
97838fd1498Szrj ++diagnostic_kind_count (context, DK_WERROR);
97938fd1498Szrj else
98038fd1498Szrj ++diagnostic_kind_count (context, diagnostic->kind);
98138fd1498Szrj
98238fd1498Szrj diagnostic->message.x_data = &diagnostic->x_data;
98338fd1498Szrj diagnostic->x_data = NULL;
98438fd1498Szrj pp_format (context->printer, &diagnostic->message);
98538fd1498Szrj (*diagnostic_starter (context)) (context, diagnostic);
98638fd1498Szrj pp_output_formatted_text (context->printer);
98738fd1498Szrj if (context->show_option_requested)
98838fd1498Szrj print_option_information (context, diagnostic, orig_diag_kind);
98938fd1498Szrj (*diagnostic_finalizer (context)) (context, diagnostic);
99038fd1498Szrj if (context->parseable_fixits_p)
99138fd1498Szrj {
99238fd1498Szrj print_parseable_fixits (context->printer, diagnostic->richloc);
99338fd1498Szrj pp_flush (context->printer);
99438fd1498Szrj }
99538fd1498Szrj diagnostic_action_after_output (context, diagnostic->kind);
99638fd1498Szrj diagnostic->x_data = NULL;
99738fd1498Szrj
99838fd1498Szrj if (context->edit_context_ptr)
99938fd1498Szrj if (diagnostic->richloc->fixits_can_be_auto_applied_p ())
100038fd1498Szrj context->edit_context_ptr->add_fixits (diagnostic->richloc);
100138fd1498Szrj
100238fd1498Szrj context->lock--;
100338fd1498Szrj
100438fd1498Szrj return true;
100538fd1498Szrj }
100638fd1498Szrj
100738fd1498Szrj /* Given a partial pathname as input, return another pathname that
100838fd1498Szrj shares no directory elements with the pathname of __FILE__. This
100938fd1498Szrj is used by fancy_abort() to print `Internal compiler error in expr.c'
101038fd1498Szrj instead of `Internal compiler error in ../../GCC/gcc/expr.c'. */
101138fd1498Szrj
101238fd1498Szrj const char *
trim_filename(const char * name)101338fd1498Szrj trim_filename (const char *name)
101438fd1498Szrj {
101538fd1498Szrj static const char this_file[] = __FILE__;
101638fd1498Szrj const char *p = name, *q = this_file;
101738fd1498Szrj
101838fd1498Szrj /* First skip any "../" in each filename. This allows us to give a proper
101938fd1498Szrj reference to a file in a subdirectory. */
102038fd1498Szrj while (p[0] == '.' && p[1] == '.' && IS_DIR_SEPARATOR (p[2]))
102138fd1498Szrj p += 3;
102238fd1498Szrj
102338fd1498Szrj while (q[0] == '.' && q[1] == '.' && IS_DIR_SEPARATOR (q[2]))
102438fd1498Szrj q += 3;
102538fd1498Szrj
102638fd1498Szrj /* Now skip any parts the two filenames have in common. */
102738fd1498Szrj while (*p == *q && *p != 0 && *q != 0)
102838fd1498Szrj p++, q++;
102938fd1498Szrj
103038fd1498Szrj /* Now go backwards until the previous directory separator. */
103138fd1498Szrj while (p > name && !IS_DIR_SEPARATOR (p[-1]))
103238fd1498Szrj p--;
103338fd1498Szrj
103438fd1498Szrj return p;
103538fd1498Szrj }
103638fd1498Szrj
103738fd1498Szrj /* Standard error reporting routines in increasing order of severity.
103838fd1498Szrj All of these take arguments like printf. */
103938fd1498Szrj
104038fd1498Szrj /* Text to be emitted verbatim to the error message stream; this
104138fd1498Szrj produces no prefix and disables line-wrapping. Use rarely. */
104238fd1498Szrj void
verbatim(const char * gmsgid,...)104338fd1498Szrj verbatim (const char *gmsgid, ...)
104438fd1498Szrj {
104538fd1498Szrj text_info text;
104638fd1498Szrj va_list ap;
104738fd1498Szrj
104838fd1498Szrj va_start (ap, gmsgid);
104938fd1498Szrj text.err_no = errno;
105038fd1498Szrj text.args_ptr = ≈
105138fd1498Szrj text.format_spec = _(gmsgid);
105238fd1498Szrj text.x_data = NULL;
105338fd1498Szrj pp_format_verbatim (global_dc->printer, &text);
105438fd1498Szrj pp_newline_and_flush (global_dc->printer);
105538fd1498Szrj va_end (ap);
105638fd1498Szrj }
105738fd1498Szrj
105838fd1498Szrj /* Add a note with text GMSGID and with LOCATION to the diagnostic CONTEXT. */
105938fd1498Szrj void
diagnostic_append_note(diagnostic_context * context,location_t location,const char * gmsgid,...)106038fd1498Szrj diagnostic_append_note (diagnostic_context *context,
106138fd1498Szrj location_t location,
106238fd1498Szrj const char * gmsgid, ...)
106338fd1498Szrj {
106438fd1498Szrj diagnostic_info diagnostic;
106538fd1498Szrj va_list ap;
106638fd1498Szrj rich_location richloc (line_table, location);
106738fd1498Szrj
106838fd1498Szrj va_start (ap, gmsgid);
106938fd1498Szrj diagnostic_set_info (&diagnostic, gmsgid, &ap, &richloc, DK_NOTE);
107038fd1498Szrj if (context->inhibit_notes_p)
107138fd1498Szrj {
107238fd1498Szrj va_end (ap);
107338fd1498Szrj return;
107438fd1498Szrj }
1075*58e805e6Szrj char *saved_prefix = pp_take_prefix (context->printer);
107638fd1498Szrj pp_set_prefix (context->printer,
107738fd1498Szrj diagnostic_build_prefix (context, &diagnostic));
107838fd1498Szrj pp_format (context->printer, &diagnostic.message);
107938fd1498Szrj pp_output_formatted_text (context->printer);
108038fd1498Szrj pp_destroy_prefix (context->printer);
108138fd1498Szrj pp_set_prefix (context->printer, saved_prefix);
108238fd1498Szrj diagnostic_show_locus (context, &richloc, DK_NOTE);
108338fd1498Szrj va_end (ap);
108438fd1498Szrj }
108538fd1498Szrj
108638fd1498Szrj /* Implement emit_diagnostic, inform, warning, warning_at, pedwarn,
108738fd1498Szrj permerror, error, error_at, error_at, sorry, fatal_error, internal_error,
108838fd1498Szrj and internal_error_no_backtrace, as documented and defined below. */
108938fd1498Szrj static bool
diagnostic_impl(rich_location * richloc,int opt,const char * gmsgid,va_list * ap,diagnostic_t kind)109038fd1498Szrj diagnostic_impl (rich_location *richloc, int opt,
109138fd1498Szrj const char *gmsgid,
109238fd1498Szrj va_list *ap, diagnostic_t kind)
109338fd1498Szrj {
109438fd1498Szrj diagnostic_info diagnostic;
109538fd1498Szrj if (kind == DK_PERMERROR)
109638fd1498Szrj {
109738fd1498Szrj diagnostic_set_info (&diagnostic, gmsgid, ap, richloc,
109838fd1498Szrj permissive_error_kind (global_dc));
109938fd1498Szrj diagnostic.option_index = permissive_error_option (global_dc);
110038fd1498Szrj }
110138fd1498Szrj else
110238fd1498Szrj {
110338fd1498Szrj diagnostic_set_info (&diagnostic, gmsgid, ap, richloc, kind);
110438fd1498Szrj if (kind == DK_WARNING || kind == DK_PEDWARN)
110538fd1498Szrj diagnostic.option_index = opt;
110638fd1498Szrj }
110738fd1498Szrj return diagnostic_report_diagnostic (global_dc, &diagnostic);
110838fd1498Szrj }
110938fd1498Szrj
111038fd1498Szrj /* Implement inform_n, warning_n, and error_n, as documented and
111138fd1498Szrj defined below. */
111238fd1498Szrj static bool
diagnostic_n_impl(rich_location * richloc,int opt,unsigned HOST_WIDE_INT n,const char * singular_gmsgid,const char * plural_gmsgid,va_list * ap,diagnostic_t kind)111338fd1498Szrj diagnostic_n_impl (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
111438fd1498Szrj const char *singular_gmsgid,
111538fd1498Szrj const char *plural_gmsgid,
111638fd1498Szrj va_list *ap, diagnostic_t kind)
111738fd1498Szrj {
111838fd1498Szrj diagnostic_info diagnostic;
111938fd1498Szrj unsigned long gtn;
112038fd1498Szrj
112138fd1498Szrj if (sizeof n <= sizeof gtn)
112238fd1498Szrj gtn = n;
112338fd1498Szrj else
112438fd1498Szrj /* Use the largest number ngettext can handle, otherwise
112538fd1498Szrj preserve the six least significant decimal digits for
112638fd1498Szrj languages where the plural form depends on them. */
112738fd1498Szrj gtn = n <= ULONG_MAX ? n : n % 1000000LU + 1000000LU;
112838fd1498Szrj
112938fd1498Szrj const char *text = ngettext (singular_gmsgid, plural_gmsgid, gtn);
113038fd1498Szrj diagnostic_set_info_translated (&diagnostic, text, ap, richloc, kind);
113138fd1498Szrj if (kind == DK_WARNING)
113238fd1498Szrj diagnostic.option_index = opt;
113338fd1498Szrj return diagnostic_report_diagnostic (global_dc, &diagnostic);
113438fd1498Szrj }
113538fd1498Szrj
113638fd1498Szrj /* Wrapper around diagnostic_impl taking a variable argument list. */
113738fd1498Szrj
113838fd1498Szrj bool
emit_diagnostic(diagnostic_t kind,location_t location,int opt,const char * gmsgid,...)113938fd1498Szrj emit_diagnostic (diagnostic_t kind, location_t location, int opt,
114038fd1498Szrj const char *gmsgid, ...)
114138fd1498Szrj {
114238fd1498Szrj va_list ap;
114338fd1498Szrj va_start (ap, gmsgid);
114438fd1498Szrj rich_location richloc (line_table, location);
114538fd1498Szrj bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, kind);
114638fd1498Szrj va_end (ap);
114738fd1498Szrj return ret;
114838fd1498Szrj }
114938fd1498Szrj
115038fd1498Szrj /* Wrapper around diagnostic_impl taking a va_list parameter. */
115138fd1498Szrj
115238fd1498Szrj bool
emit_diagnostic_valist(diagnostic_t kind,location_t location,int opt,const char * gmsgid,va_list * ap)115338fd1498Szrj emit_diagnostic_valist (diagnostic_t kind, location_t location, int opt,
115438fd1498Szrj const char *gmsgid, va_list *ap)
115538fd1498Szrj {
115638fd1498Szrj rich_location richloc (line_table, location);
115738fd1498Szrj return diagnostic_impl (&richloc, opt, gmsgid, ap, kind);
115838fd1498Szrj }
115938fd1498Szrj
116038fd1498Szrj /* An informative note at LOCATION. Use this for additional details on an error
116138fd1498Szrj message. */
116238fd1498Szrj void
inform(location_t location,const char * gmsgid,...)116338fd1498Szrj inform (location_t location, const char *gmsgid, ...)
116438fd1498Szrj {
116538fd1498Szrj va_list ap;
116638fd1498Szrj va_start (ap, gmsgid);
116738fd1498Szrj rich_location richloc (line_table, location);
116838fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_NOTE);
116938fd1498Szrj va_end (ap);
117038fd1498Szrj }
117138fd1498Szrj
117238fd1498Szrj /* Same as "inform" above, but at RICHLOC. */
117338fd1498Szrj void
inform(rich_location * richloc,const char * gmsgid,...)117438fd1498Szrj inform (rich_location *richloc, const char *gmsgid, ...)
117538fd1498Szrj {
117638fd1498Szrj gcc_assert (richloc);
117738fd1498Szrj
117838fd1498Szrj va_list ap;
117938fd1498Szrj va_start (ap, gmsgid);
118038fd1498Szrj diagnostic_impl (richloc, -1, gmsgid, &ap, DK_NOTE);
118138fd1498Szrj va_end (ap);
118238fd1498Szrj }
118338fd1498Szrj
118438fd1498Szrj /* An informative note at LOCATION. Use this for additional details on an
118538fd1498Szrj error message. */
118638fd1498Szrj void
inform_n(location_t location,unsigned HOST_WIDE_INT n,const char * singular_gmsgid,const char * plural_gmsgid,...)118738fd1498Szrj inform_n (location_t location, unsigned HOST_WIDE_INT n,
118838fd1498Szrj const char *singular_gmsgid, const char *plural_gmsgid, ...)
118938fd1498Szrj {
119038fd1498Szrj va_list ap;
119138fd1498Szrj va_start (ap, plural_gmsgid);
119238fd1498Szrj rich_location richloc (line_table, location);
119338fd1498Szrj diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
119438fd1498Szrj &ap, DK_NOTE);
119538fd1498Szrj va_end (ap);
119638fd1498Szrj }
119738fd1498Szrj
119838fd1498Szrj /* A warning at INPUT_LOCATION. Use this for code which is correct according
119938fd1498Szrj to the relevant language specification but is likely to be buggy anyway.
120038fd1498Szrj Returns true if the warning was printed, false if it was inhibited. */
120138fd1498Szrj bool
warning(int opt,const char * gmsgid,...)120238fd1498Szrj warning (int opt, const char *gmsgid, ...)
120338fd1498Szrj {
120438fd1498Szrj va_list ap;
120538fd1498Szrj va_start (ap, gmsgid);
120638fd1498Szrj rich_location richloc (line_table, input_location);
120738fd1498Szrj bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_WARNING);
120838fd1498Szrj va_end (ap);
120938fd1498Szrj return ret;
121038fd1498Szrj }
121138fd1498Szrj
121238fd1498Szrj /* A warning at LOCATION. Use this for code which is correct according to the
121338fd1498Szrj relevant language specification but is likely to be buggy anyway.
121438fd1498Szrj Returns true if the warning was printed, false if it was inhibited. */
121538fd1498Szrj
121638fd1498Szrj bool
warning_at(location_t location,int opt,const char * gmsgid,...)121738fd1498Szrj warning_at (location_t location, int opt, const char *gmsgid, ...)
121838fd1498Szrj {
121938fd1498Szrj va_list ap;
122038fd1498Szrj va_start (ap, gmsgid);
122138fd1498Szrj rich_location richloc (line_table, location);
122238fd1498Szrj bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_WARNING);
122338fd1498Szrj va_end (ap);
122438fd1498Szrj return ret;
122538fd1498Szrj }
122638fd1498Szrj
122738fd1498Szrj /* Same as "warning at" above, but using RICHLOC. */
122838fd1498Szrj
122938fd1498Szrj bool
warning_at(rich_location * richloc,int opt,const char * gmsgid,...)123038fd1498Szrj warning_at (rich_location *richloc, int opt, const char *gmsgid, ...)
123138fd1498Szrj {
123238fd1498Szrj gcc_assert (richloc);
123338fd1498Szrj
123438fd1498Szrj va_list ap;
123538fd1498Szrj va_start (ap, gmsgid);
123638fd1498Szrj bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_WARNING);
123738fd1498Szrj va_end (ap);
123838fd1498Szrj return ret;
123938fd1498Szrj }
124038fd1498Szrj
124138fd1498Szrj /* Same as warning_n plural variant below, but using RICHLOC. */
124238fd1498Szrj
124338fd1498Szrj bool
warning_n(rich_location * richloc,int opt,unsigned HOST_WIDE_INT n,const char * singular_gmsgid,const char * plural_gmsgid,...)124438fd1498Szrj warning_n (rich_location *richloc, int opt, unsigned HOST_WIDE_INT n,
124538fd1498Szrj const char *singular_gmsgid, const char *plural_gmsgid, ...)
124638fd1498Szrj {
124738fd1498Szrj gcc_assert (richloc);
124838fd1498Szrj
124938fd1498Szrj va_list ap;
125038fd1498Szrj va_start (ap, plural_gmsgid);
125138fd1498Szrj bool ret = diagnostic_n_impl (richloc, opt, n,
125238fd1498Szrj singular_gmsgid, plural_gmsgid,
125338fd1498Szrj &ap, DK_WARNING);
125438fd1498Szrj va_end (ap);
125538fd1498Szrj return ret;
125638fd1498Szrj }
125738fd1498Szrj
125838fd1498Szrj /* A warning at LOCATION. Use this for code which is correct according to the
125938fd1498Szrj relevant language specification but is likely to be buggy anyway.
126038fd1498Szrj Returns true if the warning was printed, false if it was inhibited. */
126138fd1498Szrj
126238fd1498Szrj bool
warning_n(location_t location,int opt,unsigned HOST_WIDE_INT n,const char * singular_gmsgid,const char * plural_gmsgid,...)126338fd1498Szrj warning_n (location_t location, int opt, unsigned HOST_WIDE_INT n,
126438fd1498Szrj const char *singular_gmsgid, const char *plural_gmsgid, ...)
126538fd1498Szrj {
126638fd1498Szrj va_list ap;
126738fd1498Szrj va_start (ap, plural_gmsgid);
126838fd1498Szrj rich_location richloc (line_table, location);
126938fd1498Szrj bool ret = diagnostic_n_impl (&richloc, opt, n,
127038fd1498Szrj singular_gmsgid, plural_gmsgid,
127138fd1498Szrj &ap, DK_WARNING);
127238fd1498Szrj va_end (ap);
127338fd1498Szrj return ret;
127438fd1498Szrj }
127538fd1498Szrj
127638fd1498Szrj /* A "pedantic" warning at LOCATION: issues a warning unless
127738fd1498Szrj -pedantic-errors was given on the command line, in which case it
127838fd1498Szrj issues an error. Use this for diagnostics required by the relevant
127938fd1498Szrj language standard, if you have chosen not to make them errors.
128038fd1498Szrj
128138fd1498Szrj Note that these diagnostics are issued independent of the setting
128238fd1498Szrj of the -Wpedantic command-line switch. To get a warning enabled
128338fd1498Szrj only with that switch, use either "if (pedantic) pedwarn
128438fd1498Szrj (OPT_Wpedantic,...)" or just "pedwarn (OPT_Wpedantic,..)". To get a
128538fd1498Szrj pedwarn independently of the -Wpedantic switch use "pedwarn (0,...)".
128638fd1498Szrj
128738fd1498Szrj Returns true if the warning was printed, false if it was inhibited. */
128838fd1498Szrj
128938fd1498Szrj bool
pedwarn(location_t location,int opt,const char * gmsgid,...)129038fd1498Szrj pedwarn (location_t location, int opt, const char *gmsgid, ...)
129138fd1498Szrj {
129238fd1498Szrj va_list ap;
129338fd1498Szrj va_start (ap, gmsgid);
129438fd1498Szrj rich_location richloc (line_table, location);
129538fd1498Szrj bool ret = diagnostic_impl (&richloc, opt, gmsgid, &ap, DK_PEDWARN);
129638fd1498Szrj va_end (ap);
129738fd1498Szrj return ret;
129838fd1498Szrj }
129938fd1498Szrj
130038fd1498Szrj /* Same as pedwarn above, but using RICHLOC. */
130138fd1498Szrj
130238fd1498Szrj bool
pedwarn(rich_location * richloc,int opt,const char * gmsgid,...)130338fd1498Szrj pedwarn (rich_location *richloc, int opt, const char *gmsgid, ...)
130438fd1498Szrj {
130538fd1498Szrj gcc_assert (richloc);
130638fd1498Szrj
130738fd1498Szrj va_list ap;
130838fd1498Szrj va_start (ap, gmsgid);
130938fd1498Szrj bool ret = diagnostic_impl (richloc, opt, gmsgid, &ap, DK_PEDWARN);
131038fd1498Szrj va_end (ap);
131138fd1498Szrj return ret;
131238fd1498Szrj }
131338fd1498Szrj
131438fd1498Szrj /* A "permissive" error at LOCATION: issues an error unless
131538fd1498Szrj -fpermissive was given on the command line, in which case it issues
131638fd1498Szrj a warning. Use this for things that really should be errors but we
131738fd1498Szrj want to support legacy code.
131838fd1498Szrj
131938fd1498Szrj Returns true if the warning was printed, false if it was inhibited. */
132038fd1498Szrj
132138fd1498Szrj bool
permerror(location_t location,const char * gmsgid,...)132238fd1498Szrj permerror (location_t location, const char *gmsgid, ...)
132338fd1498Szrj {
132438fd1498Szrj va_list ap;
132538fd1498Szrj va_start (ap, gmsgid);
132638fd1498Szrj rich_location richloc (line_table, location);
132738fd1498Szrj bool ret = diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_PERMERROR);
132838fd1498Szrj va_end (ap);
132938fd1498Szrj return ret;
133038fd1498Szrj }
133138fd1498Szrj
133238fd1498Szrj /* Same as "permerror" above, but at RICHLOC. */
133338fd1498Szrj
133438fd1498Szrj bool
permerror(rich_location * richloc,const char * gmsgid,...)133538fd1498Szrj permerror (rich_location *richloc, const char *gmsgid, ...)
133638fd1498Szrj {
133738fd1498Szrj gcc_assert (richloc);
133838fd1498Szrj
133938fd1498Szrj va_list ap;
134038fd1498Szrj va_start (ap, gmsgid);
134138fd1498Szrj bool ret = diagnostic_impl (richloc, -1, gmsgid, &ap, DK_PERMERROR);
134238fd1498Szrj va_end (ap);
134338fd1498Szrj return ret;
134438fd1498Szrj }
134538fd1498Szrj
134638fd1498Szrj /* A hard error: the code is definitely ill-formed, and an object file
134738fd1498Szrj will not be produced. */
134838fd1498Szrj void
error(const char * gmsgid,...)134938fd1498Szrj error (const char *gmsgid, ...)
135038fd1498Szrj {
135138fd1498Szrj va_list ap;
135238fd1498Szrj va_start (ap, gmsgid);
135338fd1498Szrj rich_location richloc (line_table, input_location);
135438fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
135538fd1498Szrj va_end (ap);
135638fd1498Szrj }
135738fd1498Szrj
135838fd1498Szrj /* A hard error: the code is definitely ill-formed, and an object file
135938fd1498Szrj will not be produced. */
136038fd1498Szrj void
error_n(location_t location,unsigned HOST_WIDE_INT n,const char * singular_gmsgid,const char * plural_gmsgid,...)136138fd1498Szrj error_n (location_t location, unsigned HOST_WIDE_INT n,
136238fd1498Szrj const char *singular_gmsgid, const char *plural_gmsgid, ...)
136338fd1498Szrj {
136438fd1498Szrj va_list ap;
136538fd1498Szrj va_start (ap, plural_gmsgid);
136638fd1498Szrj rich_location richloc (line_table, location);
136738fd1498Szrj diagnostic_n_impl (&richloc, -1, n, singular_gmsgid, plural_gmsgid,
136838fd1498Szrj &ap, DK_ERROR);
136938fd1498Szrj va_end (ap);
137038fd1498Szrj }
137138fd1498Szrj
137238fd1498Szrj /* Same as above, but use location LOC instead of input_location. */
137338fd1498Szrj void
error_at(location_t loc,const char * gmsgid,...)137438fd1498Szrj error_at (location_t loc, const char *gmsgid, ...)
137538fd1498Szrj {
137638fd1498Szrj va_list ap;
137738fd1498Szrj va_start (ap, gmsgid);
137838fd1498Szrj rich_location richloc (line_table, loc);
137938fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ERROR);
138038fd1498Szrj va_end (ap);
138138fd1498Szrj }
138238fd1498Szrj
138338fd1498Szrj /* Same as above, but use RICH_LOC. */
138438fd1498Szrj
138538fd1498Szrj void
error_at(rich_location * richloc,const char * gmsgid,...)138638fd1498Szrj error_at (rich_location *richloc, const char *gmsgid, ...)
138738fd1498Szrj {
138838fd1498Szrj gcc_assert (richloc);
138938fd1498Szrj
139038fd1498Szrj va_list ap;
139138fd1498Szrj va_start (ap, gmsgid);
139238fd1498Szrj diagnostic_impl (richloc, -1, gmsgid, &ap, DK_ERROR);
139338fd1498Szrj va_end (ap);
139438fd1498Szrj }
139538fd1498Szrj
139638fd1498Szrj /* "Sorry, not implemented." Use for a language feature which is
139738fd1498Szrj required by the relevant specification but not implemented by GCC.
139838fd1498Szrj An object file will not be produced. */
139938fd1498Szrj void
sorry(const char * gmsgid,...)140038fd1498Szrj sorry (const char *gmsgid, ...)
140138fd1498Szrj {
140238fd1498Szrj va_list ap;
140338fd1498Szrj va_start (ap, gmsgid);
140438fd1498Szrj rich_location richloc (line_table, input_location);
140538fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_SORRY);
140638fd1498Szrj va_end (ap);
140738fd1498Szrj }
140838fd1498Szrj
140938fd1498Szrj /* Return true if an error or a "sorry" has been seen. Various
141038fd1498Szrj processing is disabled after errors. */
141138fd1498Szrj bool
seen_error(void)141238fd1498Szrj seen_error (void)
141338fd1498Szrj {
141438fd1498Szrj return errorcount || sorrycount;
141538fd1498Szrj }
141638fd1498Szrj
141738fd1498Szrj /* An error which is severe enough that we make no attempt to
141838fd1498Szrj continue. Do not use this for internal consistency checks; that's
141938fd1498Szrj internal_error. Use of this function should be rare. */
142038fd1498Szrj void
fatal_error(location_t loc,const char * gmsgid,...)142138fd1498Szrj fatal_error (location_t loc, const char *gmsgid, ...)
142238fd1498Szrj {
142338fd1498Szrj va_list ap;
142438fd1498Szrj va_start (ap, gmsgid);
142538fd1498Szrj rich_location richloc (line_table, loc);
142638fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_FATAL);
142738fd1498Szrj va_end (ap);
142838fd1498Szrj
142938fd1498Szrj gcc_unreachable ();
143038fd1498Szrj }
143138fd1498Szrj
143238fd1498Szrj /* An internal consistency check has failed. We make no attempt to
143338fd1498Szrj continue. Note that unless there is debugging value to be had from
143438fd1498Szrj a more specific message, or some other good reason, you should use
143538fd1498Szrj abort () instead of calling this function directly. */
143638fd1498Szrj void
internal_error(const char * gmsgid,...)143738fd1498Szrj internal_error (const char *gmsgid, ...)
143838fd1498Szrj {
143938fd1498Szrj va_list ap;
144038fd1498Szrj va_start (ap, gmsgid);
144138fd1498Szrj rich_location richloc (line_table, input_location);
144238fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE);
144338fd1498Szrj va_end (ap);
144438fd1498Szrj
144538fd1498Szrj gcc_unreachable ();
144638fd1498Szrj }
144738fd1498Szrj
144838fd1498Szrj /* Like internal_error, but no backtrace will be printed. Used when
144938fd1498Szrj the internal error does not happen at the current location, but happened
145038fd1498Szrj somewhere else. */
145138fd1498Szrj void
internal_error_no_backtrace(const char * gmsgid,...)145238fd1498Szrj internal_error_no_backtrace (const char *gmsgid, ...)
145338fd1498Szrj {
145438fd1498Szrj va_list ap;
145538fd1498Szrj va_start (ap, gmsgid);
145638fd1498Szrj rich_location richloc (line_table, input_location);
145738fd1498Szrj diagnostic_impl (&richloc, -1, gmsgid, &ap, DK_ICE_NOBT);
145838fd1498Szrj va_end (ap);
145938fd1498Szrj
146038fd1498Szrj gcc_unreachable ();
146138fd1498Szrj }
146238fd1498Szrj
146338fd1498Szrj /* Special case error functions. Most are implemented in terms of the
146438fd1498Szrj above, or should be. */
146538fd1498Szrj
146638fd1498Szrj /* Print a diagnostic MSGID on FILE. This is just fprintf, except it
146738fd1498Szrj runs its second argument through gettext. */
146838fd1498Szrj void
fnotice(FILE * file,const char * cmsgid,...)146938fd1498Szrj fnotice (FILE *file, const char *cmsgid, ...)
147038fd1498Szrj {
147138fd1498Szrj va_list ap;
147238fd1498Szrj
147338fd1498Szrj va_start (ap, cmsgid);
147438fd1498Szrj vfprintf (file, _(cmsgid), ap);
147538fd1498Szrj va_end (ap);
147638fd1498Szrj }
147738fd1498Szrj
147838fd1498Szrj /* Inform the user that an error occurred while trying to report some
147938fd1498Szrj other error. This indicates catastrophic internal inconsistencies,
148038fd1498Szrj so give up now. But do try to flush out the previous error.
148138fd1498Szrj This mustn't use internal_error, that will cause infinite recursion. */
148238fd1498Szrj
148338fd1498Szrj static void
error_recursion(diagnostic_context * context)148438fd1498Szrj error_recursion (diagnostic_context *context)
148538fd1498Szrj {
148638fd1498Szrj if (context->lock < 3)
148738fd1498Szrj pp_newline_and_flush (context->printer);
148838fd1498Szrj
148938fd1498Szrj fnotice (stderr,
149038fd1498Szrj "Internal compiler error: Error reporting routines re-entered.\n");
149138fd1498Szrj
149238fd1498Szrj /* Call diagnostic_action_after_output to get the "please submit a bug
149338fd1498Szrj report" message. */
149438fd1498Szrj diagnostic_action_after_output (context, DK_ICE);
149538fd1498Szrj
149638fd1498Szrj /* Do not use gcc_unreachable here; that goes through internal_error
149738fd1498Szrj and therefore would cause infinite recursion. */
149838fd1498Szrj real_abort ();
149938fd1498Szrj }
150038fd1498Szrj
150138fd1498Szrj /* Report an internal compiler error in a friendly manner. This is
150238fd1498Szrj the function that gets called upon use of abort() in the source
150338fd1498Szrj code generally, thanks to a special macro. */
150438fd1498Szrj
150538fd1498Szrj void
fancy_abort(const char * file,int line,const char * function)150638fd1498Szrj fancy_abort (const char *file, int line, const char *function)
150738fd1498Szrj {
150838fd1498Szrj internal_error ("in %s, at %s:%d", function, trim_filename (file), line);
150938fd1498Szrj }
151038fd1498Szrj
151138fd1498Szrj /* Really call the system 'abort'. This has to go right at the end of
151238fd1498Szrj this file, so that there are no functions after it that call abort
151338fd1498Szrj and get the system abort instead of our macro. */
151438fd1498Szrj #undef abort
151538fd1498Szrj static void
real_abort(void)151638fd1498Szrj real_abort (void)
151738fd1498Szrj {
151838fd1498Szrj abort ();
151938fd1498Szrj }
152038fd1498Szrj
152138fd1498Szrj #if CHECKING_P
152238fd1498Szrj
152338fd1498Szrj namespace selftest {
152438fd1498Szrj
152538fd1498Szrj /* Helper function for test_print_escaped_string. */
152638fd1498Szrj
152738fd1498Szrj static void
assert_print_escaped_string(const location & loc,const char * expected_output,const char * input)152838fd1498Szrj assert_print_escaped_string (const location &loc, const char *expected_output,
152938fd1498Szrj const char *input)
153038fd1498Szrj {
153138fd1498Szrj pretty_printer pp;
153238fd1498Szrj print_escaped_string (&pp, input);
153338fd1498Szrj ASSERT_STREQ_AT (loc, expected_output, pp_formatted_text (&pp));
153438fd1498Szrj }
153538fd1498Szrj
153638fd1498Szrj #define ASSERT_PRINT_ESCAPED_STRING_STREQ(EXPECTED_OUTPUT, INPUT) \
153738fd1498Szrj assert_print_escaped_string (SELFTEST_LOCATION, EXPECTED_OUTPUT, INPUT)
153838fd1498Szrj
153938fd1498Szrj /* Tests of print_escaped_string. */
154038fd1498Szrj
154138fd1498Szrj static void
test_print_escaped_string()154238fd1498Szrj test_print_escaped_string ()
154338fd1498Szrj {
154438fd1498Szrj /* Empty string. */
154538fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"\"", "");
154638fd1498Szrj
154738fd1498Szrj /* Non-empty string. */
154838fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"hello world\"", "hello world");
154938fd1498Szrj
155038fd1498Szrj /* Various things that need to be escaped: */
155138fd1498Szrj /* Backslash. */
155238fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\\after\"",
155338fd1498Szrj "before\\after");
155438fd1498Szrj /* Tab. */
155538fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\tafter\"",
155638fd1498Szrj "before\tafter");
155738fd1498Szrj /* Newline. */
155838fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\nafter\"",
155938fd1498Szrj "before\nafter");
156038fd1498Szrj /* Double quote. */
156138fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\\"after\"",
156238fd1498Szrj "before\"after");
156338fd1498Szrj
156438fd1498Szrj /* Non-printable characters: BEL: '\a': 0x07 */
156538fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\007after\"",
156638fd1498Szrj "before\aafter");
156738fd1498Szrj /* Non-printable characters: vertical tab: '\v': 0x0b */
156838fd1498Szrj ASSERT_PRINT_ESCAPED_STRING_STREQ ("\"before\\013after\"",
156938fd1498Szrj "before\vafter");
157038fd1498Szrj }
157138fd1498Szrj
157238fd1498Szrj /* Tests of print_parseable_fixits. */
157338fd1498Szrj
157438fd1498Szrj /* Verify that print_parseable_fixits emits the empty string if there
157538fd1498Szrj are no fixits. */
157638fd1498Szrj
157738fd1498Szrj static void
test_print_parseable_fixits_none()157838fd1498Szrj test_print_parseable_fixits_none ()
157938fd1498Szrj {
158038fd1498Szrj pretty_printer pp;
158138fd1498Szrj rich_location richloc (line_table, UNKNOWN_LOCATION);
158238fd1498Szrj
158338fd1498Szrj print_parseable_fixits (&pp, &richloc);
158438fd1498Szrj ASSERT_STREQ ("", pp_formatted_text (&pp));
158538fd1498Szrj }
158638fd1498Szrj
158738fd1498Szrj /* Verify that print_parseable_fixits does the right thing if there
158838fd1498Szrj is an insertion fixit hint. */
158938fd1498Szrj
159038fd1498Szrj static void
test_print_parseable_fixits_insert()159138fd1498Szrj test_print_parseable_fixits_insert ()
159238fd1498Szrj {
159338fd1498Szrj pretty_printer pp;
159438fd1498Szrj rich_location richloc (line_table, UNKNOWN_LOCATION);
159538fd1498Szrj
159638fd1498Szrj linemap_add (line_table, LC_ENTER, false, "test.c", 0);
159738fd1498Szrj linemap_line_start (line_table, 5, 100);
159838fd1498Szrj linemap_add (line_table, LC_LEAVE, false, NULL, 0);
159938fd1498Szrj location_t where = linemap_position_for_column (line_table, 10);
160038fd1498Szrj richloc.add_fixit_insert_before (where, "added content");
160138fd1498Szrj
160238fd1498Szrj print_parseable_fixits (&pp, &richloc);
160338fd1498Szrj ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:10}:\"added content\"\n",
160438fd1498Szrj pp_formatted_text (&pp));
160538fd1498Szrj }
160638fd1498Szrj
160738fd1498Szrj /* Verify that print_parseable_fixits does the right thing if there
160838fd1498Szrj is an removal fixit hint. */
160938fd1498Szrj
161038fd1498Szrj static void
test_print_parseable_fixits_remove()161138fd1498Szrj test_print_parseable_fixits_remove ()
161238fd1498Szrj {
161338fd1498Szrj pretty_printer pp;
161438fd1498Szrj rich_location richloc (line_table, UNKNOWN_LOCATION);
161538fd1498Szrj
161638fd1498Szrj linemap_add (line_table, LC_ENTER, false, "test.c", 0);
161738fd1498Szrj linemap_line_start (line_table, 5, 100);
161838fd1498Szrj linemap_add (line_table, LC_LEAVE, false, NULL, 0);
161938fd1498Szrj source_range where;
162038fd1498Szrj where.m_start = linemap_position_for_column (line_table, 10);
162138fd1498Szrj where.m_finish = linemap_position_for_column (line_table, 20);
162238fd1498Szrj richloc.add_fixit_remove (where);
162338fd1498Szrj
162438fd1498Szrj print_parseable_fixits (&pp, &richloc);
162538fd1498Szrj ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"\"\n",
162638fd1498Szrj pp_formatted_text (&pp));
162738fd1498Szrj }
162838fd1498Szrj
162938fd1498Szrj /* Verify that print_parseable_fixits does the right thing if there
163038fd1498Szrj is an replacement fixit hint. */
163138fd1498Szrj
163238fd1498Szrj static void
test_print_parseable_fixits_replace()163338fd1498Szrj test_print_parseable_fixits_replace ()
163438fd1498Szrj {
163538fd1498Szrj pretty_printer pp;
163638fd1498Szrj rich_location richloc (line_table, UNKNOWN_LOCATION);
163738fd1498Szrj
163838fd1498Szrj linemap_add (line_table, LC_ENTER, false, "test.c", 0);
163938fd1498Szrj linemap_line_start (line_table, 5, 100);
164038fd1498Szrj linemap_add (line_table, LC_LEAVE, false, NULL, 0);
164138fd1498Szrj source_range where;
164238fd1498Szrj where.m_start = linemap_position_for_column (line_table, 10);
164338fd1498Szrj where.m_finish = linemap_position_for_column (line_table, 20);
164438fd1498Szrj richloc.add_fixit_replace (where, "replacement");
164538fd1498Szrj
164638fd1498Szrj print_parseable_fixits (&pp, &richloc);
164738fd1498Szrj ASSERT_STREQ ("fix-it:\"test.c\":{5:10-5:21}:\"replacement\"\n",
164838fd1498Szrj pp_formatted_text (&pp));
164938fd1498Szrj }
165038fd1498Szrj
165138fd1498Szrj /* Verify that
165238fd1498Szrj diagnostic_get_location_text (..., SHOW_COLUMN)
165338fd1498Szrj generates EXPECTED_LOC_TEXT, given FILENAME, LINE, COLUMN, with
165438fd1498Szrj colorization disabled. */
165538fd1498Szrj
165638fd1498Szrj static void
assert_location_text(const char * expected_loc_text,const char * filename,int line,int column,bool show_column)165738fd1498Szrj assert_location_text (const char *expected_loc_text,
165838fd1498Szrj const char *filename, int line, int column,
165938fd1498Szrj bool show_column)
166038fd1498Szrj {
166138fd1498Szrj test_diagnostic_context dc;
166238fd1498Szrj dc.show_column = show_column;
166338fd1498Szrj
166438fd1498Szrj expanded_location xloc;
166538fd1498Szrj xloc.file = filename;
166638fd1498Szrj xloc.line = line;
166738fd1498Szrj xloc.column = column;
166838fd1498Szrj xloc.data = NULL;
166938fd1498Szrj xloc.sysp = false;
167038fd1498Szrj
167138fd1498Szrj char *actual_loc_text = diagnostic_get_location_text (&dc, xloc);
167238fd1498Szrj ASSERT_STREQ (expected_loc_text, actual_loc_text);
167338fd1498Szrj free (actual_loc_text);
167438fd1498Szrj }
167538fd1498Szrj
167638fd1498Szrj /* Verify that diagnostic_get_location_text works as expected. */
167738fd1498Szrj
167838fd1498Szrj static void
test_diagnostic_get_location_text()167938fd1498Szrj test_diagnostic_get_location_text ()
168038fd1498Szrj {
168138fd1498Szrj const char *old_progname = progname;
168238fd1498Szrj progname = "PROGNAME";
168338fd1498Szrj assert_location_text ("PROGNAME:", NULL, 0, 0, true);
168438fd1498Szrj assert_location_text ("<built-in>:", "<built-in>", 42, 10, true);
168538fd1498Szrj assert_location_text ("foo.c:42:10:", "foo.c", 42, 10, true);
168638fd1498Szrj assert_location_text ("foo.c:42:", "foo.c", 42, 0, true);
168738fd1498Szrj assert_location_text ("foo.c:", "foo.c", 0, 10, true);
168838fd1498Szrj assert_location_text ("foo.c:42:", "foo.c", 42, 10, false);
168938fd1498Szrj assert_location_text ("foo.c:", "foo.c", 0, 10, false);
169038fd1498Szrj
169138fd1498Szrj maybe_line_and_column (INT_MAX, INT_MAX);
169238fd1498Szrj maybe_line_and_column (INT_MIN, INT_MIN);
169338fd1498Szrj
169438fd1498Szrj progname = old_progname;
169538fd1498Szrj }
169638fd1498Szrj
169738fd1498Szrj /* Run all of the selftests within this file. */
169838fd1498Szrj
169938fd1498Szrj void
diagnostic_c_tests()170038fd1498Szrj diagnostic_c_tests ()
170138fd1498Szrj {
170238fd1498Szrj test_print_escaped_string ();
170338fd1498Szrj test_print_parseable_fixits_none ();
170438fd1498Szrj test_print_parseable_fixits_insert ();
170538fd1498Szrj test_print_parseable_fixits_remove ();
170638fd1498Szrj test_print_parseable_fixits_replace ();
170738fd1498Szrj test_diagnostic_get_location_text ();
170838fd1498Szrj }
170938fd1498Szrj
171038fd1498Szrj } // namespace selftest
171138fd1498Szrj
171238fd1498Szrj #endif /* #if CHECKING_P */
1713