1627f7eb2Smrg /* Handle errors.
2*4c3eb207Smrg Copyright (C) 2000-2020 Free Software Foundation, Inc.
3627f7eb2Smrg Contributed by Andy Vaught & Niels Kristian Bech Jensen
4627f7eb2Smrg
5627f7eb2Smrg This file is part of GCC.
6627f7eb2Smrg
7627f7eb2Smrg GCC is free software; you can redistribute it and/or modify it under
8627f7eb2Smrg the terms of the GNU General Public License as published by the Free
9627f7eb2Smrg Software Foundation; either version 3, or (at your option) any later
10627f7eb2Smrg version.
11627f7eb2Smrg
12627f7eb2Smrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13627f7eb2Smrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14627f7eb2Smrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15627f7eb2Smrg for more details.
16627f7eb2Smrg
17627f7eb2Smrg You should have received a copy of the GNU General Public License
18627f7eb2Smrg along with GCC; see the file COPYING3. If not see
19627f7eb2Smrg <http://www.gnu.org/licenses/>. */
20627f7eb2Smrg
21627f7eb2Smrg /* Handle the inevitable errors. A major catch here is that things
22627f7eb2Smrg flagged as errors in one match subroutine can conceivably be legal
23627f7eb2Smrg elsewhere. This means that error messages are recorded and saved
24627f7eb2Smrg for possible use later. If a line does not match a legal
25627f7eb2Smrg construction, then the saved error message is reported. */
26627f7eb2Smrg
27627f7eb2Smrg #include "config.h"
28627f7eb2Smrg #include "system.h"
29627f7eb2Smrg #include "coretypes.h"
30627f7eb2Smrg #include "options.h"
31627f7eb2Smrg #include "gfortran.h"
32627f7eb2Smrg
33627f7eb2Smrg #include "diagnostic.h"
34627f7eb2Smrg #include "diagnostic-color.h"
35627f7eb2Smrg #include "tree-diagnostic.h" /* tree_diagnostics_defaults */
36627f7eb2Smrg
37627f7eb2Smrg static int suppress_errors = 0;
38627f7eb2Smrg
39627f7eb2Smrg static bool warnings_not_errors = false;
40627f7eb2Smrg
41627f7eb2Smrg static int terminal_width;
42627f7eb2Smrg
43627f7eb2Smrg /* True if the error/warnings should be buffered. */
44627f7eb2Smrg static bool buffered_p;
45627f7eb2Smrg
46627f7eb2Smrg static gfc_error_buffer error_buffer;
47627f7eb2Smrg /* These are always buffered buffers (.flush_p == false) to be used by
48627f7eb2Smrg the pretty-printer. */
49627f7eb2Smrg static output_buffer *pp_error_buffer, *pp_warning_buffer;
50627f7eb2Smrg static int warningcount_buffered, werrorcount_buffered;
51627f7eb2Smrg
52627f7eb2Smrg /* Return true if there output_buffer is empty. */
53627f7eb2Smrg
54627f7eb2Smrg static bool
gfc_output_buffer_empty_p(const output_buffer * buf)55627f7eb2Smrg gfc_output_buffer_empty_p (const output_buffer * buf)
56627f7eb2Smrg {
57627f7eb2Smrg return output_buffer_last_position_in_text (buf) == NULL;
58627f7eb2Smrg }
59627f7eb2Smrg
60627f7eb2Smrg /* Go one level deeper suppressing errors. */
61627f7eb2Smrg
62627f7eb2Smrg void
gfc_push_suppress_errors(void)63627f7eb2Smrg gfc_push_suppress_errors (void)
64627f7eb2Smrg {
65627f7eb2Smrg gcc_assert (suppress_errors >= 0);
66627f7eb2Smrg ++suppress_errors;
67627f7eb2Smrg }
68627f7eb2Smrg
69627f7eb2Smrg static void
70627f7eb2Smrg gfc_error_opt (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
71627f7eb2Smrg
72627f7eb2Smrg static bool
73627f7eb2Smrg gfc_warning (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
74627f7eb2Smrg
75627f7eb2Smrg
76627f7eb2Smrg /* Leave one level of error suppressing. */
77627f7eb2Smrg
78627f7eb2Smrg void
gfc_pop_suppress_errors(void)79627f7eb2Smrg gfc_pop_suppress_errors (void)
80627f7eb2Smrg {
81627f7eb2Smrg gcc_assert (suppress_errors > 0);
82627f7eb2Smrg --suppress_errors;
83627f7eb2Smrg }
84627f7eb2Smrg
85627f7eb2Smrg
86627f7eb2Smrg /* Determine terminal width (for trimming source lines in output). */
87627f7eb2Smrg
88627f7eb2Smrg static int
gfc_get_terminal_width(void)89627f7eb2Smrg gfc_get_terminal_width (void)
90627f7eb2Smrg {
91627f7eb2Smrg return isatty (STDERR_FILENO) ? get_terminal_width () : INT_MAX;
92627f7eb2Smrg }
93627f7eb2Smrg
94627f7eb2Smrg
95627f7eb2Smrg /* Per-file error initialization. */
96627f7eb2Smrg
97627f7eb2Smrg void
gfc_error_init_1(void)98627f7eb2Smrg gfc_error_init_1 (void)
99627f7eb2Smrg {
100627f7eb2Smrg terminal_width = gfc_get_terminal_width ();
101627f7eb2Smrg gfc_buffer_error (false);
102627f7eb2Smrg }
103627f7eb2Smrg
104627f7eb2Smrg
105627f7eb2Smrg /* Set the flag for buffering errors or not. */
106627f7eb2Smrg
107627f7eb2Smrg void
gfc_buffer_error(bool flag)108627f7eb2Smrg gfc_buffer_error (bool flag)
109627f7eb2Smrg {
110627f7eb2Smrg buffered_p = flag;
111627f7eb2Smrg }
112627f7eb2Smrg
113627f7eb2Smrg
114627f7eb2Smrg /* Add a single character to the error buffer or output depending on
115627f7eb2Smrg buffered_p. */
116627f7eb2Smrg
117627f7eb2Smrg static void
error_char(char)118627f7eb2Smrg error_char (char)
119627f7eb2Smrg {
120627f7eb2Smrg /* FIXME: Unused function to be removed in a subsequent patch. */
121627f7eb2Smrg }
122627f7eb2Smrg
123627f7eb2Smrg
124627f7eb2Smrg /* Copy a string to wherever it needs to go. */
125627f7eb2Smrg
126627f7eb2Smrg static void
error_string(const char * p)127627f7eb2Smrg error_string (const char *p)
128627f7eb2Smrg {
129627f7eb2Smrg while (*p)
130627f7eb2Smrg error_char (*p++);
131627f7eb2Smrg }
132627f7eb2Smrg
133627f7eb2Smrg
134627f7eb2Smrg /* Print a formatted integer to the error buffer or output. */
135627f7eb2Smrg
136627f7eb2Smrg #define IBUF_LEN 60
137627f7eb2Smrg
138627f7eb2Smrg static void
error_uinteger(unsigned long int i)139627f7eb2Smrg error_uinteger (unsigned long int i)
140627f7eb2Smrg {
141627f7eb2Smrg char *p, int_buf[IBUF_LEN];
142627f7eb2Smrg
143627f7eb2Smrg p = int_buf + IBUF_LEN - 1;
144627f7eb2Smrg *p-- = '\0';
145627f7eb2Smrg
146627f7eb2Smrg if (i == 0)
147627f7eb2Smrg *p-- = '0';
148627f7eb2Smrg
149627f7eb2Smrg while (i > 0)
150627f7eb2Smrg {
151627f7eb2Smrg *p-- = i % 10 + '0';
152627f7eb2Smrg i = i / 10;
153627f7eb2Smrg }
154627f7eb2Smrg
155627f7eb2Smrg error_string (p + 1);
156627f7eb2Smrg }
157627f7eb2Smrg
158627f7eb2Smrg static void
error_integer(long int i)159627f7eb2Smrg error_integer (long int i)
160627f7eb2Smrg {
161627f7eb2Smrg unsigned long int u;
162627f7eb2Smrg
163627f7eb2Smrg if (i < 0)
164627f7eb2Smrg {
165627f7eb2Smrg u = (unsigned long int) -i;
166627f7eb2Smrg error_char ('-');
167627f7eb2Smrg }
168627f7eb2Smrg else
169627f7eb2Smrg u = i;
170627f7eb2Smrg
171627f7eb2Smrg error_uinteger (u);
172627f7eb2Smrg }
173627f7eb2Smrg
174627f7eb2Smrg
175627f7eb2Smrg static size_t
gfc_widechar_display_length(gfc_char_t c)176627f7eb2Smrg gfc_widechar_display_length (gfc_char_t c)
177627f7eb2Smrg {
178627f7eb2Smrg if (gfc_wide_is_printable (c) || c == '\t')
179627f7eb2Smrg /* Printable ASCII character, or tabulation (output as a space). */
180627f7eb2Smrg return 1;
181627f7eb2Smrg else if (c < ((gfc_char_t) 1 << 8))
182627f7eb2Smrg /* Displayed as \x?? */
183627f7eb2Smrg return 4;
184627f7eb2Smrg else if (c < ((gfc_char_t) 1 << 16))
185627f7eb2Smrg /* Displayed as \u???? */
186627f7eb2Smrg return 6;
187627f7eb2Smrg else
188627f7eb2Smrg /* Displayed as \U???????? */
189627f7eb2Smrg return 10;
190627f7eb2Smrg }
191627f7eb2Smrg
192627f7eb2Smrg
193627f7eb2Smrg /* Length of the ASCII representation of the wide string, escaping wide
194627f7eb2Smrg characters as print_wide_char_into_buffer() does. */
195627f7eb2Smrg
196627f7eb2Smrg static size_t
gfc_wide_display_length(const gfc_char_t * str)197627f7eb2Smrg gfc_wide_display_length (const gfc_char_t *str)
198627f7eb2Smrg {
199627f7eb2Smrg size_t i, len;
200627f7eb2Smrg
201627f7eb2Smrg for (i = 0, len = 0; str[i]; i++)
202627f7eb2Smrg len += gfc_widechar_display_length (str[i]);
203627f7eb2Smrg
204627f7eb2Smrg return len;
205627f7eb2Smrg }
206627f7eb2Smrg
207627f7eb2Smrg static int
print_wide_char_into_buffer(gfc_char_t c,char * buf)208627f7eb2Smrg print_wide_char_into_buffer (gfc_char_t c, char *buf)
209627f7eb2Smrg {
210627f7eb2Smrg static const char xdigit[16] = { '0', '1', '2', '3', '4', '5', '6',
211627f7eb2Smrg '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
212627f7eb2Smrg
213627f7eb2Smrg if (gfc_wide_is_printable (c) || c == '\t')
214627f7eb2Smrg {
215627f7eb2Smrg buf[1] = '\0';
216627f7eb2Smrg /* Tabulation is output as a space. */
217627f7eb2Smrg buf[0] = (unsigned char) (c == '\t' ? ' ' : c);
218627f7eb2Smrg return 1;
219627f7eb2Smrg }
220627f7eb2Smrg else if (c < ((gfc_char_t) 1 << 8))
221627f7eb2Smrg {
222627f7eb2Smrg buf[4] = '\0';
223627f7eb2Smrg buf[3] = xdigit[c & 0x0F];
224627f7eb2Smrg c = c >> 4;
225627f7eb2Smrg buf[2] = xdigit[c & 0x0F];
226627f7eb2Smrg
227627f7eb2Smrg buf[1] = 'x';
228627f7eb2Smrg buf[0] = '\\';
229627f7eb2Smrg return 4;
230627f7eb2Smrg }
231627f7eb2Smrg else if (c < ((gfc_char_t) 1 << 16))
232627f7eb2Smrg {
233627f7eb2Smrg buf[6] = '\0';
234627f7eb2Smrg buf[5] = xdigit[c & 0x0F];
235627f7eb2Smrg c = c >> 4;
236627f7eb2Smrg buf[4] = xdigit[c & 0x0F];
237627f7eb2Smrg c = c >> 4;
238627f7eb2Smrg buf[3] = xdigit[c & 0x0F];
239627f7eb2Smrg c = c >> 4;
240627f7eb2Smrg buf[2] = xdigit[c & 0x0F];
241627f7eb2Smrg
242627f7eb2Smrg buf[1] = 'u';
243627f7eb2Smrg buf[0] = '\\';
244627f7eb2Smrg return 6;
245627f7eb2Smrg }
246627f7eb2Smrg else
247627f7eb2Smrg {
248627f7eb2Smrg buf[10] = '\0';
249627f7eb2Smrg buf[9] = xdigit[c & 0x0F];
250627f7eb2Smrg c = c >> 4;
251627f7eb2Smrg buf[8] = xdigit[c & 0x0F];
252627f7eb2Smrg c = c >> 4;
253627f7eb2Smrg buf[7] = xdigit[c & 0x0F];
254627f7eb2Smrg c = c >> 4;
255627f7eb2Smrg buf[6] = xdigit[c & 0x0F];
256627f7eb2Smrg c = c >> 4;
257627f7eb2Smrg buf[5] = xdigit[c & 0x0F];
258627f7eb2Smrg c = c >> 4;
259627f7eb2Smrg buf[4] = xdigit[c & 0x0F];
260627f7eb2Smrg c = c >> 4;
261627f7eb2Smrg buf[3] = xdigit[c & 0x0F];
262627f7eb2Smrg c = c >> 4;
263627f7eb2Smrg buf[2] = xdigit[c & 0x0F];
264627f7eb2Smrg
265627f7eb2Smrg buf[1] = 'U';
266627f7eb2Smrg buf[0] = '\\';
267627f7eb2Smrg return 10;
268627f7eb2Smrg }
269627f7eb2Smrg }
270627f7eb2Smrg
271627f7eb2Smrg static char wide_char_print_buffer[11];
272627f7eb2Smrg
273627f7eb2Smrg const char *
gfc_print_wide_char(gfc_char_t c)274627f7eb2Smrg gfc_print_wide_char (gfc_char_t c)
275627f7eb2Smrg {
276627f7eb2Smrg print_wide_char_into_buffer (c, wide_char_print_buffer);
277627f7eb2Smrg return wide_char_print_buffer;
278627f7eb2Smrg }
279627f7eb2Smrg
280627f7eb2Smrg
281627f7eb2Smrg /* Show the file, where it was included, and the source line, give a
282627f7eb2Smrg locus. Calls error_printf() recursively, but the recursion is at
283627f7eb2Smrg most one level deep. */
284627f7eb2Smrg
285627f7eb2Smrg static void error_printf (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
286627f7eb2Smrg
287627f7eb2Smrg static void
show_locus(locus * loc,int c1,int c2)288627f7eb2Smrg show_locus (locus *loc, int c1, int c2)
289627f7eb2Smrg {
290627f7eb2Smrg gfc_linebuf *lb;
291627f7eb2Smrg gfc_file *f;
292627f7eb2Smrg gfc_char_t *p;
293627f7eb2Smrg int i, offset, cmax;
294627f7eb2Smrg
295627f7eb2Smrg /* TODO: Either limit the total length and number of included files
296627f7eb2Smrg displayed or add buffering of arbitrary number of characters in
297627f7eb2Smrg error messages. */
298627f7eb2Smrg
299627f7eb2Smrg /* Write out the error header line, giving the source file and error
300627f7eb2Smrg location (in GNU standard "[file]:[line].[column]:" format),
301627f7eb2Smrg followed by an "included by" stack and a blank line. This header
302627f7eb2Smrg format is matched by a testsuite parser defined in
303627f7eb2Smrg lib/gfortran-dg.exp. */
304627f7eb2Smrg
305627f7eb2Smrg lb = loc->lb;
306627f7eb2Smrg f = lb->file;
307627f7eb2Smrg
308627f7eb2Smrg error_string (f->filename);
309627f7eb2Smrg error_char (':');
310627f7eb2Smrg
311627f7eb2Smrg error_integer (LOCATION_LINE (lb->location));
312627f7eb2Smrg
313627f7eb2Smrg if ((c1 > 0) || (c2 > 0))
314627f7eb2Smrg error_char ('.');
315627f7eb2Smrg
316627f7eb2Smrg if (c1 > 0)
317627f7eb2Smrg error_integer (c1);
318627f7eb2Smrg
319627f7eb2Smrg if ((c1 > 0) && (c2 > 0))
320627f7eb2Smrg error_char ('-');
321627f7eb2Smrg
322627f7eb2Smrg if (c2 > 0)
323627f7eb2Smrg error_integer (c2);
324627f7eb2Smrg
325627f7eb2Smrg error_char (':');
326627f7eb2Smrg error_char ('\n');
327627f7eb2Smrg
328627f7eb2Smrg for (;;)
329627f7eb2Smrg {
330627f7eb2Smrg i = f->inclusion_line;
331627f7eb2Smrg
332627f7eb2Smrg f = f->up;
333627f7eb2Smrg if (f == NULL) break;
334627f7eb2Smrg
335627f7eb2Smrg error_printf (" Included at %s:%d:", f->filename, i);
336627f7eb2Smrg }
337627f7eb2Smrg
338627f7eb2Smrg error_char ('\n');
339627f7eb2Smrg
340627f7eb2Smrg /* Calculate an appropriate horizontal offset of the source line in
341627f7eb2Smrg order to get the error locus within the visible portion of the
342627f7eb2Smrg line. Note that if the margin of 5 here is changed, the
343627f7eb2Smrg corresponding margin of 10 in show_loci should be changed. */
344627f7eb2Smrg
345627f7eb2Smrg offset = 0;
346627f7eb2Smrg
347627f7eb2Smrg /* If the two loci would appear in the same column, we shift
348627f7eb2Smrg '2' one column to the right, so as to print '12' rather than
349627f7eb2Smrg just '1'. We do this here so it will be accounted for in the
350627f7eb2Smrg margin calculations. */
351627f7eb2Smrg
352627f7eb2Smrg if (c1 == c2)
353627f7eb2Smrg c2 += 1;
354627f7eb2Smrg
355627f7eb2Smrg cmax = (c1 < c2) ? c2 : c1;
356627f7eb2Smrg if (cmax > terminal_width - 5)
357627f7eb2Smrg offset = cmax - terminal_width + 5;
358627f7eb2Smrg
359627f7eb2Smrg /* Show the line itself, taking care not to print more than what can
360627f7eb2Smrg show up on the terminal. Tabs are converted to spaces, and
361627f7eb2Smrg nonprintable characters are converted to a "\xNN" sequence. */
362627f7eb2Smrg
363627f7eb2Smrg p = &(lb->line[offset]);
364627f7eb2Smrg i = gfc_wide_display_length (p);
365627f7eb2Smrg if (i > terminal_width)
366627f7eb2Smrg i = terminal_width - 1;
367627f7eb2Smrg
368627f7eb2Smrg while (i > 0)
369627f7eb2Smrg {
370627f7eb2Smrg static char buffer[11];
371627f7eb2Smrg i -= print_wide_char_into_buffer (*p++, buffer);
372627f7eb2Smrg error_string (buffer);
373627f7eb2Smrg }
374627f7eb2Smrg
375627f7eb2Smrg error_char ('\n');
376627f7eb2Smrg
377627f7eb2Smrg /* Show the '1' and/or '2' corresponding to the column of the error
378627f7eb2Smrg locus. Note that a value of -1 for c1 or c2 will simply cause
379627f7eb2Smrg the relevant number not to be printed. */
380627f7eb2Smrg
381627f7eb2Smrg c1 -= offset;
382627f7eb2Smrg c2 -= offset;
383627f7eb2Smrg cmax -= offset;
384627f7eb2Smrg
385627f7eb2Smrg p = &(lb->line[offset]);
386627f7eb2Smrg for (i = 0; i < cmax; i++)
387627f7eb2Smrg {
388627f7eb2Smrg int spaces, j;
389627f7eb2Smrg spaces = gfc_widechar_display_length (*p++);
390627f7eb2Smrg
391627f7eb2Smrg if (i == c1)
392627f7eb2Smrg error_char ('1'), spaces--;
393627f7eb2Smrg else if (i == c2)
394627f7eb2Smrg error_char ('2'), spaces--;
395627f7eb2Smrg
396627f7eb2Smrg for (j = 0; j < spaces; j++)
397627f7eb2Smrg error_char (' ');
398627f7eb2Smrg }
399627f7eb2Smrg
400627f7eb2Smrg if (i == c1)
401627f7eb2Smrg error_char ('1');
402627f7eb2Smrg else if (i == c2)
403627f7eb2Smrg error_char ('2');
404627f7eb2Smrg
405627f7eb2Smrg error_char ('\n');
406627f7eb2Smrg
407627f7eb2Smrg }
408627f7eb2Smrg
409627f7eb2Smrg
410627f7eb2Smrg /* As part of printing an error, we show the source lines that caused
411627f7eb2Smrg the problem. We show at least one, and possibly two loci; the two
412627f7eb2Smrg loci may or may not be on the same source line. */
413627f7eb2Smrg
414627f7eb2Smrg static void
show_loci(locus * l1,locus * l2)415627f7eb2Smrg show_loci (locus *l1, locus *l2)
416627f7eb2Smrg {
417627f7eb2Smrg int m, c1, c2;
418627f7eb2Smrg
419627f7eb2Smrg if (l1 == NULL || l1->lb == NULL)
420627f7eb2Smrg {
421627f7eb2Smrg error_printf ("<During initialization>\n");
422627f7eb2Smrg return;
423627f7eb2Smrg }
424627f7eb2Smrg
425627f7eb2Smrg /* While calculating parameters for printing the loci, we consider possible
426627f7eb2Smrg reasons for printing one per line. If appropriate, print the loci
427627f7eb2Smrg individually; otherwise we print them both on the same line. */
428627f7eb2Smrg
429627f7eb2Smrg c1 = l1->nextc - l1->lb->line;
430627f7eb2Smrg if (l2 == NULL)
431627f7eb2Smrg {
432627f7eb2Smrg show_locus (l1, c1, -1);
433627f7eb2Smrg return;
434627f7eb2Smrg }
435627f7eb2Smrg
436627f7eb2Smrg c2 = l2->nextc - l2->lb->line;
437627f7eb2Smrg
438627f7eb2Smrg if (c1 < c2)
439627f7eb2Smrg m = c2 - c1;
440627f7eb2Smrg else
441627f7eb2Smrg m = c1 - c2;
442627f7eb2Smrg
443627f7eb2Smrg /* Note that the margin value of 10 here needs to be less than the
444627f7eb2Smrg margin of 5 used in the calculation of offset in show_locus. */
445627f7eb2Smrg
446627f7eb2Smrg if (l1->lb != l2->lb || m > terminal_width - 10)
447627f7eb2Smrg {
448627f7eb2Smrg show_locus (l1, c1, -1);
449627f7eb2Smrg show_locus (l2, -1, c2);
450627f7eb2Smrg return;
451627f7eb2Smrg }
452627f7eb2Smrg
453627f7eb2Smrg show_locus (l1, c1, c2);
454627f7eb2Smrg
455627f7eb2Smrg return;
456627f7eb2Smrg }
457627f7eb2Smrg
458627f7eb2Smrg
459627f7eb2Smrg /* Workhorse for the error printing subroutines. This subroutine is
460627f7eb2Smrg inspired by g77's error handling and is similar to printf() with
461627f7eb2Smrg the following %-codes:
462627f7eb2Smrg
463627f7eb2Smrg %c Character, %d or %i Integer, %s String, %% Percent
464627f7eb2Smrg %L Takes locus argument
465627f7eb2Smrg %C Current locus (no argument)
466627f7eb2Smrg
467627f7eb2Smrg If a locus pointer is given, the actual source line is printed out
468627f7eb2Smrg and the column is indicated. Since we want the error message at
469627f7eb2Smrg the bottom of any source file information, we must scan the
470627f7eb2Smrg argument list twice -- once to determine whether the loci are
471627f7eb2Smrg present and record this for printing, and once to print the error
472627f7eb2Smrg message after and loci have been printed. A maximum of two locus
473627f7eb2Smrg arguments are permitted.
474627f7eb2Smrg
475627f7eb2Smrg This function is also called (recursively) by show_locus in the
476627f7eb2Smrg case of included files; however, as show_locus does not resupply
477627f7eb2Smrg any loci, the recursion is at most one level deep. */
478627f7eb2Smrg
479627f7eb2Smrg #define MAX_ARGS 10
480627f7eb2Smrg
481627f7eb2Smrg static void ATTRIBUTE_GCC_GFC(2,0)
error_print(const char * type,const char * format0,va_list argp)482627f7eb2Smrg error_print (const char *type, const char *format0, va_list argp)
483627f7eb2Smrg {
484627f7eb2Smrg enum { TYPE_CURRENTLOC, TYPE_LOCUS, TYPE_INTEGER, TYPE_UINTEGER,
485627f7eb2Smrg TYPE_LONGINT, TYPE_ULONGINT, TYPE_CHAR, TYPE_STRING,
486627f7eb2Smrg NOTYPE };
487627f7eb2Smrg struct
488627f7eb2Smrg {
489627f7eb2Smrg int type;
490627f7eb2Smrg int pos;
491627f7eb2Smrg union
492627f7eb2Smrg {
493627f7eb2Smrg int intval;
494627f7eb2Smrg unsigned int uintval;
495627f7eb2Smrg long int longintval;
496627f7eb2Smrg unsigned long int ulongintval;
497627f7eb2Smrg char charval;
498627f7eb2Smrg const char * stringval;
499627f7eb2Smrg } u;
500627f7eb2Smrg } arg[MAX_ARGS], spec[MAX_ARGS];
501627f7eb2Smrg /* spec is the array of specifiers, in the same order as they
502627f7eb2Smrg appear in the format string. arg is the array of arguments,
503627f7eb2Smrg in the same order as they appear in the va_list. */
504627f7eb2Smrg
505627f7eb2Smrg char c;
506627f7eb2Smrg int i, n, have_l1, pos, maxpos;
507627f7eb2Smrg locus *l1, *l2, *loc;
508627f7eb2Smrg const char *format;
509627f7eb2Smrg
510627f7eb2Smrg loc = l1 = l2 = NULL;
511627f7eb2Smrg
512627f7eb2Smrg have_l1 = 0;
513627f7eb2Smrg pos = -1;
514627f7eb2Smrg maxpos = -1;
515627f7eb2Smrg
516627f7eb2Smrg n = 0;
517627f7eb2Smrg format = format0;
518627f7eb2Smrg
519627f7eb2Smrg for (i = 0; i < MAX_ARGS; i++)
520627f7eb2Smrg {
521627f7eb2Smrg arg[i].type = NOTYPE;
522627f7eb2Smrg spec[i].pos = -1;
523627f7eb2Smrg }
524627f7eb2Smrg
525627f7eb2Smrg /* First parse the format string for position specifiers. */
526627f7eb2Smrg while (*format)
527627f7eb2Smrg {
528627f7eb2Smrg c = *format++;
529627f7eb2Smrg if (c != '%')
530627f7eb2Smrg continue;
531627f7eb2Smrg
532627f7eb2Smrg if (*format == '%')
533627f7eb2Smrg {
534627f7eb2Smrg format++;
535627f7eb2Smrg continue;
536627f7eb2Smrg }
537627f7eb2Smrg
538627f7eb2Smrg if (ISDIGIT (*format))
539627f7eb2Smrg {
540627f7eb2Smrg /* This is a position specifier. For example, the number
541627f7eb2Smrg 12 in the format string "%12$d", which specifies the third
542627f7eb2Smrg argument of the va_list, formatted in %d format.
543627f7eb2Smrg For details, see "man 3 printf". */
544627f7eb2Smrg pos = atoi(format) - 1;
545627f7eb2Smrg gcc_assert (pos >= 0);
546627f7eb2Smrg while (ISDIGIT(*format))
547627f7eb2Smrg format++;
548627f7eb2Smrg gcc_assert (*format == '$');
549627f7eb2Smrg format++;
550627f7eb2Smrg }
551627f7eb2Smrg else
552627f7eb2Smrg pos++;
553627f7eb2Smrg
554627f7eb2Smrg c = *format++;
555627f7eb2Smrg
556627f7eb2Smrg if (pos > maxpos)
557627f7eb2Smrg maxpos = pos;
558627f7eb2Smrg
559627f7eb2Smrg switch (c)
560627f7eb2Smrg {
561627f7eb2Smrg case 'C':
562627f7eb2Smrg arg[pos].type = TYPE_CURRENTLOC;
563627f7eb2Smrg break;
564627f7eb2Smrg
565627f7eb2Smrg case 'L':
566627f7eb2Smrg arg[pos].type = TYPE_LOCUS;
567627f7eb2Smrg break;
568627f7eb2Smrg
569627f7eb2Smrg case 'd':
570627f7eb2Smrg case 'i':
571627f7eb2Smrg arg[pos].type = TYPE_INTEGER;
572627f7eb2Smrg break;
573627f7eb2Smrg
574627f7eb2Smrg case 'u':
575627f7eb2Smrg arg[pos].type = TYPE_UINTEGER;
576627f7eb2Smrg break;
577627f7eb2Smrg
578627f7eb2Smrg case 'l':
579627f7eb2Smrg c = *format++;
580627f7eb2Smrg if (c == 'u')
581627f7eb2Smrg arg[pos].type = TYPE_ULONGINT;
582627f7eb2Smrg else if (c == 'i' || c == 'd')
583627f7eb2Smrg arg[pos].type = TYPE_LONGINT;
584627f7eb2Smrg else
585627f7eb2Smrg gcc_unreachable ();
586627f7eb2Smrg break;
587627f7eb2Smrg
588627f7eb2Smrg case 'c':
589627f7eb2Smrg arg[pos].type = TYPE_CHAR;
590627f7eb2Smrg break;
591627f7eb2Smrg
592627f7eb2Smrg case 's':
593627f7eb2Smrg arg[pos].type = TYPE_STRING;
594627f7eb2Smrg break;
595627f7eb2Smrg
596627f7eb2Smrg default:
597627f7eb2Smrg gcc_unreachable ();
598627f7eb2Smrg }
599627f7eb2Smrg
600627f7eb2Smrg spec[n++].pos = pos;
601627f7eb2Smrg }
602627f7eb2Smrg
603627f7eb2Smrg /* Then convert the values for each %-style argument. */
604627f7eb2Smrg for (pos = 0; pos <= maxpos; pos++)
605627f7eb2Smrg {
606627f7eb2Smrg gcc_assert (arg[pos].type != NOTYPE);
607627f7eb2Smrg switch (arg[pos].type)
608627f7eb2Smrg {
609627f7eb2Smrg case TYPE_CURRENTLOC:
610627f7eb2Smrg loc = &gfc_current_locus;
611627f7eb2Smrg /* Fall through. */
612627f7eb2Smrg
613627f7eb2Smrg case TYPE_LOCUS:
614627f7eb2Smrg if (arg[pos].type == TYPE_LOCUS)
615627f7eb2Smrg loc = va_arg (argp, locus *);
616627f7eb2Smrg
617627f7eb2Smrg if (have_l1)
618627f7eb2Smrg {
619627f7eb2Smrg l2 = loc;
620627f7eb2Smrg arg[pos].u.stringval = "(2)";
621*4c3eb207Smrg /* Point %C first offending character not the last good one. */
622*4c3eb207Smrg if (arg[pos].type == TYPE_CURRENTLOC && *l2->nextc != '\0')
623*4c3eb207Smrg l2->nextc++;
624627f7eb2Smrg }
625627f7eb2Smrg else
626627f7eb2Smrg {
627627f7eb2Smrg l1 = loc;
628627f7eb2Smrg have_l1 = 1;
629627f7eb2Smrg arg[pos].u.stringval = "(1)";
630*4c3eb207Smrg /* Point %C first offending character not the last good one. */
631*4c3eb207Smrg if (arg[pos].type == TYPE_CURRENTLOC && *l1->nextc != '\0')
632*4c3eb207Smrg l1->nextc++;
633627f7eb2Smrg }
634627f7eb2Smrg break;
635627f7eb2Smrg
636627f7eb2Smrg case TYPE_INTEGER:
637627f7eb2Smrg arg[pos].u.intval = va_arg (argp, int);
638627f7eb2Smrg break;
639627f7eb2Smrg
640627f7eb2Smrg case TYPE_UINTEGER:
641627f7eb2Smrg arg[pos].u.uintval = va_arg (argp, unsigned int);
642627f7eb2Smrg break;
643627f7eb2Smrg
644627f7eb2Smrg case TYPE_LONGINT:
645627f7eb2Smrg arg[pos].u.longintval = va_arg (argp, long int);
646627f7eb2Smrg break;
647627f7eb2Smrg
648627f7eb2Smrg case TYPE_ULONGINT:
649627f7eb2Smrg arg[pos].u.ulongintval = va_arg (argp, unsigned long int);
650627f7eb2Smrg break;
651627f7eb2Smrg
652627f7eb2Smrg case TYPE_CHAR:
653627f7eb2Smrg arg[pos].u.charval = (char) va_arg (argp, int);
654627f7eb2Smrg break;
655627f7eb2Smrg
656627f7eb2Smrg case TYPE_STRING:
657627f7eb2Smrg arg[pos].u.stringval = (const char *) va_arg (argp, char *);
658627f7eb2Smrg break;
659627f7eb2Smrg
660627f7eb2Smrg default:
661627f7eb2Smrg gcc_unreachable ();
662627f7eb2Smrg }
663627f7eb2Smrg }
664627f7eb2Smrg
665627f7eb2Smrg for (n = 0; spec[n].pos >= 0; n++)
666627f7eb2Smrg spec[n].u = arg[spec[n].pos].u;
667627f7eb2Smrg
668627f7eb2Smrg /* Show the current loci if we have to. */
669627f7eb2Smrg if (have_l1)
670627f7eb2Smrg show_loci (l1, l2);
671627f7eb2Smrg
672627f7eb2Smrg if (*type)
673627f7eb2Smrg {
674627f7eb2Smrg error_string (type);
675627f7eb2Smrg error_char (' ');
676627f7eb2Smrg }
677627f7eb2Smrg
678627f7eb2Smrg have_l1 = 0;
679627f7eb2Smrg format = format0;
680627f7eb2Smrg n = 0;
681627f7eb2Smrg
682627f7eb2Smrg for (; *format; format++)
683627f7eb2Smrg {
684627f7eb2Smrg if (*format != '%')
685627f7eb2Smrg {
686627f7eb2Smrg error_char (*format);
687627f7eb2Smrg continue;
688627f7eb2Smrg }
689627f7eb2Smrg
690627f7eb2Smrg format++;
691627f7eb2Smrg if (ISDIGIT (*format))
692627f7eb2Smrg {
693627f7eb2Smrg /* This is a position specifier. See comment above. */
694627f7eb2Smrg while (ISDIGIT (*format))
695627f7eb2Smrg format++;
696627f7eb2Smrg
697627f7eb2Smrg /* Skip over the dollar sign. */
698627f7eb2Smrg format++;
699627f7eb2Smrg }
700627f7eb2Smrg
701627f7eb2Smrg switch (*format)
702627f7eb2Smrg {
703627f7eb2Smrg case '%':
704627f7eb2Smrg error_char ('%');
705627f7eb2Smrg break;
706627f7eb2Smrg
707627f7eb2Smrg case 'c':
708627f7eb2Smrg error_char (spec[n++].u.charval);
709627f7eb2Smrg break;
710627f7eb2Smrg
711627f7eb2Smrg case 's':
712627f7eb2Smrg case 'C': /* Current locus */
713627f7eb2Smrg case 'L': /* Specified locus */
714627f7eb2Smrg error_string (spec[n++].u.stringval);
715627f7eb2Smrg break;
716627f7eb2Smrg
717627f7eb2Smrg case 'd':
718627f7eb2Smrg case 'i':
719627f7eb2Smrg error_integer (spec[n++].u.intval);
720627f7eb2Smrg break;
721627f7eb2Smrg
722627f7eb2Smrg case 'u':
723627f7eb2Smrg error_uinteger (spec[n++].u.uintval);
724627f7eb2Smrg break;
725627f7eb2Smrg
726627f7eb2Smrg case 'l':
727627f7eb2Smrg format++;
728627f7eb2Smrg if (*format == 'u')
729627f7eb2Smrg error_uinteger (spec[n++].u.ulongintval);
730627f7eb2Smrg else
731627f7eb2Smrg error_integer (spec[n++].u.longintval);
732627f7eb2Smrg break;
733627f7eb2Smrg
734627f7eb2Smrg }
735627f7eb2Smrg }
736627f7eb2Smrg
737627f7eb2Smrg error_char ('\n');
738627f7eb2Smrg }
739627f7eb2Smrg
740627f7eb2Smrg
741627f7eb2Smrg /* Wrapper for error_print(). */
742627f7eb2Smrg
743627f7eb2Smrg static void
error_printf(const char * gmsgid,...)744627f7eb2Smrg error_printf (const char *gmsgid, ...)
745627f7eb2Smrg {
746627f7eb2Smrg va_list argp;
747627f7eb2Smrg
748627f7eb2Smrg va_start (argp, gmsgid);
749627f7eb2Smrg error_print ("", _(gmsgid), argp);
750627f7eb2Smrg va_end (argp);
751627f7eb2Smrg }
752627f7eb2Smrg
753627f7eb2Smrg
754627f7eb2Smrg /* Clear any output buffered in a pretty-print output_buffer. */
755627f7eb2Smrg
756627f7eb2Smrg static void
gfc_clear_pp_buffer(output_buffer * this_buffer)757627f7eb2Smrg gfc_clear_pp_buffer (output_buffer *this_buffer)
758627f7eb2Smrg {
759627f7eb2Smrg pretty_printer *pp = global_dc->printer;
760627f7eb2Smrg output_buffer *tmp_buffer = pp->buffer;
761627f7eb2Smrg pp->buffer = this_buffer;
762627f7eb2Smrg pp_clear_output_area (pp);
763627f7eb2Smrg pp->buffer = tmp_buffer;
764627f7eb2Smrg /* We need to reset last_location, otherwise we may skip caret lines
765627f7eb2Smrg when we actually give a diagnostic. */
766627f7eb2Smrg global_dc->last_location = UNKNOWN_LOCATION;
767627f7eb2Smrg }
768627f7eb2Smrg
769*4c3eb207Smrg /* The currently-printing diagnostic, for use by gfc_format_decoder,
770*4c3eb207Smrg for colorizing %C and %L. */
771*4c3eb207Smrg
772*4c3eb207Smrg static diagnostic_info *curr_diagnostic;
773*4c3eb207Smrg
774*4c3eb207Smrg /* A helper function to call diagnostic_report_diagnostic, while setting
775*4c3eb207Smrg curr_diagnostic for the duration of the call. */
776*4c3eb207Smrg
777*4c3eb207Smrg static bool
gfc_report_diagnostic(diagnostic_info * diagnostic)778*4c3eb207Smrg gfc_report_diagnostic (diagnostic_info *diagnostic)
779*4c3eb207Smrg {
780*4c3eb207Smrg gcc_assert (diagnostic != NULL);
781*4c3eb207Smrg curr_diagnostic = diagnostic;
782*4c3eb207Smrg bool ret = diagnostic_report_diagnostic (global_dc, diagnostic);
783*4c3eb207Smrg curr_diagnostic = NULL;
784*4c3eb207Smrg return ret;
785*4c3eb207Smrg }
786627f7eb2Smrg
787627f7eb2Smrg /* This is just a helper function to avoid duplicating the logic of
788627f7eb2Smrg gfc_warning. */
789627f7eb2Smrg
790627f7eb2Smrg static bool
gfc_warning(int opt,const char * gmsgid,va_list ap)791627f7eb2Smrg gfc_warning (int opt, const char *gmsgid, va_list ap)
792627f7eb2Smrg {
793627f7eb2Smrg va_list argp;
794627f7eb2Smrg va_copy (argp, ap);
795627f7eb2Smrg
796627f7eb2Smrg diagnostic_info diagnostic;
797627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
798627f7eb2Smrg bool fatal_errors = global_dc->fatal_errors;
799627f7eb2Smrg pretty_printer *pp = global_dc->printer;
800627f7eb2Smrg output_buffer *tmp_buffer = pp->buffer;
801627f7eb2Smrg
802627f7eb2Smrg gfc_clear_pp_buffer (pp_warning_buffer);
803627f7eb2Smrg
804627f7eb2Smrg if (buffered_p)
805627f7eb2Smrg {
806627f7eb2Smrg pp->buffer = pp_warning_buffer;
807627f7eb2Smrg global_dc->fatal_errors = false;
808627f7eb2Smrg /* To prevent -fmax-errors= triggering. */
809627f7eb2Smrg --werrorcount;
810627f7eb2Smrg }
811627f7eb2Smrg
812627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
813627f7eb2Smrg DK_WARNING);
814627f7eb2Smrg diagnostic.option_index = opt;
815*4c3eb207Smrg bool ret = gfc_report_diagnostic (&diagnostic);
816627f7eb2Smrg
817627f7eb2Smrg if (buffered_p)
818627f7eb2Smrg {
819627f7eb2Smrg pp->buffer = tmp_buffer;
820627f7eb2Smrg global_dc->fatal_errors = fatal_errors;
821627f7eb2Smrg
822627f7eb2Smrg warningcount_buffered = 0;
823627f7eb2Smrg werrorcount_buffered = 0;
824627f7eb2Smrg /* Undo the above --werrorcount if not Werror, otherwise
825627f7eb2Smrg werrorcount is correct already. */
826627f7eb2Smrg if (!ret)
827627f7eb2Smrg ++werrorcount;
828627f7eb2Smrg else if (diagnostic.kind == DK_ERROR)
829627f7eb2Smrg ++werrorcount_buffered;
830627f7eb2Smrg else
831627f7eb2Smrg ++werrorcount, --warningcount, ++warningcount_buffered;
832627f7eb2Smrg }
833627f7eb2Smrg
834627f7eb2Smrg va_end (argp);
835627f7eb2Smrg return ret;
836627f7eb2Smrg }
837627f7eb2Smrg
838627f7eb2Smrg /* Issue a warning. */
839627f7eb2Smrg
840627f7eb2Smrg bool
gfc_warning(int opt,const char * gmsgid,...)841627f7eb2Smrg gfc_warning (int opt, const char *gmsgid, ...)
842627f7eb2Smrg {
843627f7eb2Smrg va_list argp;
844627f7eb2Smrg
845627f7eb2Smrg va_start (argp, gmsgid);
846627f7eb2Smrg bool ret = gfc_warning (opt, gmsgid, argp);
847627f7eb2Smrg va_end (argp);
848627f7eb2Smrg return ret;
849627f7eb2Smrg }
850627f7eb2Smrg
851627f7eb2Smrg
852627f7eb2Smrg /* Whether, for a feature included in a given standard set (GFC_STD_*),
853627f7eb2Smrg we should issue an error or a warning, or be quiet. */
854627f7eb2Smrg
855627f7eb2Smrg notification
gfc_notification_std(int std)856627f7eb2Smrg gfc_notification_std (int std)
857627f7eb2Smrg {
858627f7eb2Smrg bool warning;
859627f7eb2Smrg
860627f7eb2Smrg warning = ((gfc_option.warn_std & std) != 0) && !inhibit_warnings;
861627f7eb2Smrg if ((gfc_option.allow_std & std) != 0 && !warning)
862627f7eb2Smrg return SILENT;
863627f7eb2Smrg
864627f7eb2Smrg return warning ? WARNING : ERROR;
865627f7eb2Smrg }
866627f7eb2Smrg
867627f7eb2Smrg
868627f7eb2Smrg /* Return a string describing the nature of a standard violation
869627f7eb2Smrg * and/or the relevant version of the standard. */
870627f7eb2Smrg
871627f7eb2Smrg char const*
notify_std_msg(int std)872627f7eb2Smrg notify_std_msg(int std)
873627f7eb2Smrg {
874627f7eb2Smrg
875627f7eb2Smrg if (std & GFC_STD_F2018_DEL)
876627f7eb2Smrg return _("Fortran 2018 deleted feature:");
877627f7eb2Smrg else if (std & GFC_STD_F2018_OBS)
878627f7eb2Smrg return _("Fortran 2018 obsolescent feature:");
879627f7eb2Smrg else if (std & GFC_STD_F2018)
880627f7eb2Smrg return _("Fortran 2018:");
881627f7eb2Smrg else if (std & GFC_STD_F2008_OBS)
882627f7eb2Smrg return _("Fortran 2008 obsolescent feature:");
883627f7eb2Smrg else if (std & GFC_STD_F2008)
884627f7eb2Smrg return "Fortran 2008:";
885627f7eb2Smrg else if (std & GFC_STD_F2003)
886627f7eb2Smrg return "Fortran 2003:";
887627f7eb2Smrg else if (std & GFC_STD_GNU)
888627f7eb2Smrg return _("GNU Extension:");
889627f7eb2Smrg else if (std & GFC_STD_LEGACY)
890627f7eb2Smrg return _("Legacy Extension:");
891627f7eb2Smrg else if (std & GFC_STD_F95_OBS)
892627f7eb2Smrg return _("Obsolescent feature:");
893627f7eb2Smrg else if (std & GFC_STD_F95_DEL)
894627f7eb2Smrg return _("Deleted feature:");
895627f7eb2Smrg else
896627f7eb2Smrg gcc_unreachable ();
897627f7eb2Smrg }
898627f7eb2Smrg
899627f7eb2Smrg
900627f7eb2Smrg /* Possibly issue a warning/error about use of a nonstandard (or deleted)
901627f7eb2Smrg feature. An error/warning will be issued if the currently selected
902627f7eb2Smrg standard does not contain the requested bits. Return false if
903627f7eb2Smrg an error is generated. */
904627f7eb2Smrg
905627f7eb2Smrg bool
gfc_notify_std(int std,const char * gmsgid,...)906627f7eb2Smrg gfc_notify_std (int std, const char *gmsgid, ...)
907627f7eb2Smrg {
908627f7eb2Smrg va_list argp;
909627f7eb2Smrg const char *msg, *msg2;
910627f7eb2Smrg char *buffer;
911627f7eb2Smrg
912627f7eb2Smrg /* Determine whether an error or a warning is needed. */
913627f7eb2Smrg const int wstd = std & gfc_option.warn_std; /* Standard to warn about. */
914627f7eb2Smrg const int estd = std & ~gfc_option.allow_std; /* Standard to error about. */
915627f7eb2Smrg const bool warning = (wstd != 0) && !inhibit_warnings;
916627f7eb2Smrg const bool error = (estd != 0);
917627f7eb2Smrg
918627f7eb2Smrg if (!error && !warning)
919627f7eb2Smrg return true;
920627f7eb2Smrg if (suppress_errors)
921627f7eb2Smrg return !error;
922627f7eb2Smrg
923627f7eb2Smrg if (error)
924627f7eb2Smrg msg = notify_std_msg (estd);
925627f7eb2Smrg else
926627f7eb2Smrg msg = notify_std_msg (wstd);
927627f7eb2Smrg
928627f7eb2Smrg msg2 = _(gmsgid);
929627f7eb2Smrg buffer = (char *) alloca (strlen (msg) + strlen (msg2) + 2);
930627f7eb2Smrg strcpy (buffer, msg);
931627f7eb2Smrg strcat (buffer, " ");
932627f7eb2Smrg strcat (buffer, msg2);
933627f7eb2Smrg
934627f7eb2Smrg va_start (argp, gmsgid);
935627f7eb2Smrg if (error)
936627f7eb2Smrg gfc_error_opt (0, buffer, argp);
937627f7eb2Smrg else
938627f7eb2Smrg gfc_warning (0, buffer, argp);
939627f7eb2Smrg va_end (argp);
940627f7eb2Smrg
941627f7eb2Smrg if (error)
942627f7eb2Smrg return false;
943627f7eb2Smrg else
944627f7eb2Smrg return (warning && !warnings_are_errors);
945627f7eb2Smrg }
946627f7eb2Smrg
947627f7eb2Smrg
948627f7eb2Smrg /* Called from output_format -- during diagnostic message processing
949627f7eb2Smrg to handle Fortran specific format specifiers with the following meanings:
950627f7eb2Smrg
951627f7eb2Smrg %C Current locus (no argument)
952627f7eb2Smrg %L Takes locus argument
953627f7eb2Smrg */
954627f7eb2Smrg static bool
gfc_format_decoder(pretty_printer * pp,text_info * text,const char * spec,int precision,bool wide,bool set_locus,bool hash,bool * quoted,const char ** buffer_ptr)955627f7eb2Smrg gfc_format_decoder (pretty_printer *pp, text_info *text, const char *spec,
956627f7eb2Smrg int precision, bool wide, bool set_locus, bool hash,
957627f7eb2Smrg bool *quoted, const char **buffer_ptr)
958627f7eb2Smrg {
959627f7eb2Smrg switch (*spec)
960627f7eb2Smrg {
961627f7eb2Smrg case 'C':
962627f7eb2Smrg case 'L':
963627f7eb2Smrg {
964627f7eb2Smrg static const char *result[2] = { "(1)", "(2)" };
965627f7eb2Smrg locus *loc;
966627f7eb2Smrg if (*spec == 'C')
967627f7eb2Smrg loc = &gfc_current_locus;
968627f7eb2Smrg else
969627f7eb2Smrg loc = va_arg (*text->args_ptr, locus *);
970627f7eb2Smrg gcc_assert (loc->nextc - loc->lb->line >= 0);
971627f7eb2Smrg unsigned int offset = loc->nextc - loc->lb->line;
972*4c3eb207Smrg if (*spec == 'C' && *loc->nextc != '\0')
973*4c3eb207Smrg /* Point %C first offending character not the last good one. */
974*4c3eb207Smrg offset++;
975627f7eb2Smrg /* If location[0] != UNKNOWN_LOCATION means that we already
976627f7eb2Smrg processed one of %C/%L. */
977627f7eb2Smrg int loc_num = text->get_location (0) == UNKNOWN_LOCATION ? 0 : 1;
978627f7eb2Smrg location_t src_loc
979627f7eb2Smrg = linemap_position_for_loc_and_offset (line_table,
980627f7eb2Smrg loc->lb->location,
981627f7eb2Smrg offset);
982627f7eb2Smrg text->set_location (loc_num, src_loc, SHOW_RANGE_WITH_CARET);
983*4c3eb207Smrg /* Colorize the markers to match the color choices of
984*4c3eb207Smrg diagnostic_show_locus (the initial location has a color given
985*4c3eb207Smrg by the "kind" of the diagnostic, the secondary location has
986*4c3eb207Smrg color "range1"). */
987*4c3eb207Smrg gcc_assert (curr_diagnostic != NULL);
988*4c3eb207Smrg const char *color
989*4c3eb207Smrg = (loc_num
990*4c3eb207Smrg ? "range1"
991*4c3eb207Smrg : diagnostic_get_color_for_kind (curr_diagnostic->kind));
992*4c3eb207Smrg pp_string (pp, colorize_start (pp_show_color (pp), color));
993627f7eb2Smrg pp_string (pp, result[loc_num]);
994*4c3eb207Smrg pp_string (pp, colorize_stop (pp_show_color (pp)));
995627f7eb2Smrg return true;
996627f7eb2Smrg }
997627f7eb2Smrg default:
998627f7eb2Smrg /* Fall through info the middle-end decoder, as e.g. stor-layout.c
999627f7eb2Smrg etc. diagnostics can use the FE printer while the FE is still
1000627f7eb2Smrg active. */
1001627f7eb2Smrg return default_tree_printer (pp, text, spec, precision, wide,
1002627f7eb2Smrg set_locus, hash, quoted, buffer_ptr);
1003627f7eb2Smrg }
1004627f7eb2Smrg }
1005627f7eb2Smrg
1006627f7eb2Smrg /* Return a malloc'd string describing the kind of diagnostic. The
1007627f7eb2Smrg caller is responsible for freeing the memory. */
1008627f7eb2Smrg static char *
gfc_diagnostic_build_kind_prefix(diagnostic_context * context,const diagnostic_info * diagnostic)1009627f7eb2Smrg gfc_diagnostic_build_kind_prefix (diagnostic_context *context,
1010627f7eb2Smrg const diagnostic_info *diagnostic)
1011627f7eb2Smrg {
1012627f7eb2Smrg static const char *const diagnostic_kind_text[] = {
1013627f7eb2Smrg #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (T),
1014627f7eb2Smrg #include "gfc-diagnostic.def"
1015627f7eb2Smrg #undef DEFINE_DIAGNOSTIC_KIND
1016627f7eb2Smrg "must-not-happen"
1017627f7eb2Smrg };
1018627f7eb2Smrg static const char *const diagnostic_kind_color[] = {
1019627f7eb2Smrg #define DEFINE_DIAGNOSTIC_KIND(K, T, C) (C),
1020627f7eb2Smrg #include "gfc-diagnostic.def"
1021627f7eb2Smrg #undef DEFINE_DIAGNOSTIC_KIND
1022627f7eb2Smrg NULL
1023627f7eb2Smrg };
1024627f7eb2Smrg gcc_assert (diagnostic->kind < DK_LAST_DIAGNOSTIC_KIND);
1025627f7eb2Smrg const char *text = _(diagnostic_kind_text[diagnostic->kind]);
1026627f7eb2Smrg const char *text_cs = "", *text_ce = "";
1027627f7eb2Smrg pretty_printer *pp = context->printer;
1028627f7eb2Smrg
1029627f7eb2Smrg if (diagnostic_kind_color[diagnostic->kind])
1030627f7eb2Smrg {
1031627f7eb2Smrg text_cs = colorize_start (pp_show_color (pp),
1032627f7eb2Smrg diagnostic_kind_color[diagnostic->kind]);
1033627f7eb2Smrg text_ce = colorize_stop (pp_show_color (pp));
1034627f7eb2Smrg }
1035627f7eb2Smrg return build_message_string ("%s%s:%s ", text_cs, text, text_ce);
1036627f7eb2Smrg }
1037627f7eb2Smrg
1038627f7eb2Smrg /* Return a malloc'd string describing a location. The caller is
1039627f7eb2Smrg responsible for freeing the memory. */
1040627f7eb2Smrg static char *
gfc_diagnostic_build_locus_prefix(diagnostic_context * context,expanded_location s)1041627f7eb2Smrg gfc_diagnostic_build_locus_prefix (diagnostic_context *context,
1042627f7eb2Smrg expanded_location s)
1043627f7eb2Smrg {
1044627f7eb2Smrg pretty_printer *pp = context->printer;
1045627f7eb2Smrg const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
1046627f7eb2Smrg const char *locus_ce = colorize_stop (pp_show_color (pp));
1047627f7eb2Smrg return (s.file == NULL
1048627f7eb2Smrg ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
1049627f7eb2Smrg : !strcmp (s.file, N_("<built-in>"))
1050627f7eb2Smrg ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
1051627f7eb2Smrg : context->show_column
1052627f7eb2Smrg ? build_message_string ("%s%s:%d:%d:%s", locus_cs, s.file, s.line,
1053627f7eb2Smrg s.column, locus_ce)
1054627f7eb2Smrg : build_message_string ("%s%s:%d:%s", locus_cs, s.file, s.line, locus_ce));
1055627f7eb2Smrg }
1056627f7eb2Smrg
1057627f7eb2Smrg /* Return a malloc'd string describing two locations. The caller is
1058627f7eb2Smrg responsible for freeing the memory. */
1059627f7eb2Smrg static char *
gfc_diagnostic_build_locus_prefix(diagnostic_context * context,expanded_location s,expanded_location s2)1060627f7eb2Smrg gfc_diagnostic_build_locus_prefix (diagnostic_context *context,
1061627f7eb2Smrg expanded_location s, expanded_location s2)
1062627f7eb2Smrg {
1063627f7eb2Smrg pretty_printer *pp = context->printer;
1064627f7eb2Smrg const char *locus_cs = colorize_start (pp_show_color (pp), "locus");
1065627f7eb2Smrg const char *locus_ce = colorize_stop (pp_show_color (pp));
1066627f7eb2Smrg
1067627f7eb2Smrg return (s.file == NULL
1068627f7eb2Smrg ? build_message_string ("%s%s:%s", locus_cs, progname, locus_ce )
1069627f7eb2Smrg : !strcmp (s.file, N_("<built-in>"))
1070627f7eb2Smrg ? build_message_string ("%s%s:%s", locus_cs, s.file, locus_ce)
1071627f7eb2Smrg : context->show_column
1072627f7eb2Smrg ? build_message_string ("%s%s:%d:%d-%d:%s", locus_cs, s.file, s.line,
1073627f7eb2Smrg MIN (s.column, s2.column),
1074627f7eb2Smrg MAX (s.column, s2.column), locus_ce)
1075627f7eb2Smrg : build_message_string ("%s%s:%d:%s", locus_cs, s.file, s.line,
1076627f7eb2Smrg locus_ce));
1077627f7eb2Smrg }
1078627f7eb2Smrg
1079627f7eb2Smrg /* This function prints the locus (file:line:column), the diagnostic kind
1080627f7eb2Smrg (Error, Warning) and (optionally) the relevant lines of code with
1081627f7eb2Smrg annotation lines with '1' and/or '2' below them.
1082627f7eb2Smrg
1083627f7eb2Smrg With -fdiagnostic-show-caret (the default) it prints:
1084627f7eb2Smrg
1085627f7eb2Smrg [locus of primary range]:
1086627f7eb2Smrg
1087627f7eb2Smrg some code
1088627f7eb2Smrg 1
1089627f7eb2Smrg Error: Some error at (1)
1090627f7eb2Smrg
1091627f7eb2Smrg With -fno-diagnostic-show-caret or if the primary range is not
1092627f7eb2Smrg valid, it prints:
1093627f7eb2Smrg
1094627f7eb2Smrg [locus of primary range]: Error: Some error at (1) and (2)
1095627f7eb2Smrg */
1096627f7eb2Smrg static void
gfc_diagnostic_starter(diagnostic_context * context,diagnostic_info * diagnostic)1097627f7eb2Smrg gfc_diagnostic_starter (diagnostic_context *context,
1098627f7eb2Smrg diagnostic_info *diagnostic)
1099627f7eb2Smrg {
1100627f7eb2Smrg char * kind_prefix = gfc_diagnostic_build_kind_prefix (context, diagnostic);
1101627f7eb2Smrg
1102627f7eb2Smrg expanded_location s1 = diagnostic_expand_location (diagnostic);
1103627f7eb2Smrg expanded_location s2;
1104627f7eb2Smrg bool one_locus = diagnostic->richloc->get_num_locations () < 2;
1105627f7eb2Smrg bool same_locus = false;
1106627f7eb2Smrg
1107627f7eb2Smrg if (!one_locus)
1108627f7eb2Smrg {
1109627f7eb2Smrg s2 = diagnostic_expand_location (diagnostic, 1);
1110627f7eb2Smrg same_locus = diagnostic_same_line (context, s1, s2);
1111627f7eb2Smrg }
1112627f7eb2Smrg
1113627f7eb2Smrg char * locus_prefix = (one_locus || !same_locus)
1114627f7eb2Smrg ? gfc_diagnostic_build_locus_prefix (context, s1)
1115627f7eb2Smrg : gfc_diagnostic_build_locus_prefix (context, s1, s2);
1116627f7eb2Smrg
1117627f7eb2Smrg if (!context->show_caret
1118627f7eb2Smrg || diagnostic_location (diagnostic, 0) <= BUILTINS_LOCATION
1119627f7eb2Smrg || diagnostic_location (diagnostic, 0) == context->last_location)
1120627f7eb2Smrg {
1121627f7eb2Smrg pp_set_prefix (context->printer,
1122627f7eb2Smrg concat (locus_prefix, " ", kind_prefix, NULL));
1123627f7eb2Smrg free (locus_prefix);
1124627f7eb2Smrg
1125627f7eb2Smrg if (one_locus || same_locus)
1126627f7eb2Smrg {
1127627f7eb2Smrg free (kind_prefix);
1128627f7eb2Smrg return;
1129627f7eb2Smrg }
1130627f7eb2Smrg /* In this case, we print the previous locus and prefix as:
1131627f7eb2Smrg
1132627f7eb2Smrg [locus]:[prefix]: (1)
1133627f7eb2Smrg
1134627f7eb2Smrg and we flush with a new line before setting the new prefix. */
1135627f7eb2Smrg pp_string (context->printer, "(1)");
1136627f7eb2Smrg pp_newline (context->printer);
1137627f7eb2Smrg locus_prefix = gfc_diagnostic_build_locus_prefix (context, s2);
1138627f7eb2Smrg pp_set_prefix (context->printer,
1139627f7eb2Smrg concat (locus_prefix, " ", kind_prefix, NULL));
1140627f7eb2Smrg free (kind_prefix);
1141627f7eb2Smrg free (locus_prefix);
1142627f7eb2Smrg }
1143627f7eb2Smrg else
1144627f7eb2Smrg {
1145627f7eb2Smrg pp_verbatim (context->printer, "%s", locus_prefix);
1146627f7eb2Smrg free (locus_prefix);
1147627f7eb2Smrg /* Fortran uses an empty line between locus and caret line. */
1148627f7eb2Smrg pp_newline (context->printer);
1149*4c3eb207Smrg pp_set_prefix (context->printer, NULL);
1150*4c3eb207Smrg pp_newline (context->printer);
1151627f7eb2Smrg diagnostic_show_locus (context, diagnostic->richloc, diagnostic->kind);
1152627f7eb2Smrg /* If the caret line was shown, the prefix does not contain the
1153627f7eb2Smrg locus. */
1154627f7eb2Smrg pp_set_prefix (context->printer, kind_prefix);
1155627f7eb2Smrg }
1156627f7eb2Smrg }
1157627f7eb2Smrg
1158627f7eb2Smrg static void
gfc_diagnostic_start_span(diagnostic_context * context,expanded_location exploc)1159627f7eb2Smrg gfc_diagnostic_start_span (diagnostic_context *context,
1160627f7eb2Smrg expanded_location exploc)
1161627f7eb2Smrg {
1162627f7eb2Smrg char *locus_prefix;
1163627f7eb2Smrg locus_prefix = gfc_diagnostic_build_locus_prefix (context, exploc);
1164627f7eb2Smrg pp_verbatim (context->printer, "%s", locus_prefix);
1165627f7eb2Smrg free (locus_prefix);
1166627f7eb2Smrg pp_newline (context->printer);
1167627f7eb2Smrg /* Fortran uses an empty line between locus and caret line. */
1168627f7eb2Smrg pp_newline (context->printer);
1169627f7eb2Smrg }
1170627f7eb2Smrg
1171627f7eb2Smrg
1172627f7eb2Smrg static void
gfc_diagnostic_finalizer(diagnostic_context * context,diagnostic_info * diagnostic ATTRIBUTE_UNUSED,diagnostic_t orig_diag_kind ATTRIBUTE_UNUSED)1173627f7eb2Smrg gfc_diagnostic_finalizer (diagnostic_context *context,
1174627f7eb2Smrg diagnostic_info *diagnostic ATTRIBUTE_UNUSED,
1175627f7eb2Smrg diagnostic_t orig_diag_kind ATTRIBUTE_UNUSED)
1176627f7eb2Smrg {
1177627f7eb2Smrg pp_destroy_prefix (context->printer);
1178627f7eb2Smrg pp_newline_and_flush (context->printer);
1179627f7eb2Smrg }
1180627f7eb2Smrg
1181627f7eb2Smrg /* Immediate warning (i.e. do not buffer the warning) with an explicit
1182627f7eb2Smrg location. */
1183627f7eb2Smrg
1184627f7eb2Smrg bool
gfc_warning_now_at(location_t loc,int opt,const char * gmsgid,...)1185627f7eb2Smrg gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
1186627f7eb2Smrg {
1187627f7eb2Smrg va_list argp;
1188627f7eb2Smrg diagnostic_info diagnostic;
1189627f7eb2Smrg rich_location rich_loc (line_table, loc);
1190627f7eb2Smrg bool ret;
1191627f7eb2Smrg
1192627f7eb2Smrg va_start (argp, gmsgid);
1193627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_WARNING);
1194627f7eb2Smrg diagnostic.option_index = opt;
1195*4c3eb207Smrg ret = gfc_report_diagnostic (&diagnostic);
1196627f7eb2Smrg va_end (argp);
1197627f7eb2Smrg return ret;
1198627f7eb2Smrg }
1199627f7eb2Smrg
1200627f7eb2Smrg /* Immediate warning (i.e. do not buffer the warning). */
1201627f7eb2Smrg
1202627f7eb2Smrg bool
gfc_warning_now(int opt,const char * gmsgid,...)1203627f7eb2Smrg gfc_warning_now (int opt, const char *gmsgid, ...)
1204627f7eb2Smrg {
1205627f7eb2Smrg va_list argp;
1206627f7eb2Smrg diagnostic_info diagnostic;
1207627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1208627f7eb2Smrg bool ret;
1209627f7eb2Smrg
1210627f7eb2Smrg va_start (argp, gmsgid);
1211627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
1212627f7eb2Smrg DK_WARNING);
1213627f7eb2Smrg diagnostic.option_index = opt;
1214*4c3eb207Smrg ret = gfc_report_diagnostic (&diagnostic);
1215627f7eb2Smrg va_end (argp);
1216627f7eb2Smrg return ret;
1217627f7eb2Smrg }
1218627f7eb2Smrg
1219627f7eb2Smrg /* Internal warning, do not buffer. */
1220627f7eb2Smrg
1221627f7eb2Smrg bool
gfc_warning_internal(int opt,const char * gmsgid,...)1222627f7eb2Smrg gfc_warning_internal (int opt, const char *gmsgid, ...)
1223627f7eb2Smrg {
1224627f7eb2Smrg va_list argp;
1225627f7eb2Smrg diagnostic_info diagnostic;
1226627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1227627f7eb2Smrg bool ret;
1228627f7eb2Smrg
1229627f7eb2Smrg va_start (argp, gmsgid);
1230627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc,
1231627f7eb2Smrg DK_WARNING);
1232627f7eb2Smrg diagnostic.option_index = opt;
1233*4c3eb207Smrg ret = gfc_report_diagnostic (&diagnostic);
1234627f7eb2Smrg va_end (argp);
1235627f7eb2Smrg return ret;
1236627f7eb2Smrg }
1237627f7eb2Smrg
1238627f7eb2Smrg /* Immediate error (i.e. do not buffer). */
1239627f7eb2Smrg
1240627f7eb2Smrg void
gfc_error_now(const char * gmsgid,...)1241627f7eb2Smrg gfc_error_now (const char *gmsgid, ...)
1242627f7eb2Smrg {
1243627f7eb2Smrg va_list argp;
1244627f7eb2Smrg diagnostic_info diagnostic;
1245627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1246627f7eb2Smrg
1247627f7eb2Smrg error_buffer.flag = true;
1248627f7eb2Smrg
1249627f7eb2Smrg va_start (argp, gmsgid);
1250627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ERROR);
1251*4c3eb207Smrg gfc_report_diagnostic (&diagnostic);
1252627f7eb2Smrg va_end (argp);
1253627f7eb2Smrg }
1254627f7eb2Smrg
1255627f7eb2Smrg
1256627f7eb2Smrg /* Fatal error, never returns. */
1257627f7eb2Smrg
1258627f7eb2Smrg void
gfc_fatal_error(const char * gmsgid,...)1259627f7eb2Smrg gfc_fatal_error (const char *gmsgid, ...)
1260627f7eb2Smrg {
1261627f7eb2Smrg va_list argp;
1262627f7eb2Smrg diagnostic_info diagnostic;
1263627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1264627f7eb2Smrg
1265627f7eb2Smrg va_start (argp, gmsgid);
1266627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_FATAL);
1267*4c3eb207Smrg gfc_report_diagnostic (&diagnostic);
1268627f7eb2Smrg va_end (argp);
1269627f7eb2Smrg
1270627f7eb2Smrg gcc_unreachable ();
1271627f7eb2Smrg }
1272627f7eb2Smrg
1273627f7eb2Smrg /* Clear the warning flag. */
1274627f7eb2Smrg
1275627f7eb2Smrg void
gfc_clear_warning(void)1276627f7eb2Smrg gfc_clear_warning (void)
1277627f7eb2Smrg {
1278627f7eb2Smrg gfc_clear_pp_buffer (pp_warning_buffer);
1279627f7eb2Smrg warningcount_buffered = 0;
1280627f7eb2Smrg werrorcount_buffered = 0;
1281627f7eb2Smrg }
1282627f7eb2Smrg
1283627f7eb2Smrg
1284627f7eb2Smrg /* Check to see if any warnings have been saved.
1285627f7eb2Smrg If so, print the warning. */
1286627f7eb2Smrg
1287627f7eb2Smrg void
gfc_warning_check(void)1288627f7eb2Smrg gfc_warning_check (void)
1289627f7eb2Smrg {
1290627f7eb2Smrg if (! gfc_output_buffer_empty_p (pp_warning_buffer))
1291627f7eb2Smrg {
1292627f7eb2Smrg pretty_printer *pp = global_dc->printer;
1293627f7eb2Smrg output_buffer *tmp_buffer = pp->buffer;
1294627f7eb2Smrg pp->buffer = pp_warning_buffer;
1295627f7eb2Smrg pp_really_flush (pp);
1296627f7eb2Smrg warningcount += warningcount_buffered;
1297627f7eb2Smrg werrorcount += werrorcount_buffered;
1298627f7eb2Smrg gcc_assert (warningcount_buffered + werrorcount_buffered == 1);
1299627f7eb2Smrg pp->buffer = tmp_buffer;
1300627f7eb2Smrg diagnostic_action_after_output (global_dc,
1301627f7eb2Smrg warningcount_buffered
1302627f7eb2Smrg ? DK_WARNING : DK_ERROR);
1303627f7eb2Smrg diagnostic_check_max_errors (global_dc, true);
1304627f7eb2Smrg }
1305627f7eb2Smrg }
1306627f7eb2Smrg
1307627f7eb2Smrg
1308627f7eb2Smrg /* Issue an error. */
1309627f7eb2Smrg
1310627f7eb2Smrg static void
gfc_error_opt(int opt,const char * gmsgid,va_list ap)1311627f7eb2Smrg gfc_error_opt (int opt, const char *gmsgid, va_list ap)
1312627f7eb2Smrg {
1313627f7eb2Smrg va_list argp;
1314627f7eb2Smrg va_copy (argp, ap);
1315627f7eb2Smrg bool saved_abort_on_error = false;
1316627f7eb2Smrg
1317627f7eb2Smrg if (warnings_not_errors)
1318627f7eb2Smrg {
1319627f7eb2Smrg gfc_warning (opt, gmsgid, argp);
1320627f7eb2Smrg va_end (argp);
1321627f7eb2Smrg return;
1322627f7eb2Smrg }
1323627f7eb2Smrg
1324627f7eb2Smrg if (suppress_errors)
1325627f7eb2Smrg {
1326627f7eb2Smrg va_end (argp);
1327627f7eb2Smrg return;
1328627f7eb2Smrg }
1329627f7eb2Smrg
1330627f7eb2Smrg diagnostic_info diagnostic;
1331627f7eb2Smrg rich_location richloc (line_table, UNKNOWN_LOCATION);
1332627f7eb2Smrg bool fatal_errors = global_dc->fatal_errors;
1333627f7eb2Smrg pretty_printer *pp = global_dc->printer;
1334627f7eb2Smrg output_buffer *tmp_buffer = pp->buffer;
1335627f7eb2Smrg
1336627f7eb2Smrg gfc_clear_pp_buffer (pp_error_buffer);
1337627f7eb2Smrg
1338627f7eb2Smrg if (buffered_p)
1339627f7eb2Smrg {
1340627f7eb2Smrg /* To prevent -dH from triggering an abort on a buffered error,
1341627f7eb2Smrg save abort_on_error and restore it below. */
1342627f7eb2Smrg saved_abort_on_error = global_dc->abort_on_error;
1343627f7eb2Smrg global_dc->abort_on_error = false;
1344627f7eb2Smrg pp->buffer = pp_error_buffer;
1345627f7eb2Smrg global_dc->fatal_errors = false;
1346627f7eb2Smrg /* To prevent -fmax-errors= triggering, we decrease it before
1347627f7eb2Smrg report_diagnostic increases it. */
1348627f7eb2Smrg --errorcount;
1349627f7eb2Smrg }
1350627f7eb2Smrg
1351627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &richloc, DK_ERROR);
1352*4c3eb207Smrg gfc_report_diagnostic (&diagnostic);
1353627f7eb2Smrg
1354627f7eb2Smrg if (buffered_p)
1355627f7eb2Smrg {
1356627f7eb2Smrg pp->buffer = tmp_buffer;
1357627f7eb2Smrg global_dc->fatal_errors = fatal_errors;
1358627f7eb2Smrg global_dc->abort_on_error = saved_abort_on_error;
1359627f7eb2Smrg
1360627f7eb2Smrg }
1361627f7eb2Smrg
1362627f7eb2Smrg va_end (argp);
1363627f7eb2Smrg }
1364627f7eb2Smrg
1365627f7eb2Smrg
1366627f7eb2Smrg void
gfc_error_opt(int opt,const char * gmsgid,...)1367627f7eb2Smrg gfc_error_opt (int opt, const char *gmsgid, ...)
1368627f7eb2Smrg {
1369627f7eb2Smrg va_list argp;
1370627f7eb2Smrg va_start (argp, gmsgid);
1371627f7eb2Smrg gfc_error_opt (opt, gmsgid, argp);
1372627f7eb2Smrg va_end (argp);
1373627f7eb2Smrg }
1374627f7eb2Smrg
1375627f7eb2Smrg
1376627f7eb2Smrg void
gfc_error(const char * gmsgid,...)1377627f7eb2Smrg gfc_error (const char *gmsgid, ...)
1378627f7eb2Smrg {
1379627f7eb2Smrg va_list argp;
1380627f7eb2Smrg va_start (argp, gmsgid);
1381627f7eb2Smrg gfc_error_opt (0, gmsgid, argp);
1382627f7eb2Smrg va_end (argp);
1383627f7eb2Smrg }
1384627f7eb2Smrg
1385627f7eb2Smrg
1386627f7eb2Smrg /* This shouldn't happen... but sometimes does. */
1387627f7eb2Smrg
1388627f7eb2Smrg void
gfc_internal_error(const char * gmsgid,...)1389627f7eb2Smrg gfc_internal_error (const char *gmsgid, ...)
1390627f7eb2Smrg {
1391627f7eb2Smrg int e, w;
1392627f7eb2Smrg va_list argp;
1393627f7eb2Smrg diagnostic_info diagnostic;
1394627f7eb2Smrg rich_location rich_loc (line_table, UNKNOWN_LOCATION);
1395627f7eb2Smrg
1396627f7eb2Smrg gfc_get_errors (&w, &e);
1397627f7eb2Smrg if (e > 0)
1398627f7eb2Smrg exit(EXIT_FAILURE);
1399627f7eb2Smrg
1400627f7eb2Smrg va_start (argp, gmsgid);
1401627f7eb2Smrg diagnostic_set_info (&diagnostic, gmsgid, &argp, &rich_loc, DK_ICE);
1402*4c3eb207Smrg gfc_report_diagnostic (&diagnostic);
1403627f7eb2Smrg va_end (argp);
1404627f7eb2Smrg
1405627f7eb2Smrg gcc_unreachable ();
1406627f7eb2Smrg }
1407627f7eb2Smrg
1408627f7eb2Smrg
1409627f7eb2Smrg /* Clear the error flag when we start to compile a source line. */
1410627f7eb2Smrg
1411627f7eb2Smrg void
gfc_clear_error(void)1412627f7eb2Smrg gfc_clear_error (void)
1413627f7eb2Smrg {
1414*4c3eb207Smrg error_buffer.flag = false;
1415627f7eb2Smrg warnings_not_errors = false;
1416627f7eb2Smrg gfc_clear_pp_buffer (pp_error_buffer);
1417627f7eb2Smrg }
1418627f7eb2Smrg
1419627f7eb2Smrg
1420627f7eb2Smrg /* Tests the state of error_flag. */
1421627f7eb2Smrg
1422627f7eb2Smrg bool
gfc_error_flag_test(void)1423627f7eb2Smrg gfc_error_flag_test (void)
1424627f7eb2Smrg {
1425627f7eb2Smrg return error_buffer.flag
1426627f7eb2Smrg || !gfc_output_buffer_empty_p (pp_error_buffer);
1427627f7eb2Smrg }
1428627f7eb2Smrg
1429627f7eb2Smrg
1430627f7eb2Smrg /* Check to see if any errors have been saved.
1431627f7eb2Smrg If so, print the error. Returns the state of error_flag. */
1432627f7eb2Smrg
1433627f7eb2Smrg bool
gfc_error_check(void)1434627f7eb2Smrg gfc_error_check (void)
1435627f7eb2Smrg {
1436627f7eb2Smrg if (error_buffer.flag
1437627f7eb2Smrg || ! gfc_output_buffer_empty_p (pp_error_buffer))
1438627f7eb2Smrg {
1439627f7eb2Smrg error_buffer.flag = false;
1440627f7eb2Smrg pretty_printer *pp = global_dc->printer;
1441627f7eb2Smrg output_buffer *tmp_buffer = pp->buffer;
1442627f7eb2Smrg pp->buffer = pp_error_buffer;
1443627f7eb2Smrg pp_really_flush (pp);
1444627f7eb2Smrg ++errorcount;
1445627f7eb2Smrg gcc_assert (gfc_output_buffer_empty_p (pp_error_buffer));
1446627f7eb2Smrg pp->buffer = tmp_buffer;
1447627f7eb2Smrg diagnostic_action_after_output (global_dc, DK_ERROR);
1448627f7eb2Smrg diagnostic_check_max_errors (global_dc, true);
1449627f7eb2Smrg return true;
1450627f7eb2Smrg }
1451627f7eb2Smrg
1452627f7eb2Smrg return false;
1453627f7eb2Smrg }
1454627f7eb2Smrg
1455627f7eb2Smrg /* Move the text buffered from FROM to TO, then clear
1456627f7eb2Smrg FROM. Independently if there was text in FROM, TO is also
1457627f7eb2Smrg cleared. */
1458627f7eb2Smrg
1459627f7eb2Smrg static void
gfc_move_error_buffer_from_to(gfc_error_buffer * buffer_from,gfc_error_buffer * buffer_to)1460627f7eb2Smrg gfc_move_error_buffer_from_to (gfc_error_buffer * buffer_from,
1461627f7eb2Smrg gfc_error_buffer * buffer_to)
1462627f7eb2Smrg {
1463627f7eb2Smrg output_buffer * from = &(buffer_from->buffer);
1464627f7eb2Smrg output_buffer * to = &(buffer_to->buffer);
1465627f7eb2Smrg
1466627f7eb2Smrg buffer_to->flag = buffer_from->flag;
1467627f7eb2Smrg buffer_from->flag = false;
1468627f7eb2Smrg
1469627f7eb2Smrg gfc_clear_pp_buffer (to);
1470627f7eb2Smrg /* We make sure this is always buffered. */
1471627f7eb2Smrg to->flush_p = false;
1472627f7eb2Smrg
1473627f7eb2Smrg if (! gfc_output_buffer_empty_p (from))
1474627f7eb2Smrg {
1475627f7eb2Smrg const char *str = output_buffer_formatted_text (from);
1476627f7eb2Smrg output_buffer_append_r (to, str, strlen (str));
1477627f7eb2Smrg gfc_clear_pp_buffer (from);
1478627f7eb2Smrg }
1479627f7eb2Smrg }
1480627f7eb2Smrg
1481627f7eb2Smrg /* Save the existing error state. */
1482627f7eb2Smrg
1483627f7eb2Smrg void
gfc_push_error(gfc_error_buffer * err)1484627f7eb2Smrg gfc_push_error (gfc_error_buffer *err)
1485627f7eb2Smrg {
1486627f7eb2Smrg gfc_move_error_buffer_from_to (&error_buffer, err);
1487627f7eb2Smrg }
1488627f7eb2Smrg
1489627f7eb2Smrg
1490627f7eb2Smrg /* Restore a previous pushed error state. */
1491627f7eb2Smrg
1492627f7eb2Smrg void
gfc_pop_error(gfc_error_buffer * err)1493627f7eb2Smrg gfc_pop_error (gfc_error_buffer *err)
1494627f7eb2Smrg {
1495627f7eb2Smrg gfc_move_error_buffer_from_to (err, &error_buffer);
1496627f7eb2Smrg }
1497627f7eb2Smrg
1498627f7eb2Smrg
1499627f7eb2Smrg /* Free a pushed error state, but keep the current error state. */
1500627f7eb2Smrg
1501627f7eb2Smrg void
gfc_free_error(gfc_error_buffer * err)1502627f7eb2Smrg gfc_free_error (gfc_error_buffer *err)
1503627f7eb2Smrg {
1504627f7eb2Smrg gfc_clear_pp_buffer (&(err->buffer));
1505627f7eb2Smrg }
1506627f7eb2Smrg
1507627f7eb2Smrg
1508627f7eb2Smrg /* Report the number of warnings and errors that occurred to the caller. */
1509627f7eb2Smrg
1510627f7eb2Smrg void
gfc_get_errors(int * w,int * e)1511627f7eb2Smrg gfc_get_errors (int *w, int *e)
1512627f7eb2Smrg {
1513627f7eb2Smrg if (w != NULL)
1514627f7eb2Smrg *w = warningcount + werrorcount;
1515627f7eb2Smrg if (e != NULL)
1516627f7eb2Smrg *e = errorcount + sorrycount + werrorcount;
1517627f7eb2Smrg }
1518627f7eb2Smrg
1519627f7eb2Smrg
1520627f7eb2Smrg /* Switch errors into warnings. */
1521627f7eb2Smrg
1522627f7eb2Smrg void
gfc_errors_to_warnings(bool f)1523627f7eb2Smrg gfc_errors_to_warnings (bool f)
1524627f7eb2Smrg {
1525627f7eb2Smrg warnings_not_errors = f;
1526627f7eb2Smrg }
1527627f7eb2Smrg
1528627f7eb2Smrg void
gfc_diagnostics_init(void)1529627f7eb2Smrg gfc_diagnostics_init (void)
1530627f7eb2Smrg {
1531627f7eb2Smrg diagnostic_starter (global_dc) = gfc_diagnostic_starter;
1532627f7eb2Smrg global_dc->start_span = gfc_diagnostic_start_span;
1533627f7eb2Smrg diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer;
1534627f7eb2Smrg diagnostic_format_decoder (global_dc) = gfc_format_decoder;
1535627f7eb2Smrg global_dc->caret_chars[0] = '1';
1536627f7eb2Smrg global_dc->caret_chars[1] = '2';
1537627f7eb2Smrg pp_warning_buffer = new (XNEW (output_buffer)) output_buffer ();
1538627f7eb2Smrg pp_warning_buffer->flush_p = false;
1539627f7eb2Smrg /* pp_error_buffer is statically allocated. This simplifies memory
1540627f7eb2Smrg management when using gfc_push/pop_error. */
1541627f7eb2Smrg pp_error_buffer = &(error_buffer.buffer);
1542627f7eb2Smrg pp_error_buffer->flush_p = false;
1543627f7eb2Smrg }
1544627f7eb2Smrg
1545627f7eb2Smrg void
gfc_diagnostics_finish(void)1546627f7eb2Smrg gfc_diagnostics_finish (void)
1547627f7eb2Smrg {
1548627f7eb2Smrg tree_diagnostics_defaults (global_dc);
1549627f7eb2Smrg /* We still want to use the gfc starter and finalizer, not the tree
1550627f7eb2Smrg defaults. */
1551627f7eb2Smrg diagnostic_starter (global_dc) = gfc_diagnostic_starter;
1552627f7eb2Smrg diagnostic_finalizer (global_dc) = gfc_diagnostic_finalizer;
1553627f7eb2Smrg global_dc->caret_chars[0] = '^';
1554627f7eb2Smrg global_dc->caret_chars[1] = '^';
1555627f7eb2Smrg }
1556