d-diagnostic.cc revision 1.1 1 1.1 mrg /* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
2 1.1 mrg Copyright (C) 2017-2019 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 mrg %X: uppercase unsigned hexadecimals are rewritten as '%x'.
40 1.1 mrg
41 1.1 mrg The result should be freed by the caller. */
42 1.1 mrg
43 1.1 mrg static char *
44 1.1 mrg expand_d_format (const char *format)
45 1.1 mrg {
46 1.1 mrg OutBuffer buf;
47 1.1 mrg bool inbacktick = false;
48 1.1 mrg
49 1.1 mrg for (const char *p = format; *p;)
50 1.1 mrg {
51 1.1 mrg while (*p != '\0' && *p != '%' && *p != '`')
52 1.1 mrg {
53 1.1 mrg buf.writeByte (*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 mrg if (*p == '`')
61 1.1 mrg {
62 1.1 mrg /* Text enclosed by `...` are translated as a quoted string. */
63 1.1 mrg if (inbacktick)
64 1.1 mrg {
65 1.1 mrg buf.writestring ("%>");
66 1.1 mrg inbacktick = false;
67 1.1 mrg }
68 1.1 mrg else
69 1.1 mrg {
70 1.1 mrg buf.writestring ("%<");
71 1.1 mrg inbacktick = true;
72 1.1 mrg }
73 1.1 mrg p++;
74 1.1 mrg continue;
75 1.1 mrg }
76 1.1 mrg
77 1.1 mrg /* Check the conversion specification for unhandled flags. */
78 1.1 mrg buf.writeByte (*p);
79 1.1 mrg p++;
80 1.1 mrg
81 1.1 mrg Lagain:
82 1.1 mrg switch (*p)
83 1.1 mrg {
84 1.1 mrg case '\0':
85 1.1 mrg /* Malformed format string. */
86 1.1 mrg gcc_unreachable ();
87 1.1 mrg
88 1.1 mrg case '-':
89 1.1 mrg /* Remove whitespace formatting. */
90 1.1 mrg p++;
91 1.1 mrg while (ISDIGIT (*p))
92 1.1 mrg p++;
93 1.1 mrg goto Lagain;
94 1.1 mrg
95 1.1 mrg case '0':
96 1.1 mrg /* Remove zero padding from format string. */
97 1.1 mrg while (ISDIGIT (*p))
98 1.1 mrg p++;
99 1.1 mrg goto Lagain;
100 1.1 mrg
101 1.1 mrg case 'X':
102 1.1 mrg /* Hex format only supports lower-case. */
103 1.1 mrg buf.writeByte ('x');
104 1.1 mrg p++;
105 1.1 mrg break;
106 1.1 mrg
107 1.1 mrg default:
108 1.1 mrg break;
109 1.1 mrg }
110 1.1 mrg }
111 1.1 mrg
112 1.1 mrg gcc_assert (!inbacktick);
113 1.1 mrg return buf.extractString ();
114 1.1 mrg }
115 1.1 mrg
116 1.1 mrg /* Helper routine for all error routines. Reports a diagnostic specified by
117 1.1 mrg KIND at the explicit location LOC. The message FORMAT comes from the dmd
118 1.1 mrg front-end, which does not get translated by the gcc diagnostic routines. */
119 1.1 mrg
120 1.1 mrg static void ATTRIBUTE_GCC_DIAG(3,0)
121 1.1 mrg d_diagnostic_report_diagnostic (const Loc& loc, int opt, const char *format,
122 1.1 mrg va_list ap, diagnostic_t kind, bool verbatim)
123 1.1 mrg {
124 1.1 mrg va_list argp;
125 1.1 mrg va_copy (argp, ap);
126 1.1 mrg
127 1.1 mrg if (loc.filename || !verbatim)
128 1.1 mrg {
129 1.1 mrg rich_location rich_loc (line_table, make_location_t (loc));
130 1.1 mrg diagnostic_info diagnostic;
131 1.1 mrg char *xformat = expand_d_format (format);
132 1.1 mrg
133 1.1 mrg diagnostic_set_info_translated (&diagnostic, xformat, &argp,
134 1.1 mrg &rich_loc, kind);
135 1.1 mrg if (opt != 0)
136 1.1 mrg diagnostic.option_index = opt;
137 1.1 mrg
138 1.1 mrg diagnostic_report_diagnostic (global_dc, &diagnostic);
139 1.1 mrg free (xformat);
140 1.1 mrg }
141 1.1 mrg else
142 1.1 mrg {
143 1.1 mrg /* Write verbatim messages with no location direct to stream. */
144 1.1 mrg text_info text;
145 1.1 mrg text.err_no = errno;
146 1.1 mrg text.args_ptr = &argp;
147 1.1 mrg text.format_spec = expand_d_format (format);
148 1.1 mrg text.x_data = NULL;
149 1.1 mrg
150 1.1 mrg pp_format_verbatim (global_dc->printer, &text);
151 1.1 mrg pp_newline_and_flush (global_dc->printer);
152 1.1 mrg }
153 1.1 mrg
154 1.1 mrg va_end (argp);
155 1.1 mrg }
156 1.1 mrg
157 1.1 mrg /* Print a hard error message with explicit location LOC with an optional
158 1.1 mrg message prefix PREFIX1 and PREFIX2, increasing the global or gagged
159 1.1 mrg error count. */
160 1.1 mrg
161 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
162 1.1 mrg error (const Loc& loc, const char *format, ...)
163 1.1 mrg {
164 1.1 mrg va_list ap;
165 1.1 mrg va_start (ap, format);
166 1.1 mrg verror (loc, format, ap);
167 1.1 mrg va_end (ap);
168 1.1 mrg }
169 1.1 mrg
170 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
171 1.1 mrg verror (const Loc& loc, const char *format, va_list ap,
172 1.1 mrg const char *prefix1, const char *prefix2, const char *)
173 1.1 mrg {
174 1.1 mrg if (!global.gag || global.params.showGaggedErrors)
175 1.1 mrg {
176 1.1 mrg char *xformat;
177 1.1 mrg
178 1.1 mrg /* Build string and emit. */
179 1.1 mrg if (prefix2 != NULL)
180 1.1 mrg xformat = xasprintf ("%s %s %s", prefix1, prefix2, format);
181 1.1 mrg else if (prefix1 != NULL)
182 1.1 mrg xformat = xasprintf ("%s %s", prefix1, format);
183 1.1 mrg else
184 1.1 mrg xformat = xasprintf ("%s", format);
185 1.1 mrg
186 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, xformat, ap,
187 1.1 mrg global.gag ? DK_ANACHRONISM : DK_ERROR,
188 1.1 mrg false);
189 1.1 mrg free (xformat);
190 1.1 mrg }
191 1.1 mrg
192 1.1 mrg if (global.gag)
193 1.1 mrg global.gaggedErrors++;
194 1.1 mrg
195 1.1 mrg global.errors++;
196 1.1 mrg }
197 1.1 mrg
198 1.1 mrg /* Print supplementary message about the last error with explicit location LOC.
199 1.1 mrg This doesn't increase the global error count. */
200 1.1 mrg
201 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
202 1.1 mrg errorSupplemental (const Loc& loc, const char *format, ...)
203 1.1 mrg {
204 1.1 mrg va_list ap;
205 1.1 mrg va_start (ap, format);
206 1.1 mrg verrorSupplemental (loc, format, ap);
207 1.1 mrg va_end (ap);
208 1.1 mrg }
209 1.1 mrg
210 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
211 1.1 mrg verrorSupplemental (const Loc& loc, const char *format, va_list ap)
212 1.1 mrg {
213 1.1 mrg if (global.gag && !global.params.showGaggedErrors)
214 1.1 mrg return;
215 1.1 mrg
216 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
217 1.1 mrg }
218 1.1 mrg
219 1.1 mrg /* Print a warning message with explicit location LOC, increasing the
220 1.1 mrg global warning count. */
221 1.1 mrg
222 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
223 1.1 mrg warning (const Loc& loc, const char *format, ...)
224 1.1 mrg {
225 1.1 mrg va_list ap;
226 1.1 mrg va_start (ap, format);
227 1.1 mrg vwarning (loc, format, ap);
228 1.1 mrg va_end (ap);
229 1.1 mrg }
230 1.1 mrg
231 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
232 1.1 mrg vwarning (const Loc& loc, const char *format, va_list ap)
233 1.1 mrg {
234 1.1 mrg if (!global.gag && global.params.warnings != DIAGNOSTICoff)
235 1.1 mrg {
236 1.1 mrg /* Warnings don't count if not treated as errors. */
237 1.1 mrg if (global.params.warnings == DIAGNOSTICerror)
238 1.1 mrg global.warnings++;
239 1.1 mrg
240 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_WARNING, false);
241 1.1 mrg }
242 1.1 mrg }
243 1.1 mrg
244 1.1 mrg /* Print supplementary message about the last warning with explicit location
245 1.1 mrg LOC. This doesn't increase the global warning count. */
246 1.1 mrg
247 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
248 1.1 mrg warningSupplemental (const Loc& loc, const char *format, ...)
249 1.1 mrg {
250 1.1 mrg va_list ap;
251 1.1 mrg va_start (ap, format);
252 1.1 mrg vwarningSupplemental (loc, format, ap);
253 1.1 mrg va_end (ap);
254 1.1 mrg }
255 1.1 mrg
256 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
257 1.1 mrg vwarningSupplemental (const Loc& loc, const char *format, va_list ap)
258 1.1 mrg {
259 1.1 mrg if (global.params.warnings == DIAGNOSTICoff || global.gag)
260 1.1 mrg return;
261 1.1 mrg
262 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
263 1.1 mrg }
264 1.1 mrg
265 1.1 mrg /* Print a deprecation message with explicit location LOC with an optional
266 1.1 mrg message prefix PREFIX1 and PREFIX2, increasing the global warning or
267 1.1 mrg error count depending on how deprecations are treated. */
268 1.1 mrg
269 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
270 1.1 mrg deprecation (const Loc& loc, const char *format, ...)
271 1.1 mrg {
272 1.1 mrg va_list ap;
273 1.1 mrg va_start (ap, format);
274 1.1 mrg vdeprecation (loc, format, ap);
275 1.1 mrg va_end (ap);
276 1.1 mrg }
277 1.1 mrg
278 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
279 1.1 mrg vdeprecation (const Loc& loc, const char *format, va_list ap,
280 1.1 mrg const char *prefix1, const char *prefix2)
281 1.1 mrg {
282 1.1 mrg if (global.params.useDeprecated == DIAGNOSTICerror)
283 1.1 mrg verror (loc, format, ap, prefix1, prefix2);
284 1.1 mrg else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
285 1.1 mrg {
286 1.1 mrg char *xformat;
287 1.1 mrg
288 1.1 mrg /* Build string and emit. */
289 1.1 mrg if (prefix2 != NULL)
290 1.1 mrg xformat = xasprintf ("%s %s %s", prefix1, prefix2, format);
291 1.1 mrg else if (prefix1 != NULL)
292 1.1 mrg xformat = xasprintf ("%s %s", prefix1, format);
293 1.1 mrg else
294 1.1 mrg xformat = xasprintf ("%s", format);
295 1.1 mrg
296 1.1 mrg d_diagnostic_report_diagnostic (loc, OPT_Wdeprecated, xformat, ap,
297 1.1 mrg DK_WARNING, false);
298 1.1 mrg free (xformat);
299 1.1 mrg }
300 1.1 mrg }
301 1.1 mrg
302 1.1 mrg /* Print supplementary message about the last deprecation with explicit
303 1.1 mrg location LOC. This does not increase the global error count. */
304 1.1 mrg
305 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,3)
306 1.1 mrg deprecationSupplemental (const Loc& loc, const char *format, ...)
307 1.1 mrg {
308 1.1 mrg va_list ap;
309 1.1 mrg va_start (ap, format);
310 1.1 mrg vdeprecationSupplemental (loc, format, ap);
311 1.1 mrg va_end (ap);
312 1.1 mrg }
313 1.1 mrg
314 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
315 1.1 mrg vdeprecationSupplemental (const Loc& loc, const char *format, va_list ap)
316 1.1 mrg {
317 1.1 mrg if (global.params.useDeprecated == DIAGNOSTICerror)
318 1.1 mrg verrorSupplemental (loc, format, ap);
319 1.1 mrg else if (global.params.useDeprecated == DIAGNOSTICinform && !global.gag)
320 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, false);
321 1.1 mrg }
322 1.1 mrg
323 1.1 mrg /* Print a verbose message with explicit location LOC. */
324 1.1 mrg
325 1.1 mrg void ATTRIBUTE_GCC_DIAG(2, 3)
326 1.1 mrg message (const Loc& loc, const char *format, ...)
327 1.1 mrg {
328 1.1 mrg va_list ap;
329 1.1 mrg va_start (ap, format);
330 1.1 mrg vmessage (loc, format, ap);
331 1.1 mrg va_end (ap);
332 1.1 mrg }
333 1.1 mrg
334 1.1 mrg void ATTRIBUTE_GCC_DIAG(2,0)
335 1.1 mrg vmessage (const Loc& loc, const char *format, va_list ap)
336 1.1 mrg {
337 1.1 mrg d_diagnostic_report_diagnostic (loc, 0, format, ap, DK_NOTE, true);
338 1.1 mrg }
339 1.1 mrg
340 1.1 mrg /* Same as above, but doesn't take a location argument. */
341 1.1 mrg
342 1.1 mrg void ATTRIBUTE_GCC_DIAG(1, 2)
343 1.1 mrg message (const char *format, ...)
344 1.1 mrg {
345 1.1 mrg va_list ap;
346 1.1 mrg va_start (ap, format);
347 1.1 mrg vmessage (Loc (), format, ap);
348 1.1 mrg va_end (ap);
349 1.1 mrg }
350 1.1 mrg
351 1.1 mrg /* Call this after printing out fatal error messages to clean up and
352 1.1 mrg exit the compiler. */
353 1.1 mrg
354 1.1 mrg void
355 1.1 mrg fatal (void)
356 1.1 mrg {
357 1.1 mrg exit (FATAL_EXIT_CODE);
358 1.1 mrg }
359