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)
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,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
)
233 /* Build string and emit. */
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
);
240 xformat
= xasprintf ("%s", format
);
242 d_diagnostic_report_diagnostic (loc
, 0, xformat
, ap
,
243 global
.gag
? DK_ANACHRONISM
: DK_ERROR
,
249 global
.gaggedErrors
++;
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
)
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
)
278 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_WARNING
, false);
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
)
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
)
310 /* Build string and emit. */
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
);
317 xformat
= xasprintf ("%s", format
);
319 d_diagnostic_report_diagnostic (loc
, OPT_Wdeprecated
, xformat
, ap
,
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
)
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. */
362 exit (FATAL_EXIT_CODE
);