Update baseline symbols for hppa-linux.
[official-gcc.git] / gcc / d / d-diagnostic.cc
blobe2d51911b1455683f251a9c4b13591ee8ee581e3
1 /* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
2 Copyright (C) 2017-2022 Free Software Foundation, Inc.
4 GCC is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
9 GCC is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GCC; see the file COPYING3. If not see
16 <http://www.gnu.org/licenses/>. */
18 #include "config.h"
19 #include "system.h"
20 #include "coretypes.h"
22 #include "dmd/globals.h"
23 #include "dmd/errors.h"
25 #include "tree.h"
26 #include "options.h"
27 #include "diagnostic.h"
29 #include "d-tree.h"
32 /* Rewrite the format string FORMAT to deal with any format extensions not
33 supported by pp_format().
35 The following format specifiers are handled:
36 `...`: text within backticks gets quoted as '%<...%>'.
37 %-10s: left-justify format flag is removed leaving '%s' remaining.
38 %02x: zero-padding format flag is removed leaving '%x' remaining.
39 %X: uppercase unsigned hexadecimals are rewritten as '%x'. */
41 static char *
42 expand_d_format (const char *format)
44 obstack buf;
45 bool inbacktick = false;
47 gcc_obstack_init (&buf);
49 for (const char *p = format; *p;)
51 while (*p != '\0' && *p != '\\' && *p != '%' && *p != '`')
53 obstack_1grow (&buf, *p);
54 p++;
57 if (*p == '\0')
58 break;
60 if (*p == '\\')
62 if (p[1] == '`')
64 /* Escaped backtick, don't expand it as a quoted string. */
65 obstack_1grow (&buf, '`');
66 p++;;
68 else
69 obstack_1grow (&buf, *p);
71 p++;
72 continue;
75 if (*p == '`')
77 /* Text enclosed by `...` are translated as a quoted string. */
78 if (inbacktick)
80 obstack_grow (&buf, "%>", 2);
81 inbacktick = false;
83 else
85 obstack_grow (&buf, "%<", 2);
86 inbacktick = true;
88 p++;
89 continue;
92 /* Check the conversion specification for unhandled flags. */
93 obstack_1grow (&buf, *p);
94 p++;
96 Lagain:
97 switch (*p)
99 case '\0':
100 /* Malformed format string. */
101 gcc_unreachable ();
103 case '-':
104 /* Remove whitespace formatting. */
105 p++;
106 while (ISDIGIT (*p))
107 p++;
108 goto Lagain;
110 case '0':
111 /* Remove zero padding from format string. */
112 while (ISDIGIT (*p))
113 p++;
114 goto Lagain;
116 case 'X':
117 /* Hex format only supports lower-case. */
118 obstack_1grow (&buf, 'x');
119 p++;
120 break;
122 default:
123 break;
127 gcc_assert (!inbacktick);
128 obstack_1grow (&buf, '\0');
129 return (char *) obstack_finish (&buf);
132 /* Rewrite the format string FORMAT to deal with any characters that require
133 escaping before expand_d_format expands it. */
135 static char *
136 escape_d_format (const char *format)
138 bool quoted = false;
139 size_t format_len = 0;
140 obstack buf;
142 gcc_obstack_init (&buf);
144 /* If the format string is enclosed by two '`' characters, then don't escape
145 the first and last characters. */
146 if (*format == '`')
148 format_len = strlen (format) - 1;
149 if (format_len && format[format_len] == '`')
150 quoted = true;
153 for (const char *p = format; *p; p++)
155 switch (*p)
157 case '%':
158 /* Escape `%' characters so that pp_format does not confuse them
159 for actual format specifiers. */
160 obstack_1grow (&buf, '%');
161 break;
163 case '`':
164 /* Escape '`' characters so that expand_d_format does not confuse them
165 for a quoted string. */
166 if (!quoted || (p != format && p != (format + format_len)))
167 obstack_1grow (&buf, '\\');
168 break;
170 default:
171 break;
174 obstack_1grow (&buf, *p);
177 obstack_1grow (&buf, '\0');
178 return (char *) obstack_finish (&buf);
181 /* Helper routine for all error routines. Reports a diagnostic specified by
182 KIND at the explicit location LOC. The message FORMAT comes from the dmd
183 front-end, which does not get translated by the gcc diagnostic routines. */
185 static void ATTRIBUTE_GCC_DIAG(3,0)
186 d_diagnostic_report_diagnostic (const Loc &loc, int opt, const char *format,
187 va_list ap, diagnostic_t kind, bool verbatim)
189 va_list argp;
190 va_copy (argp, ap);
192 if (loc.filename || !verbatim)
194 rich_location rich_loc (line_table, make_location_t (loc));
195 diagnostic_info diagnostic;
196 char *xformat = expand_d_format (format);
198 diagnostic_set_info_translated (&diagnostic, xformat, &argp,
199 &rich_loc, kind);
200 if (opt != 0)
201 diagnostic.option_index = opt;
203 diagnostic_report_diagnostic (global_dc, &diagnostic);
205 else
207 /* Write verbatim messages with no location direct to stream. */
208 text_info text;
209 text.err_no = errno;
210 text.args_ptr = &argp;
211 text.format_spec = expand_d_format (format);
212 text.x_data = NULL;
214 pp_format_verbatim (global_dc->printer, &text);
215 pp_newline_and_flush (global_dc->printer);
218 va_end (argp);
221 /* Print a hard error message with explicit location LOC with an optional
222 message prefix PREFIX1 and PREFIX2, increasing the global or gagged
223 error count. */
225 void ATTRIBUTE_GCC_DIAG(2,0)
226 verror (const Loc &loc, const char *format, va_list ap,
227 const char *prefix1, const char *prefix2, const char *)
229 if (!global.gag || global.params.showGaggedErrors)
231 char *xformat;
233 /* Build string and emit. */
234 if (prefix2 != NULL)
235 xformat = xasprintf ("%s %s %s", escape_d_format (prefix1),
236 escape_d_format (prefix2), format);
237 else if (prefix1 != NULL)
238 xformat = xasprintf ("%s %s", escape_d_format (prefix1), format);
239 else
240 xformat = xasprintf ("%s", format);
242 d_diagnostic_report_diagnostic (loc, 0, xformat, ap,
243 global.gag ? DK_ANACHRONISM : DK_ERROR,
244 false);
245 free (xformat);
248 if (global.gag)
249 global.gaggedErrors++;
251 global.errors++;
254 /* Print supplementary message about the last error with explicit location LOC.
255 This doesn't increase the global error count. */
257 void ATTRIBUTE_GCC_DIAG(2,0)
258 verrorSupplemental (const Loc &loc, const char *format, va_list ap)
260 if (global.gag && !global.params.showGaggedErrors)
261 return;
263 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
266 /* Print a warning message with explicit location LOC, increasing the
267 global warning count. */
269 void ATTRIBUTE_GCC_DIAG(2,0)
270 vwarning (const Loc &loc, const char *format, va_list ap)
272 if (!global.gag && global.params.warnings != DIAGNOSTICoff)
274 /* Warnings don't count if not treated as errors. */
275 if (global.params.warnings == DIAGNOSTICerror)
276 global.warnings++;
278 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_WARNING, false);
280 else if (global.gag)
281 global.gaggedWarnings++;
284 /* Print supplementary message about the last warning with explicit location
285 LOC. This doesn't increase the global warning count. */
287 void ATTRIBUTE_GCC_DIAG(2,0)
288 vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
290 if (global.params.warnings == DIAGNOSTICoff || global.gag)
291 return;
293 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
296 /* Print a deprecation message with explicit location LOC with an optional
297 message prefix PREFIX1 and PREFIX2, increasing the global warning or
298 error count depending on how deprecations are treated. */
300 void ATTRIBUTE_GCC_DIAG(2,0)
301 vdeprecation (const Loc &loc, const char *format, va_list ap,
302 const char *prefix1, const char *prefix2)
304 if (global.params.useDeprecated == DIAGNOSTICerror)
305 verror (loc, format, ap, prefix1, prefix2);
306 else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
308 char *xformat;
310 /* Build string and emit. */
311 if (prefix2 != NULL)
312 xformat = xasprintf ("%s %s %s", escape_d_format (prefix1),
313 escape_d_format (prefix2), format);
314 else if (prefix1 != NULL)
315 xformat = xasprintf ("%s %s", escape_d_format (prefix1), format);
316 else
317 xformat = xasprintf ("%s", format);
319 d_diagnostic_report_diagnostic (loc, OPT_Wdeprecated, xformat, ap,
320 DK_WARNING, false);
321 free (xformat);
323 else if (global.gag)
324 global.gaggedWarnings++;
327 /* Print supplementary message about the last deprecation with explicit
328 location LOC. This does not increase the global error count. */
330 void ATTRIBUTE_GCC_DIAG(2,0)
331 vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
333 if (global.params.useDeprecated == DIAGNOSTICerror)
334 verrorSupplemental (loc, format, ap);
335 else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
336 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
339 /* Print a verbose message with explicit location LOC. */
341 void ATTRIBUTE_GCC_DIAG(2,0)
342 vmessage (const Loc &loc, const char *format, va_list ap)
344 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
347 /* Print a tip message with prefix and highlighing. */
349 void ATTRIBUTE_GCC_DIAG(1,0)
350 vtip (const char *format, va_list ap)
352 if (!global.gag)
353 d_diagnostic_report_diagnostic (Loc (), 0, format, ap, DK_DEBUG, true);
356 /* Call this after printing out fatal error messages to clean up and
357 exit the compiler. */
359 void
360 fatal (void)
362 exit (FATAL_EXIT_CODE);