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