Daily bump.
[official-gcc.git] / gcc / d / d-diagnostic.cc
blob1982bd954a8f086514e1774fa867fa85c6b3c029
1 /* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
2 Copyright (C) 2017-2021 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,3)
226 error (const Loc &loc, const char *format, ...)
228 va_list ap;
229 va_start (ap, format);
230 verror (loc, format, ap);
231 va_end (ap);
234 void ATTRIBUTE_GCC_DIAG(2,0)
235 verror (const Loc &loc, const char *format, va_list ap,
236 const char *prefix1, const char *prefix2, const char *)
238 if (!global.gag || global.params.showGaggedErrors)
240 char *xformat;
242 /* Build string and emit. */
243 if (prefix2 != NULL)
244 xformat = xasprintf ("%s %s %s", escape_d_format (prefix1),
245 escape_d_format (prefix2), format);
246 else if (prefix1 != NULL)
247 xformat = xasprintf ("%s %s", escape_d_format (prefix1), format);
248 else
249 xformat = xasprintf ("%s", format);
251 d_diagnostic_report_diagnostic (loc, 0, xformat, ap,
252 global.gag ? DK_ANACHRONISM : DK_ERROR,
253 false);
254 free (xformat);
257 if (global.gag)
258 global.gaggedErrors++;
260 global.errors++;
263 /* Print supplementary message about the last error with explicit location LOC.
264 This doesn't increase the global error count. */
266 void ATTRIBUTE_GCC_DIAG(2,3)
267 errorSupplemental (const Loc &loc, const char *format, ...)
269 va_list ap;
270 va_start (ap, format);
271 verrorSupplemental (loc, format, ap);
272 va_end (ap);
275 void ATTRIBUTE_GCC_DIAG(2,0)
276 verrorSupplemental (const Loc &loc, const char *format, va_list ap)
278 if (global.gag && !global.params.showGaggedErrors)
279 return;
281 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
284 /* Print a warning message with explicit location LOC, increasing the
285 global warning count. */
287 void ATTRIBUTE_GCC_DIAG(2,3)
288 warning (const Loc &loc, const char *format, ...)
290 va_list ap;
291 va_start (ap, format);
292 vwarning (loc, format, ap);
293 va_end (ap);
296 void ATTRIBUTE_GCC_DIAG(2,0)
297 vwarning (const Loc &loc, const char *format, va_list ap)
299 if (!global.gag && global.params.warnings != DIAGNOSTICoff)
301 /* Warnings don't count if not treated as errors. */
302 if (global.params.warnings == DIAGNOSTICerror)
303 global.warnings++;
305 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_WARNING, false);
307 else if (global.gag)
308 global.gaggedWarnings++;
311 /* Print supplementary message about the last warning with explicit location
312 LOC. This doesn't increase the global warning count. */
314 void ATTRIBUTE_GCC_DIAG(2,3)
315 warningSupplemental (const Loc &loc, const char *format, ...)
317 va_list ap;
318 va_start (ap, format);
319 vwarningSupplemental (loc, format, ap);
320 va_end (ap);
323 void ATTRIBUTE_GCC_DIAG(2,0)
324 vwarningSupplemental (const Loc &loc, const char *format, va_list ap)
326 if (global.params.warnings == DIAGNOSTICoff || global.gag)
327 return;
329 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
332 /* Print a deprecation message with explicit location LOC with an optional
333 message prefix PREFIX1 and PREFIX2, increasing the global warning or
334 error count depending on how deprecations are treated. */
336 void ATTRIBUTE_GCC_DIAG(2,3)
337 deprecation (const Loc &loc, const char *format, ...)
339 va_list ap;
340 va_start (ap, format);
341 vdeprecation (loc, format, ap);
342 va_end (ap);
345 void ATTRIBUTE_GCC_DIAG(2,0)
346 vdeprecation (const Loc &loc, const char *format, va_list ap,
347 const char *prefix1, const char *prefix2)
349 if (global.params.useDeprecated == DIAGNOSTICerror)
350 verror (loc, format, ap, prefix1, prefix2);
351 else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
353 char *xformat;
355 /* Build string and emit. */
356 if (prefix2 != NULL)
357 xformat = xasprintf ("%s %s %s", escape_d_format (prefix1),
358 escape_d_format (prefix2), format);
359 else if (prefix1 != NULL)
360 xformat = xasprintf ("%s %s", escape_d_format (prefix1), format);
361 else
362 xformat = xasprintf ("%s", format);
364 d_diagnostic_report_diagnostic (loc, OPT_Wdeprecated, xformat, ap,
365 DK_WARNING, false);
366 free (xformat);
368 else if (global.gag)
369 global.gaggedWarnings++;
372 /* Print supplementary message about the last deprecation with explicit
373 location LOC. This does not increase the global error count. */
375 void ATTRIBUTE_GCC_DIAG(2,3)
376 deprecationSupplemental (const Loc &loc, const char *format, ...)
378 va_list ap;
379 va_start (ap, format);
380 vdeprecationSupplemental (loc, format, ap);
381 va_end (ap);
384 void ATTRIBUTE_GCC_DIAG(2,0)
385 vdeprecationSupplemental (const Loc &loc, const char *format, va_list ap)
387 if (global.params.useDeprecated == DIAGNOSTICerror)
388 verrorSupplemental (loc, format, ap);
389 else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
390 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
393 /* Print a verbose message with explicit location LOC. */
395 void ATTRIBUTE_GCC_DIAG(2, 3)
396 message (const Loc &loc, const char *format, ...)
398 va_list ap;
399 va_start (ap, format);
400 vmessage (loc, format, ap);
401 va_end (ap);
404 void ATTRIBUTE_GCC_DIAG(2,0)
405 vmessage (const Loc &loc, const char *format, va_list ap)
407 d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
410 /* Same as above, but doesn't take a location argument. */
412 void ATTRIBUTE_GCC_DIAG(1, 2)
413 message (const char *format, ...)
415 va_list ap;
416 va_start (ap, format);
417 vmessage (Loc (), format, ap);
418 va_end (ap);
421 /* Call this after printing out fatal error messages to clean up and
422 exit the compiler. */
424 void
425 fatal (void)
427 exit (FATAL_EXIT_CODE);