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)
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/>. */
20 #include "coretypes.h"
22 #include "dmd/globals.h"
23 #include "dmd/errors.h"
27 #include "diagnostic.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'. */
42 expand_d_format (const char *format
)
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
);
64 /* Escaped backtick, don't expand it as a quoted string. */
65 obstack_1grow (&buf
, '`');
69 obstack_1grow (&buf
, *p
);
77 /* Text enclosed by `...` are translated as a quoted string. */
80 obstack_grow (&buf
, "%>", 2);
85 obstack_grow (&buf
, "%<", 2);
92 /* Check the conversion specification for unhandled flags. */
93 obstack_1grow (&buf
, *p
);
100 /* Malformed format string. */
104 /* Remove whitespace formatting. */
111 /* Remove zero padding from format string. */
117 /* Hex format only supports lower-case. */
118 obstack_1grow (&buf
, 'x');
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. */
136 escape_d_format (const char *format
)
139 size_t format_len
= 0;
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. */
148 format_len
= strlen (format
) - 1;
149 if (format_len
&& format
[format_len
] == '`')
153 for (const char *p
= format
; *p
; p
++)
158 /* Escape `%' characters so that pp_format does not confuse them
159 for actual format specifiers. */
160 obstack_1grow (&buf
, '%');
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
, '\\');
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
)
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
,
201 diagnostic
.option_index
= opt
;
203 diagnostic_report_diagnostic (global_dc
, &diagnostic
);
207 /* Write verbatim messages with no location direct to stream. */
210 text
.args_ptr
= &argp
;
211 text
.format_spec
= expand_d_format (format
);
214 pp_format_verbatim (global_dc
->printer
, &text
);
215 pp_newline_and_flush (global_dc
->printer
);
221 /* Print a hard error message with explicit location LOC with an optional
222 message prefix PREFIX1 and PREFIX2, increasing the global or gagged
225 void ATTRIBUTE_GCC_DIAG(2,3)
226 error (const Loc
&loc
, const char *format
, ...)
229 va_start (ap
, format
);
230 verror (loc
, format
, 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
)
242 /* Build string and emit. */
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
);
249 xformat
= xasprintf ("%s", format
);
251 d_diagnostic_report_diagnostic (loc
, 0, xformat
, ap
,
252 global
.gag
? DK_ANACHRONISM
: DK_ERROR
,
258 global
.gaggedErrors
++;
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
, ...)
270 va_start (ap
, format
);
271 verrorSupplemental (loc
, format
, 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
)
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
, ...)
291 va_start (ap
, format
);
292 vwarning (loc
, format
, 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
)
305 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_WARNING
, false);
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
, ...)
318 va_start (ap
, format
);
319 vwarningSupplemental (loc
, format
, 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
)
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
, ...)
340 va_start (ap
, format
);
341 vdeprecation (loc
, format
, 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
)
355 /* Build string and emit. */
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
);
362 xformat
= xasprintf ("%s", format
);
364 d_diagnostic_report_diagnostic (loc
, OPT_Wdeprecated
, xformat
, ap
,
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
, ...)
379 va_start (ap
, format
);
380 vdeprecationSupplemental (loc
, format
, 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
, ...)
399 va_start (ap
, format
);
400 vmessage (loc
, format
, 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
, ...)
416 va_start (ap
, format
);
417 vmessage (Loc (), format
, ap
);
421 /* Call this after printing out fatal error messages to clean up and
422 exit the compiler. */
427 exit (FATAL_EXIT_CODE
);