1 /* d-diagnostics.cc -- D frontend interface to gcc diagnostics.
2 Copyright (C) 2017-2019 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'.
41 The result should be freed by the caller. */
44 expand_d_format (const char *format
)
47 bool inbacktick
= false;
49 for (const char *p
= format
; *p
;)
51 while (*p
!= '\0' && *p
!= '%' && *p
!= '`')
62 /* Text enclosed by `...` are translated as a quoted string. */
65 buf
.writestring ("%>");
70 buf
.writestring ("%<");
77 /* Check the conversion specification for unhandled flags. */
85 /* Malformed format string. */
89 /* Remove whitespace formatting. */
96 /* Remove zero padding from format string. */
102 /* Hex format only supports lower-case. */
112 gcc_assert (!inbacktick
);
113 return buf
.extractString ();
116 /* Helper routine for all error routines. Reports a diagnostic specified by
117 KIND at the explicit location LOC. The message FORMAT comes from the dmd
118 front-end, which does not get translated by the gcc diagnostic routines. */
120 static void ATTRIBUTE_GCC_DIAG(3,0)
121 d_diagnostic_report_diagnostic (const Loc
& loc
, int opt
, const char *format
,
122 va_list ap
, diagnostic_t kind
, bool verbatim
)
127 if (loc
.filename
|| !verbatim
)
129 rich_location
rich_loc (line_table
, make_location_t (loc
));
130 diagnostic_info diagnostic
;
131 char *xformat
= expand_d_format (format
);
133 diagnostic_set_info_translated (&diagnostic
, xformat
, &argp
,
136 diagnostic
.option_index
= opt
;
138 diagnostic_report_diagnostic (global_dc
, &diagnostic
);
143 /* Write verbatim messages with no location direct to stream. */
146 text
.args_ptr
= &argp
;
147 text
.format_spec
= expand_d_format (format
);
150 pp_format_verbatim (global_dc
->printer
, &text
);
151 pp_newline_and_flush (global_dc
->printer
);
157 /* Print a hard error message with explicit location LOC with an optional
158 message prefix PREFIX1 and PREFIX2, increasing the global or gagged
161 void ATTRIBUTE_GCC_DIAG(2,3)
162 error (const Loc
& loc
, const char *format
, ...)
165 va_start (ap
, format
);
166 verror (loc
, format
, ap
);
170 void ATTRIBUTE_GCC_DIAG(2,0)
171 verror (const Loc
& loc
, const char *format
, va_list ap
,
172 const char *prefix1
, const char *prefix2
, const char *)
174 if (!global
.gag
|| global
.params
.showGaggedErrors
)
178 /* Build string and emit. */
180 xformat
= xasprintf ("%s %s %s", prefix1
, prefix2
, format
);
181 else if (prefix1
!= NULL
)
182 xformat
= xasprintf ("%s %s", prefix1
, format
);
184 xformat
= xasprintf ("%s", format
);
186 d_diagnostic_report_diagnostic (loc
, 0, xformat
, ap
,
187 global
.gag
? DK_ANACHRONISM
: DK_ERROR
,
193 global
.gaggedErrors
++;
198 /* Print supplementary message about the last error with explicit location LOC.
199 This doesn't increase the global error count. */
201 void ATTRIBUTE_GCC_DIAG(2,3)
202 errorSupplemental (const Loc
& loc
, const char *format
, ...)
205 va_start (ap
, format
);
206 verrorSupplemental (loc
, format
, ap
);
210 void ATTRIBUTE_GCC_DIAG(2,0)
211 verrorSupplemental (const Loc
& loc
, const char *format
, va_list ap
)
213 if (global
.gag
&& !global
.params
.showGaggedErrors
)
216 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_NOTE
, false);
219 /* Print a warning message with explicit location LOC, increasing the
220 global warning count. */
222 void ATTRIBUTE_GCC_DIAG(2,3)
223 warning (const Loc
& loc
, const char *format
, ...)
226 va_start (ap
, format
);
227 vwarning (loc
, format
, ap
);
231 void ATTRIBUTE_GCC_DIAG(2,0)
232 vwarning (const Loc
& loc
, const char *format
, va_list ap
)
234 if (!global
.gag
&& global
.params
.warnings
!= DIAGNOSTICoff
)
236 /* Warnings don't count if not treated as errors. */
237 if (global
.params
.warnings
== DIAGNOSTICerror
)
240 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_WARNING
, false);
244 /* Print supplementary message about the last warning with explicit location
245 LOC. This doesn't increase the global warning count. */
247 void ATTRIBUTE_GCC_DIAG(2,3)
248 warningSupplemental (const Loc
& loc
, const char *format
, ...)
251 va_start (ap
, format
);
252 vwarningSupplemental (loc
, format
, ap
);
256 void ATTRIBUTE_GCC_DIAG(2,0)
257 vwarningSupplemental (const Loc
& loc
, const char *format
, va_list ap
)
259 if (global
.params
.warnings
== DIAGNOSTICoff
|| global
.gag
)
262 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_NOTE
, false);
265 /* Print a deprecation message with explicit location LOC with an optional
266 message prefix PREFIX1 and PREFIX2, increasing the global warning or
267 error count depending on how deprecations are treated. */
269 void ATTRIBUTE_GCC_DIAG(2,3)
270 deprecation (const Loc
& loc
, const char *format
, ...)
273 va_start (ap
, format
);
274 vdeprecation (loc
, format
, ap
);
278 void ATTRIBUTE_GCC_DIAG(2,0)
279 vdeprecation (const Loc
& loc
, const char *format
, va_list ap
,
280 const char *prefix1
, const char *prefix2
)
282 if (global
.params
.useDeprecated
== DIAGNOSTICerror
)
283 verror (loc
, format
, ap
, prefix1
, prefix2
);
284 else if (global
.params
.useDeprecated
== DIAGNOSTICinform
&& !global
.gag
)
288 /* Build string and emit. */
290 xformat
= xasprintf ("%s %s %s", prefix1
, prefix2
, format
);
291 else if (prefix1
!= NULL
)
292 xformat
= xasprintf ("%s %s", prefix1
, format
);
294 xformat
= xasprintf ("%s", format
);
296 d_diagnostic_report_diagnostic (loc
, OPT_Wdeprecated
, xformat
, ap
,
302 /* Print supplementary message about the last deprecation with explicit
303 location LOC. This does not increase the global error count. */
305 void ATTRIBUTE_GCC_DIAG(2,3)
306 deprecationSupplemental (const Loc
& loc
, const char *format
, ...)
309 va_start (ap
, format
);
310 vdeprecationSupplemental (loc
, format
, ap
);
314 void ATTRIBUTE_GCC_DIAG(2,0)
315 vdeprecationSupplemental (const Loc
& loc
, const char *format
, va_list ap
)
317 if (global
.params
.useDeprecated
== DIAGNOSTICerror
)
318 verrorSupplemental (loc
, format
, ap
);
319 else if (global
.params
.useDeprecated
== DIAGNOSTICinform
&& !global
.gag
)
320 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_NOTE
, false);
323 /* Print a verbose message with explicit location LOC. */
325 void ATTRIBUTE_GCC_DIAG(2, 3)
326 message (const Loc
& loc
, const char *format
, ...)
329 va_start (ap
, format
);
330 vmessage (loc
, format
, ap
);
334 void ATTRIBUTE_GCC_DIAG(2,0)
335 vmessage (const Loc
& loc
, const char *format
, va_list ap
)
337 d_diagnostic_report_diagnostic (loc
, 0, format
, ap
, DK_NOTE
, true);
340 /* Same as above, but doesn't take a location argument. */
342 void ATTRIBUTE_GCC_DIAG(1, 2)
343 message (const char *format
, ...)
346 va_start (ap
, format
);
347 vmessage (Loc (), format
, ap
);
351 /* Call this after printing out fatal error messages to clean up and
352 exit the compiler. */
357 exit (FATAL_EXIT_CODE
);