OSDN Git Service

2002-03-03 Aldy Hernandez <aldyh@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / diagnostic.c
1 /* Language-independent diagnostic subroutines for the GNU C compiler
2    Copyright (C) 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
3    Contributed by Gabriel Dos Reis <gdr@codesourcery.com>
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
10 version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22
23 /* This file implements the language independent aspect of diagnostic
24    message module.  */
25
26 #include "config.h"
27 #undef FLOAT /* This is for hpux. They should change hpux.  */
28 #undef FFS  /* Some systems define this in param.h.  */
29 #include "system.h"
30 #include "tree.h"
31 #include "tm_p.h"
32 #include "flags.h"
33 #include "input.h"
34 #include "toplev.h"
35 #include "intl.h"
36 #include "diagnostic.h"
37
38 #define obstack_chunk_alloc xmalloc
39 #define obstack_chunk_free  free
40
41 #define output_formatted_integer(BUFFER, FORMAT, INTEGER) \
42   do {                                                    \
43     sprintf ((BUFFER)->digit_buffer, FORMAT, INTEGER);    \
44     output_add_string (BUFFER, (BUFFER)->digit_buffer);   \
45   } while (0)
46
47 #define output_text_length(BUFFER) (BUFFER)->line_length
48 #define is_starting_newline(BUFFER) (output_text_length (BUFFER) == 0)
49 #define output_prefix(BUFFER) (BUFFER)->state.prefix
50 #define line_wrap_cutoff(BUFFER) (BUFFER)->state.maximum_length
51 #define prefix_was_emitted_for(BUFFER) (BUFFER)->state.emitted_prefix_p
52 #define output_buffer_ptr_to_format_args(BUFFER) (BUFFER)->state.format_args
53
54 #define diagnostic_args output_buffer_ptr_to_format_args (diagnostic_buffer)
55 #define diagnostic_msg output_buffer_text_cursor (diagnostic_buffer)
56
57 /* Prototypes.  */
58 static void diagnostic_finish PARAMS ((output_buffer *));
59 static void output_do_verbatim PARAMS ((output_buffer *,
60                                         const char *, va_list *));
61 static void output_buffer_to_stream PARAMS ((output_buffer *));
62 static void output_format PARAMS ((output_buffer *));
63 static void output_indent PARAMS ((output_buffer *));
64
65 static char *vbuild_message_string PARAMS ((const char *, va_list))
66      ATTRIBUTE_PRINTF (1, 0);
67 static char *build_message_string PARAMS ((const char *, ...))
68      ATTRIBUTE_PRINTF_1;
69 static void output_do_printf PARAMS ((output_buffer *, const char *))
70      ATTRIBUTE_PRINTF (2, 0);
71 static void format_with_decl PARAMS ((output_buffer *, tree));
72 static void diagnostic_for_decl PARAMS ((tree, const char *, va_list *, int));
73 static void set_real_maximum_length PARAMS ((output_buffer *));
74
75 static void output_unsigned_decimal PARAMS ((output_buffer *, unsigned int));
76 static void output_long_decimal PARAMS ((output_buffer *, long int));
77 static void output_long_unsigned_decimal PARAMS ((output_buffer *,
78                                                   long unsigned int));
79 static void output_octal PARAMS ((output_buffer *, unsigned int));
80 static void output_long_octal PARAMS ((output_buffer *, unsigned long int));
81 static void output_hexadecimal PARAMS ((output_buffer *, unsigned int));
82 static void output_long_hexadecimal PARAMS ((output_buffer *,
83                                              unsigned long int));
84 static void output_append_r PARAMS ((output_buffer *, const char *, int));
85 static void wrap_text PARAMS ((output_buffer *, const char *, const char *));
86 static void maybe_wrap_text PARAMS ((output_buffer *, const char *,
87                                      const char *));
88 static void clear_diagnostic_info PARAMS ((output_buffer *));
89
90 static void default_diagnostic_starter PARAMS ((output_buffer *,
91                                                 diagnostic_context *));
92 static void default_diagnostic_finalizer PARAMS ((output_buffer *,
93                                                   diagnostic_context *));
94
95 static void error_recursion PARAMS ((void)) ATTRIBUTE_NORETURN;
96
97 extern int rtl_dump_and_exit;
98 extern int warnings_are_errors;
99
100 /* A diagnostic_context surrogate for stderr.  */
101 static diagnostic_context global_diagnostic_context;
102 diagnostic_context *global_dc = &global_diagnostic_context;
103
104 /* This will be removed shortly.  */
105 output_buffer *diagnostic_buffer = &global_diagnostic_context.buffer;
106
107 /* Function of last error message;
108    more generally, function such that if next error message is in it
109    then we don't have to mention the function name.  */
110 static tree last_error_function = NULL;
111
112 /* Used to detect when input_file_stack has changed since last described.  */
113 static int last_error_tick;
114
115 /* Called by report_error_function to print out function name.
116    Default may be overridden by language front-ends.  */
117
118 void (*print_error_function) PARAMS ((diagnostic_context *, const char *))
119      = default_print_error_function;
120
121 /* Prevent recursion into the error handler.  */
122 static int diagnostic_lock;
123
124 \f
125 /* Return truthvalue if current input file is different from the most recent
126    file involved in a diagnostic message.  */
127
128 int
129 error_module_changed ()
130 {
131   return last_error_tick != input_file_stack_tick;
132 }
133
134 /* Remember current file as being the most recent file involved in a
135    diagnostic message.  */
136
137 void
138 record_last_error_module ()
139 {
140   last_error_tick = input_file_stack_tick;
141 }
142
143 /* Same as error_module_changed, but for function.  */
144
145 int
146 error_function_changed ()
147 {
148   return last_error_function != current_function_decl;
149 }
150
151 /* Same as record_last_error_module, but for function.  */
152
153 void
154 record_last_error_function ()
155 {
156   last_error_function = current_function_decl;
157 }
158
159 /* Initialize the diagnostic message outputting machinery.  */
160
161 void
162 diagnostic_initialize (context)
163      diagnostic_context *context;
164 {
165   memset (context, 0, sizeof *context);
166   obstack_init (&context->buffer.obstack);
167
168   /* By default, diagnostics are sent to stderr.  */
169   output_buffer_attached_stream (&context->buffer) = stderr;
170
171   /* By default, we emit prefixes once per message.  */
172   diagnostic_prefixing_rule (context) = DIAGNOSTICS_SHOW_PREFIX_ONCE;
173
174   diagnostic_starter (context) = default_diagnostic_starter;
175   diagnostic_finalizer (context) = default_diagnostic_finalizer;
176 }
177
178 /* Returns true if BUFFER is in line-wrapping mode.  */
179
180 int
181 output_is_line_wrapping (buffer)
182      output_buffer *buffer;
183 {
184   return diagnostic_line_cutoff (buffer) > 0;
185 }
186
187 /* Return BUFFER's prefix.  */
188
189 const char *
190 output_get_prefix (buffer)
191      const output_buffer *buffer;
192 {
193   return output_prefix (buffer);
194 }
195
196 /* Subroutine of output_set_maximum_length.  Set up BUFFER's
197    internal maximum characters per line.  */
198
199 static void
200 set_real_maximum_length (buffer)
201      output_buffer *buffer;
202 {
203   /* If we're told not to wrap lines then do the obvious thing.  In case
204    we'll emit prefix only once per diagnostic message, it is appropriate
205   not to increase unnecessarily the line-length cut-off.  */
206   if (! output_is_line_wrapping (buffer)
207       || diagnostic_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_ONCE
208       || diagnostic_prefixing_rule (buffer) == DIAGNOSTICS_SHOW_PREFIX_NEVER)
209     line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer);
210   else
211     {
212       int prefix_length =
213         output_prefix (buffer) ? strlen (output_prefix (buffer)) : 0;
214       /* If the prefix is ridiculously too long, output at least
215          32 characters.  */
216       if (diagnostic_line_cutoff (buffer) - prefix_length < 32)
217         line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer) + 32;
218       else
219         line_wrap_cutoff (buffer) = diagnostic_line_cutoff (buffer);
220     }
221 }
222
223 /* Sets the number of maximum characters per line BUFFER can output
224    in line-wrapping mode.  A LENGTH value 0 suppresses line-wrapping.  */
225
226 void
227 output_set_maximum_length (buffer, length)
228      output_buffer *buffer;
229      int length;
230 {
231   diagnostic_line_cutoff (buffer) = length;
232   set_real_maximum_length (buffer);
233 }
234
235 /* Sets BUFFER's PREFIX.  */
236
237 void
238 output_set_prefix (buffer, prefix)
239      output_buffer *buffer;
240      const char *prefix;
241 {
242   output_prefix (buffer) = prefix;
243   set_real_maximum_length (buffer);
244   prefix_was_emitted_for (buffer) = 0;
245   output_indentation (buffer) = 0;
246 }
247
248 /*  Return a pointer to the last character emitted in the output
249     BUFFER area.  A NULL pointer means no character available.  */
250 const char *
251 output_last_position (buffer)
252      const output_buffer *buffer;
253 {
254   const char *p = NULL;
255   
256   if (obstack_base (&buffer->obstack) != obstack_next_free (&buffer->obstack))
257     p = ((const char *) obstack_next_free (&buffer->obstack)) - 1;
258   return p;
259 }
260
261 /* Free BUFFER's prefix, a previously malloc'd string.  */
262
263 void
264 output_destroy_prefix (buffer)
265      output_buffer *buffer;
266 {
267   if (output_prefix (buffer) != NULL)
268     {
269       free ((char *) output_prefix (buffer));
270       output_prefix (buffer) = NULL;
271     }
272 }
273
274 /* Zero out any text output so far in BUFFER.  */
275
276 void
277 output_clear_message_text (buffer)
278      output_buffer *buffer;
279 {
280   obstack_free (&buffer->obstack, obstack_base (&buffer->obstack));
281   output_text_length (buffer) = 0;
282 }
283
284 /* Zero out any diagnostic data used so far by BUFFER.  */
285
286 static void
287 clear_diagnostic_info (buffer)
288      output_buffer *buffer;
289 {
290   output_buffer_text_cursor (buffer) = NULL;
291   output_buffer_ptr_to_format_args (buffer) = NULL;
292   prefix_was_emitted_for (buffer) = 0;
293   output_indentation (buffer) = 0;
294 }
295
296 /* Construct an output BUFFER with PREFIX and of MAXIMUM_LENGTH
297    characters per line.  */
298
299 void
300 init_output_buffer (buffer, prefix, maximum_length)
301      output_buffer *buffer;
302      const char *prefix;
303      int maximum_length;
304 {
305   memset (buffer, 0, sizeof (output_buffer));
306   obstack_init (&buffer->obstack);
307   output_buffer_attached_stream (buffer) = stderr;
308   diagnostic_line_cutoff (buffer) = maximum_length;
309   diagnostic_prefixing_rule (buffer) = diagnostic_prefixing_rule (global_dc);
310   output_set_prefix (buffer, prefix);
311   output_text_length (buffer) = 0;
312   clear_diagnostic_info (buffer);  
313 }
314
315 /* Reinitialize BUFFER.  */
316
317 void
318 output_clear (buffer)
319      output_buffer *buffer;
320 {
321   output_clear_message_text (buffer);
322   clear_diagnostic_info (buffer);
323 }
324
325 /* Finishes constructing a NULL-terminated character string representing
326    the BUFFERed message.  */
327
328 const char *
329 output_finalize_message (buffer)
330      output_buffer *buffer;
331 {
332   obstack_1grow (&buffer->obstack, '\0');
333   return output_message_text (buffer);
334 }
335
336 void
337 flush_diagnostic_buffer ()
338 {
339   output_buffer_to_stream (diagnostic_buffer);
340   fflush (output_buffer_attached_stream (diagnostic_buffer));
341 }
342
343 /* Return the amount of characters BUFFER can accept to
344    make a full line.  */
345
346 int
347 output_space_left (buffer)
348      const output_buffer *buffer;
349 {
350   return line_wrap_cutoff (buffer) - output_text_length (buffer);
351 }
352
353 /* Write out BUFFER's prefix.  */
354
355 void
356 output_emit_prefix (buffer)
357      output_buffer *buffer;
358 {
359   if (output_prefix (buffer) != NULL)
360     {
361       switch (diagnostic_prefixing_rule (buffer))
362         {
363         default:
364         case DIAGNOSTICS_SHOW_PREFIX_NEVER:
365           break;
366
367         case DIAGNOSTICS_SHOW_PREFIX_ONCE:
368           if (prefix_was_emitted_for (buffer))
369             {
370               output_indent (buffer);
371               break;
372             }
373           output_indentation (buffer) += 3;          
374           /* Fall through.  */
375
376         case DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE:
377           {
378             int prefix_length = strlen (output_prefix (buffer));
379             output_append_r (buffer, output_prefix (buffer), prefix_length);
380             prefix_was_emitted_for (buffer) = 1;
381           }
382           break;
383         }
384     }
385 }
386
387 /* Have BUFFER start a new line.  */
388
389 void
390 output_add_newline (buffer)
391      output_buffer *buffer;
392 {
393   obstack_1grow (&buffer->obstack, '\n');
394   output_text_length (buffer) = 0;
395 }
396
397 /* Appends a character to BUFFER.  */
398
399 void
400 output_add_character (buffer, c)
401      output_buffer *buffer;
402      int c;
403 {
404   if (output_is_line_wrapping (buffer) && output_space_left (buffer) <= 0)
405     output_add_newline (buffer);
406   obstack_1grow (&buffer->obstack, c);
407   ++output_text_length (buffer);
408 }
409
410 /* Adds a space to BUFFER.  */
411
412 void
413 output_add_space (buffer)
414      output_buffer *buffer;
415 {
416   if (output_is_line_wrapping (buffer) && output_space_left (buffer) <= 0)
417     {
418       output_add_newline (buffer);
419       return;
420     }
421   obstack_1grow (&buffer->obstack, ' ');
422   ++output_text_length (buffer);
423 }
424
425 /* These functions format an INTEGER into BUFFER as suggested by their
426    names.  */
427
428 void
429 output_decimal (buffer, i)
430      output_buffer *buffer;
431      int i;
432 {
433   output_formatted_integer (buffer, "%d", i);
434 }
435
436 static void
437 output_long_decimal (buffer, i)
438      output_buffer *buffer;
439      long int i;
440 {
441   output_formatted_integer (buffer, "%ld", i);
442 }
443
444 static void
445 output_unsigned_decimal (buffer, i)
446      output_buffer *buffer;
447      unsigned int i;
448 {
449   output_formatted_integer (buffer, "%u", i);
450 }
451
452 static void
453 output_long_unsigned_decimal (buffer, i)
454      output_buffer *buffer;
455      long unsigned int i;
456 {
457   output_formatted_integer (buffer, "%lu", i);
458 }
459
460 static void
461 output_octal (buffer, i)
462      output_buffer *buffer;
463      unsigned int i;
464 {
465   output_formatted_integer (buffer, "%o", i);
466 }
467
468 static void
469 output_long_octal (buffer, i)
470      output_buffer *buffer;
471      unsigned long int i;
472 {
473   output_formatted_integer (buffer, "%lo", i);
474 }
475
476 static void
477 output_hexadecimal (buffer, i)
478      output_buffer *buffer;
479      unsigned int i;
480 {
481   output_formatted_integer (buffer, "%x", i);
482 }
483
484 static void
485 output_long_hexadecimal (buffer, i)
486      output_buffer *buffer;
487      unsigned long int i;
488 {
489   output_formatted_integer (buffer, "%lx", i);
490 }
491
492 /* Append to BUFFER a string specified by its STARTING character
493    and LENGTH.  */
494
495 static void
496 output_append_r (buffer, start, length)
497      output_buffer *buffer;
498      const char *start;
499      int length;
500 {
501   obstack_grow (&buffer->obstack, start, length);
502   output_text_length (buffer) += length;
503 }
504
505 /* Append a string deliminated by START and END to BUFFER.  No wrapping is
506    done.  However, if beginning a new line then emit output_prefix (BUFFER)
507    and skip any leading whitespace if appropriate.  The caller must ensure
508    that it is safe to do so.  */
509
510 void
511 output_append (buffer, start, end)
512      output_buffer *buffer;
513      const char *start;
514      const char *end;
515 {
516   /* Emit prefix and skip whitespace if we're starting a new line.  */
517   if (is_starting_newline (buffer))
518     {
519       output_emit_prefix (buffer);
520       if (output_is_line_wrapping (buffer))
521         while (start != end && *start == ' ')
522           ++start;
523     }
524   output_append_r (buffer, start, end - start);
525 }
526
527 static void
528 output_indent (buffer)
529      output_buffer *buffer;
530 {
531   int n = output_indentation (buffer);
532   int i;
533
534   for (i = 0; i < n; ++i)
535     output_add_character (buffer, ' ');
536 }
537
538 /* Wrap a text delimited by START and END into BUFFER.  */
539
540 static void
541 wrap_text (buffer, start, end)
542      output_buffer *buffer;
543      const char *start;
544      const char *end;
545 {
546   int is_wrapping = output_is_line_wrapping (buffer);
547   
548   while (start != end)
549     {
550       /* Dump anything bordered by whitespaces.  */ 
551       {
552         const char *p = start;
553         while (p != end && *p != ' ' && *p != '\n')
554           ++p;
555         if (is_wrapping && p - start >= output_space_left (buffer))
556           output_add_newline (buffer);
557         output_append (buffer, start, p);
558         start = p;
559       }
560
561       if (start != end && *start == ' ')
562         {
563           output_add_space (buffer);
564           ++start;
565         }
566       if (start != end && *start == '\n')
567         {
568           output_add_newline (buffer);
569           ++start;
570         }
571     }
572 }
573
574 /* Same as wrap_text but wrap text only when in line-wrapping mode.  */
575
576 static void
577 maybe_wrap_text (buffer, start, end)
578      output_buffer *buffer;
579      const char *start;
580      const char *end;
581 {
582   if (output_is_line_wrapping (buffer))
583     wrap_text (buffer, start, end);
584   else
585     output_append (buffer, start, end);
586 }
587
588
589 /* Append a STRING to BUFFER; the STRING might be line-wrapped if in
590    appropriate mode.  */
591
592 void
593 output_add_string (buffer, str)
594      output_buffer *buffer;
595      const char *str;
596 {
597   maybe_wrap_text (buffer, str, str + (str ? strlen (str) : 0));
598 }
599
600 /* Flush the content of BUFFER onto the attached stream,
601    and reinitialize.  */
602
603 static void
604 output_buffer_to_stream (buffer)
605      output_buffer *buffer;
606 {
607   const char *text = output_finalize_message (buffer);
608   fputs (text, output_buffer_attached_stream (buffer));
609   output_clear_message_text (buffer);
610 }
611
612 /* Format a message pointed to by output_buffer_text_cursor (BUFFER) using
613    output_buffer_format_args (BUFFER) as appropriate.  The following format
614    specifiers are recognized as being language independent:
615    %d, %i: (signed) integer in base ten.
616    %u: unsigned integer in base ten.
617    %o: unsigned integer in base eight.
618    %x: unsigned integer in base sixteen.
619    %ld, %li, %lo, %lu, %lx: long versions of the above.
620    %c: character.
621    %s: string.
622    %%: `%'.
623    %*.s: a substring the length of which is specified by an integer.  */
624
625 static void
626 output_format (buffer)
627      output_buffer *buffer;
628 {
629   for (; *output_buffer_text_cursor (buffer);
630        ++output_buffer_text_cursor (buffer))
631     {
632       int long_integer = 0;
633
634       /* Ignore text.  */
635       {
636         const char *p = output_buffer_text_cursor (buffer);
637         while (*p && *p != '%')
638           ++p;
639         wrap_text (buffer, output_buffer_text_cursor (buffer), p);
640         output_buffer_text_cursor (buffer) = p;
641       }
642
643       if (!*output_buffer_text_cursor (buffer))
644         break;
645
646       /* We got a '%'.  Let's see what happens. Record whether we're
647          parsing a long integer format specifier.  */
648       if (*++output_buffer_text_cursor (buffer) == 'l')
649         {
650           long_integer = 1;
651           ++output_buffer_text_cursor (buffer);
652         }
653
654       /* Handle %c, %d, %i, %ld, %li, %lo, %lu, %lx, %o, %s, %u,
655          %x, %.*s; %%.  And nothing else.  Front-ends should install
656          printers to grok language specific format specifiers.  */
657       switch (*output_buffer_text_cursor (buffer))
658         {
659         case 'c':
660           output_add_character
661             (buffer, va_arg (output_buffer_format_args (buffer), int));
662           break;
663           
664         case 'd':
665         case 'i':
666           if (long_integer)
667             output_long_decimal
668               (buffer, va_arg (output_buffer_format_args (buffer), long int));
669           else
670             output_decimal
671               (buffer, va_arg (output_buffer_format_args (buffer), int));
672           break;
673
674         case 'o':
675           if (long_integer)
676             output_long_octal (buffer,
677                                va_arg (output_buffer_format_args (buffer),
678                                        unsigned long int));
679           else
680             output_octal (buffer,
681                           va_arg (output_buffer_format_args (buffer),
682                                   unsigned int));
683           break;
684
685         case 's':
686           output_add_string (buffer,
687                              va_arg (output_buffer_format_args (buffer),
688                                      const char *));
689           break;
690
691         case 'u':
692           if (long_integer)
693             output_long_unsigned_decimal
694               (buffer, va_arg (output_buffer_format_args (buffer),
695                                long unsigned int));
696           else
697             output_unsigned_decimal
698               (buffer, va_arg (output_buffer_format_args (buffer),
699                                unsigned int));
700           break;
701           
702         case 'x':
703           if (long_integer)
704             output_long_hexadecimal
705               (buffer, va_arg (output_buffer_format_args (buffer),
706                                unsigned long int));
707           else
708             output_hexadecimal
709               (buffer, va_arg (output_buffer_format_args (buffer),
710                                unsigned int));
711           break;
712
713         case '%':
714           output_add_character (buffer, '%');
715           break;
716
717         case '.':
718           {
719             int n;
720             const char *s;
721             /* We handle no precision specifier but `%.*s'.  */
722             if (*++output_buffer_text_cursor (buffer) != '*')
723               abort ();
724             else if (*++output_buffer_text_cursor (buffer) != 's')
725               abort ();
726             n = va_arg (output_buffer_format_args (buffer), int);
727             s = va_arg (output_buffer_format_args (buffer), const char *);
728             output_append (buffer, s, s + n);
729           }
730           break;
731
732         default:
733           if (!buffer->format_decoder || !(*buffer->format_decoder) (buffer))
734             {
735               /* Hmmm.  The front-end failed to install a format translator
736                  but called us with an unrecognized format.  Sorry.  */
737               abort ();
738             }
739         }
740     }
741 }
742
743 static char *
744 vbuild_message_string (msg, ap)
745      const char *msg;
746      va_list ap;
747 {
748   char *str;
749
750   vasprintf (&str, msg, ap);
751   return str;
752 }
753
754 /*  Return a malloc'd string containing MSG formatted a la
755     printf.  The caller is responsible for freeing the memory.  */
756
757 static char *
758 build_message_string VPARAMS ((const char *msg, ...))
759 {
760   char *str;
761
762   VA_OPEN (ap, msg);
763   VA_FIXEDARG (ap, const char *, msg);
764
765   str = vbuild_message_string (msg, ap);
766
767   VA_CLOSE (ap);
768
769   return str;
770 }
771
772 /* Return a malloc'd string describing a location.  The caller is
773    responsible for freeing the memory.  */
774
775 char *
776 context_as_prefix (file, line, warn)
777      const char *file;
778      int line;
779      int warn;
780 {
781   if (file)
782     {
783       if (warn)
784         return build_message_string (_("%s:%d: warning: "), file, line);
785       else
786         return build_message_string ("%s:%d: ", file, line);
787     }
788   else
789     {
790       if (warn)
791         return build_message_string (_("%s: warning: "), progname);
792       else
793         return build_message_string ("%s: ", progname);
794     }
795 }
796
797 /* Same as context_as_prefix, but only the source FILE is given.  */
798
799 char *
800 file_name_as_prefix (f)
801      const char *f;
802 {
803   return build_message_string ("%s: ", f);
804 }
805
806 /* Format a MESSAGE into BUFFER.  Automatically wrap lines.  */
807
808 static void
809 output_do_printf (buffer, msg)
810      output_buffer *buffer;
811      const char *msg;
812 {
813   char *message = vbuild_message_string (msg,
814                                          output_buffer_format_args (buffer));
815
816   wrap_text (buffer, message, message + strlen (message));
817   free (message);
818 }
819
820
821 /* Format a message into BUFFER a la printf.  */
822
823 void
824 output_printf VPARAMS ((struct output_buffer *buffer, const char *msgid, ...))
825 {
826   va_list *old_args;
827
828   VA_OPEN (ap, msgid);
829   VA_FIXEDARG (ap, output_buffer *, buffer);
830   VA_FIXEDARG (ap, const char *, msgid);
831
832   old_args = output_buffer_ptr_to_format_args (buffer);
833   output_buffer_ptr_to_format_args (buffer) = &ap;
834   output_do_printf (buffer, _(msgid));
835   output_buffer_ptr_to_format_args (buffer) = old_args;
836   VA_CLOSE (ap);
837 }
838
839 /* Print a message relevant to the given DECL.  */
840
841 static void
842 format_with_decl (buffer, decl)
843      output_buffer *buffer;
844      tree decl;
845 {
846   const char *p;
847   
848   /* Do magic to get around lack of varargs support for insertion
849      of arguments into existing list.  We know that the decl is first;
850      we ass_u_me that it will be printed with "%s".  */
851   for (p = output_buffer_text_cursor (buffer); *p; ++p)
852     {
853       if (*p == '%')
854         {
855           if (*(p + 1) == '%')
856             ++p;
857           else if (*(p + 1) != 's')
858             abort ();
859           else
860             break;
861         }
862     }
863
864   /* Print the left-hand substring.  */
865   maybe_wrap_text (buffer, output_buffer_text_cursor (buffer), p);
866   
867   if (*p == '%')                /* Print the name.  */
868     {
869       const char *const n = (DECL_NAME (decl)
870                              ? (*decl_printable_name) (decl, 2)
871                              : _("((anonymous))"));
872       output_add_string (buffer, n);
873       while (*p)
874         {
875           ++p;
876           if (ISALPHA (*(p - 1) & 0xFF))
877             break;
878         }
879     }
880
881   if (*p)                       /* Print the rest of the message.  */
882     {
883       output_buffer_text_cursor (buffer) = p;
884       output_format (buffer);
885     }
886 }
887
888
889 /* Report a diagnostic MESSAGE at the declaration DECL.
890    MSG is a format string which uses %s to substitute the declaration
891    name; subsequent substitutions are a la output_format.  */
892
893 static void
894 diagnostic_for_decl (decl, msgid, args_ptr, warn)
895      tree decl;
896      const char *msgid;
897      va_list *args_ptr;
898      int warn;
899 {
900   output_state os;
901
902   if (diagnostic_lock++)
903     error_recursion ();
904
905   if (count_error (warn))
906     {
907       os = output_buffer_state (diagnostic_buffer);
908       report_error_function (DECL_SOURCE_FILE (decl));
909       output_set_prefix
910         (diagnostic_buffer, context_as_prefix
911          (DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl), warn));
912       output_buffer_ptr_to_format_args (diagnostic_buffer) = args_ptr;
913       output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
914       format_with_decl (diagnostic_buffer, decl);
915       diagnostic_finish ((output_buffer *) global_dc);
916       output_destroy_prefix (diagnostic_buffer);
917   
918       output_buffer_state (diagnostic_buffer) = os;
919     }
920   diagnostic_lock--;
921 }
922
923 \f
924 /* Count an error or warning.  Return 1 if the message should be printed.  */
925
926 int
927 count_error (warningp)
928      int warningp;
929 {
930   if (warningp && !diagnostic_report_warnings_p ())
931     return 0;
932
933   if (warningp && !warnings_are_errors)
934     warningcount++;
935   else
936     {
937       static int warning_message = 0;
938
939       if (warningp && !warning_message)
940         {
941           verbatim ("%s: warnings being treated as errors\n", progname);
942           warning_message = 1;
943         }
944       errorcount++;
945     }
946
947   return 1;
948 }
949
950 /* Print a diagnostic MSGID on FILE.  This is just fprintf, except it
951    runs its second argument through gettext.  */
952
953 void
954 fnotice VPARAMS ((FILE *file, const char *msgid, ...))
955 {
956   VA_OPEN (ap, msgid);
957   VA_FIXEDARG (ap, FILE *, file);
958   VA_FIXEDARG (ap, const char *, msgid);
959
960   vfprintf (file, _(msgid), ap);
961   VA_CLOSE (ap);
962 }
963
964
965 /* Print a fatal I/O error message.  Argument are like printf.
966    Also include a system error message based on `errno'.  */
967
968 void
969 fatal_io_error VPARAMS ((const char *msgid, ...))
970 {
971   output_state os;
972
973   VA_OPEN (ap, msgid);
974   VA_FIXEDARG (ap, const char *, msgid);
975
976   os = output_buffer_state (diagnostic_buffer);
977
978   output_printf (diagnostic_buffer, "%s: %s: ", progname, xstrerror (errno));
979   output_buffer_ptr_to_format_args (diagnostic_buffer) = &ap;
980   output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
981   output_format (diagnostic_buffer);
982   diagnostic_finish ((output_buffer *) global_dc);
983   output_buffer_state (diagnostic_buffer) = os;
984   VA_CLOSE (ap);
985   exit (FATAL_EXIT_CODE);
986 }
987
988 /* Issue a pedantic warning MSGID.  */
989
990 void
991 pedwarn VPARAMS ((const char *msgid, ...))
992 {
993   diagnostic_context dc;
994
995   VA_OPEN (ap, msgid);
996   VA_FIXEDARG (ap, const char *, msgid);
997
998   set_diagnostic_context
999     (&dc, msgid, &ap, input_filename, lineno, !flag_pedantic_errors);
1000   report_diagnostic (&dc);
1001   VA_CLOSE (ap);
1002 }
1003
1004 /* Issue a pedantic waring about DECL.  */
1005
1006 void
1007 pedwarn_with_decl VPARAMS ((tree decl, const char *msgid, ...))
1008 {
1009   VA_OPEN (ap, msgid);
1010   VA_FIXEDARG (ap, tree, decl);
1011   VA_FIXEDARG (ap, const char *, msgid);
1012
1013   /* We don't want -pedantic-errors to cause the compilation to fail from
1014      "errors" in system header files.  Sometimes fixincludes can't fix what's
1015      broken (eg: unsigned char bitfields - fixing it may change the alignment
1016      which will cause programs to mysteriously fail because the C library
1017      or kernel uses the original layout).  There's no point in issuing a
1018      warning either, it's just unnecessary noise.  */
1019   if (!DECL_IN_SYSTEM_HEADER (decl))
1020     diagnostic_for_decl (decl, msgid, &ap, !flag_pedantic_errors);
1021   VA_CLOSE (ap);
1022 }
1023
1024 /* Same as above but within the context FILE and LINE.  */
1025
1026 void
1027 pedwarn_with_file_and_line VPARAMS ((const char *file, int line,
1028                                      const char *msgid, ...))
1029 {
1030   diagnostic_context dc;
1031
1032   VA_OPEN (ap, msgid);
1033   VA_FIXEDARG (ap, const char *, file);
1034   VA_FIXEDARG (ap, int, line);
1035   VA_FIXEDARG (ap, const char *, msgid);
1036
1037   set_diagnostic_context (&dc, msgid, &ap, file, line, !flag_pedantic_errors);
1038   report_diagnostic (&dc);
1039   VA_CLOSE (ap);
1040 }
1041
1042 /* Just apologize with MSGID.  */
1043
1044 void
1045 sorry VPARAMS ((const char *msgid, ...))
1046 {
1047   output_state os;
1048
1049   VA_OPEN (ap, msgid);
1050   VA_FIXEDARG (ap, const char *, msgid);
1051
1052   ++sorrycount;
1053   os = output_buffer_state (diagnostic_buffer);
1054
1055   output_set_prefix
1056     (diagnostic_buffer, context_as_prefix (input_filename, lineno, 0));
1057   output_printf (diagnostic_buffer, "sorry, not implemented: ");
1058   output_buffer_ptr_to_format_args (diagnostic_buffer) = &ap;
1059   output_buffer_text_cursor (diagnostic_buffer) = _(msgid);
1060   output_format (diagnostic_buffer);
1061   diagnostic_finish ((output_buffer *) global_dc);
1062   output_buffer_state (diagnostic_buffer) = os;
1063   VA_CLOSE (ap);
1064 }
1065
1066 /* Called when the start of a function definition is parsed,
1067    this function prints on stderr the name of the function.  */
1068
1069 void
1070 announce_function (decl)
1071      tree decl;
1072 {
1073   if (! quiet_flag)
1074     {
1075       if (rtl_dump_and_exit)
1076         verbatim ("%s ", IDENTIFIER_POINTER (DECL_NAME (decl)));
1077       else
1078         verbatim (" %s", (*decl_printable_name) (decl, 2));
1079       fflush (stderr);
1080       output_needs_newline (diagnostic_buffer) = 1;
1081       record_last_error_function ();
1082     }
1083 }
1084
1085 /* The default function to print out name of current function that caused
1086    an error.  */
1087
1088 void
1089 default_print_error_function (context, file)
1090      diagnostic_context *context;
1091      const char *file;
1092 {
1093   if (error_function_changed ())
1094     {
1095       char *prefix = file ? build_message_string ("%s: ", file) : NULL;
1096       output_state os;
1097
1098       os = output_buffer_state (context);
1099       output_set_prefix ((output_buffer *) context, prefix);
1100       
1101       if (current_function_decl == NULL)
1102           output_add_string ((output_buffer *) context, _("At top level:"));
1103       else
1104         {
1105           if (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE)
1106             output_printf
1107               ((output_buffer *) context, "In member function `%s':",
1108                (*decl_printable_name) (current_function_decl, 2));
1109           else
1110             output_printf
1111               ((output_buffer *) context, "In function `%s':",
1112                (*decl_printable_name) (current_function_decl, 2));
1113         }
1114       output_add_newline ((output_buffer *) context);
1115
1116       record_last_error_function ();
1117       output_buffer_to_stream ((output_buffer *) context);
1118       output_buffer_state (context) = os;
1119       free ((char*) prefix);
1120     }
1121 }
1122
1123 /* Prints out, if necessary, the name of the current function
1124   that caused an error.  Called from all error and warning functions.
1125   We ignore the FILE parameter, as it cannot be relied upon.  */
1126
1127 void
1128 report_error_function (file)
1129   const char *file ATTRIBUTE_UNUSED;
1130 {
1131   report_problematic_module ((output_buffer *) global_dc);
1132   (*print_error_function) (global_dc, input_filename);
1133 }
1134
1135 void
1136 error_with_file_and_line VPARAMS ((const char *file, int line,
1137                                    const char *msgid, ...))
1138 {
1139   diagnostic_context dc;
1140
1141   VA_OPEN (ap, msgid);
1142   VA_FIXEDARG (ap, const char *, file);
1143   VA_FIXEDARG (ap, int, line);
1144   VA_FIXEDARG (ap, const char *, msgid);
1145
1146   set_diagnostic_context (&dc, msgid, &ap, file, line, /* warn = */ 0);
1147   report_diagnostic (&dc);
1148   VA_CLOSE (ap);
1149 }
1150
1151 void
1152 error_with_decl VPARAMS ((tree decl, const char *msgid, ...))
1153 {
1154   VA_OPEN (ap, msgid);
1155   VA_FIXEDARG (ap, tree, decl);
1156   VA_FIXEDARG (ap, const char *, msgid);
1157
1158   diagnostic_for_decl (decl, msgid, &ap, /* warn = */ 0);
1159   VA_CLOSE (ap);
1160 }
1161
1162
1163 /* Report an error message.  The arguments are like that of printf.  */
1164
1165 void
1166 error VPARAMS ((const char *msgid, ...))
1167 {
1168   diagnostic_context dc;
1169
1170   VA_OPEN (ap, msgid);
1171   VA_FIXEDARG (ap, const char *, msgid);
1172
1173   set_diagnostic_context
1174     (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 0);
1175   report_diagnostic (&dc);
1176   VA_CLOSE (ap);
1177 }
1178
1179 /* Likewise, except that the compilation is terminated after printing the
1180    error message.  */
1181
1182 void
1183 fatal_error VPARAMS ((const char *msgid, ...))
1184 {
1185   diagnostic_context dc;
1186
1187   VA_OPEN (ap, msgid);
1188   VA_FIXEDARG (ap, const char *, msgid);
1189
1190   set_diagnostic_context
1191     (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 0);
1192   report_diagnostic (&dc);
1193   VA_CLOSE (ap);
1194
1195   fnotice (stderr, "compilation terminated.\n");
1196   exit (FATAL_EXIT_CODE);
1197 }
1198
1199 /* Report a compiler error at the current line number.  Allow a front end to
1200    intercept the message.  */
1201
1202 static void (*internal_error_function) PARAMS ((const char *, va_list *));
1203
1204 /* Set the function to call when a compiler error occurs.  */
1205
1206 void
1207 set_internal_error_function (f)
1208      void (*f) PARAMS ((const char *, va_list *));
1209 {
1210   internal_error_function = f;
1211 }
1212
1213 void
1214 internal_error VPARAMS ((const char *msgid, ...))
1215 {
1216   diagnostic_context dc;
1217
1218   VA_OPEN (ap, msgid);
1219   VA_FIXEDARG (ap, const char *, msgid);
1220
1221   if (diagnostic_lock)
1222     error_recursion ();
1223
1224 #ifndef ENABLE_CHECKING
1225   if (errorcount > 0 || sorrycount > 0)
1226     {
1227       fnotice (stderr, "%s:%d: confused by earlier errors, bailing out\n",
1228                input_filename, lineno);
1229       exit (FATAL_EXIT_CODE);
1230     }
1231 #endif
1232
1233   if (internal_error_function != 0)
1234     (*internal_error_function) (_(msgid), &ap);
1235   
1236   set_diagnostic_context
1237     (&dc, msgid, &ap, input_filename, lineno, /* warn = */0);
1238   report_diagnostic (&dc);
1239   VA_CLOSE (ap);
1240
1241   fnotice (stderr,
1242 "Please submit a full bug report,\n\
1243 with preprocessed source if appropriate.\n\
1244 See %s for instructions.\n", GCCBUGURL);
1245   exit (FATAL_EXIT_CODE);
1246 }
1247
1248 void
1249 warning_with_file_and_line VPARAMS ((const char *file, int line,
1250                                      const char *msgid, ...))
1251 {
1252   diagnostic_context dc;
1253
1254   VA_OPEN (ap, msgid);
1255   VA_FIXEDARG (ap, const char *, file);
1256   VA_FIXEDARG (ap, int, line);
1257   VA_FIXEDARG (ap, const char *, msgid);
1258
1259   set_diagnostic_context (&dc, msgid, &ap, file, line, /* warn = */ 1);
1260   report_diagnostic (&dc);
1261   VA_CLOSE (ap);
1262 }
1263
1264 void
1265 warning_with_decl VPARAMS ((tree decl, const char *msgid, ...))
1266 {
1267   VA_OPEN (ap, msgid);
1268   VA_FIXEDARG (ap, tree, decl);
1269   VA_FIXEDARG (ap, const char *, msgid);
1270
1271   diagnostic_for_decl (decl, msgid, &ap, /* warn = */ 1);
1272   VA_CLOSE (ap);
1273 }
1274
1275 void
1276 warning VPARAMS ((const char *msgid, ...))
1277 {
1278   diagnostic_context dc;
1279
1280   VA_OPEN (ap, msgid);
1281   VA_FIXEDARG (ap, const char *, msgid);
1282
1283   set_diagnostic_context
1284     (&dc, msgid, &ap, input_filename, lineno, /* warn = */ 1);
1285   report_diagnostic (&dc);
1286   VA_CLOSE (ap);
1287 }
1288
1289 /* Flush diagnostic_buffer content on stderr.  */
1290
1291 static void
1292 diagnostic_finish (buffer)
1293      output_buffer *buffer;
1294 {
1295   output_buffer_to_stream (buffer);
1296   clear_diagnostic_info (buffer);
1297   fputc ('\n', output_buffer_attached_stream (buffer));
1298   fflush (output_buffer_attached_stream (buffer));
1299 }
1300
1301 /* Helper subroutine of output_verbatim and verbatim. Do the appropriate
1302    settings needed by BUFFER for a verbatim formatting.  */
1303
1304 static void
1305 output_do_verbatim (buffer, msgid, args_ptr)
1306      output_buffer *buffer;
1307      const char *msgid;
1308      va_list *args_ptr;
1309 {
1310   output_state os;
1311
1312   os = output_buffer_state (buffer);
1313   output_prefix (buffer) = NULL;
1314   diagnostic_prefixing_rule (buffer) = DIAGNOSTICS_SHOW_PREFIX_NEVER;
1315   output_buffer_text_cursor (buffer) = _(msgid);
1316   output_buffer_ptr_to_format_args (buffer) = args_ptr;
1317   output_set_maximum_length (buffer, 0);
1318   output_format (buffer);
1319   output_buffer_state (buffer) = os;
1320 }
1321
1322 /* Output MESSAGE verbatim into BUFFER.  */
1323
1324 void
1325 output_verbatim VPARAMS ((output_buffer *buffer, const char *msgid, ...))
1326 {
1327   VA_OPEN (ap, msgid);
1328   VA_FIXEDARG (ap, output_buffer *, buffer);
1329   VA_FIXEDARG (ap, const char *, msgid);
1330
1331   output_do_verbatim (buffer, msgid, &ap);
1332   VA_CLOSE (ap);
1333 }
1334
1335 /* Same as above but use diagnostic_buffer.  */
1336
1337 void
1338 verbatim VPARAMS ((const char *msgid, ...))
1339 {
1340   VA_OPEN (ap, msgid);
1341   VA_FIXEDARG (ap, const char *, msgid);
1342
1343   output_do_verbatim (diagnostic_buffer, msgid, &ap);
1344   output_buffer_to_stream (diagnostic_buffer);
1345   VA_CLOSE (ap);
1346 }
1347
1348 /* Report a diagnostic message (an error or a warning) as specified by
1349    DC.  This function is *the* subroutine in terms of which front-ends
1350    should implement their specific diagnostic handling modules.  The
1351    front-end independent format specifiers are exactly those described
1352    in the documentation of output_format.  */
1353
1354 void
1355 report_diagnostic (dc)
1356      diagnostic_context *dc;
1357 {
1358   output_state os;
1359
1360   if (diagnostic_lock++)
1361     error_recursion ();
1362
1363   if (count_error (diagnostic_is_warning (dc)))
1364     {
1365       os = output_buffer_state (diagnostic_buffer);
1366       diagnostic_msg = diagnostic_message (dc);
1367       diagnostic_args = diagnostic_argument_list (dc);
1368       (*diagnostic_starter (dc)) (diagnostic_buffer, dc);
1369       output_format (diagnostic_buffer);
1370       (*diagnostic_finalizer (dc)) (diagnostic_buffer, dc);
1371       diagnostic_finish ((output_buffer *) global_dc);
1372       output_buffer_state (diagnostic_buffer) = os;
1373     }
1374
1375   diagnostic_lock--;
1376 }
1377
1378 /* Inform the user that an error occurred while trying to report some
1379    other error.  This indicates catastrophic internal inconsistencies,
1380    so give up now.  But do try to flush out the previous error.
1381    This mustn't use internal_error, that will cause infinite recursion.  */
1382
1383 static void
1384 error_recursion ()
1385 {
1386   if (diagnostic_lock < 3)
1387     diagnostic_finish ((output_buffer *) global_dc);
1388
1389   fnotice (stderr,
1390            "Internal compiler error: Error reporting routines re-entered.\n");
1391   fnotice (stderr,
1392 "Please submit a full bug report,\n\
1393 with preprocessed source if appropriate.\n\
1394 See %s for instructions.\n", GCCBUGURL);
1395   exit (FATAL_EXIT_CODE);
1396 }
1397
1398 /* Given a partial pathname as input, return another pathname that
1399    shares no directory elements with the pathname of __FILE__.  This
1400    is used by fancy_abort() to print `Internal compiler error in expr.c'
1401    instead of `Internal compiler error in ../../GCC/gcc/expr.c'.  */
1402
1403 const char *
1404 trim_filename (name)
1405      const char *name;
1406 {
1407   static const char this_file[] = __FILE__;
1408   const char *p = name, *q = this_file;
1409
1410   /* First skip any "../" in each filename.  This allows us to give a proper
1411      reference to a file in a subdirectory.  */
1412   while (p[0] == '.' && p[1] == '.'
1413          && (p[2] == DIR_SEPARATOR
1414 #ifdef DIR_SEPARATOR_2
1415              || p[2] == DIR_SEPARATOR_2
1416 #endif
1417              ))
1418     p += 3;
1419
1420   while (q[0] == '.' && q[1] == '.'
1421          && (q[2] == DIR_SEPARATOR
1422 #ifdef DIR_SEPARATOR_2
1423              || p[2] == DIR_SEPARATOR_2
1424 #endif
1425              ))
1426     q += 3;
1427
1428   /* Now skip any parts the two filenames have in common.  */
1429   while (*p == *q && *p != 0 && *q != 0)
1430     p++, q++;
1431
1432   /* Now go backwards until the previous directory separator.  */
1433   while (p > name && p[-1] != DIR_SEPARATOR
1434 #ifdef DIR_SEPARATOR_2
1435          && p[-1] != DIR_SEPARATOR_2
1436 #endif
1437          )
1438     p--;
1439
1440   return p;
1441 }
1442
1443 /* Report an internal compiler error in a friendly manner and without
1444    dumping core.  */
1445
1446 void
1447 fancy_abort (file, line, function)
1448      const char *file;
1449      int line;
1450      const char *function;
1451 {
1452   internal_error ("Internal compiler error in %s, at %s:%d",
1453                   function, trim_filename (file), line);
1454 }
1455
1456 /* Setup DC for reporting a diagnostic MESSAGE (an error or a WARNING),
1457    using arguments pointed to by ARGS_PTR, issued at a location specified
1458    by FILE and LINE.  */
1459
1460 void
1461 set_diagnostic_context (dc, msgid, args_ptr, file, line, warn)
1462      diagnostic_context *dc;
1463      const char *msgid;
1464      va_list *args_ptr;
1465      const char *file;
1466      int line;
1467      int warn;
1468 {
1469   memset (dc, 0, sizeof (diagnostic_context));
1470   diagnostic_message (dc) = _(msgid);
1471   diagnostic_argument_list (dc) = args_ptr;
1472   diagnostic_file_location (dc) = file;
1473   diagnostic_line_location (dc) = line;
1474   diagnostic_is_warning (dc) = warn;
1475   diagnostic_starter (dc) = diagnostic_starter (global_dc);
1476   diagnostic_finalizer (dc) = diagnostic_finalizer (global_dc);
1477 }
1478
1479 void
1480 report_problematic_module (buffer)
1481      output_buffer *buffer;
1482 {
1483   struct file_stack *p;
1484
1485   if (output_needs_newline (buffer))
1486     {
1487       output_add_newline (buffer);
1488       output_needs_newline (buffer) = 0;
1489     }
1490
1491   if (input_file_stack && input_file_stack->next != 0
1492       && error_module_changed ())
1493     {
1494       for (p = input_file_stack->next; p; p = p->next)
1495         if (p == input_file_stack->next)
1496           output_verbatim
1497             (buffer, "In file included from %s:%d", p->name, p->line);
1498         else
1499           output_verbatim
1500             (buffer, ",\n                 from %s:%d", p->name, p->line);
1501       output_verbatim (buffer, ":\n");
1502       record_last_error_module ();
1503     }
1504 }
1505
1506 static void
1507 default_diagnostic_starter (buffer, dc)
1508      output_buffer *buffer;
1509      diagnostic_context *dc;
1510 {
1511   report_error_function (diagnostic_file_location (dc));
1512   output_set_prefix (buffer,
1513                      context_as_prefix (diagnostic_file_location (dc),
1514                                         diagnostic_line_location (dc),
1515                                         diagnostic_is_warning (dc)));
1516 }
1517
1518 static void
1519 default_diagnostic_finalizer (buffer, dc)
1520      output_buffer *buffer;
1521      diagnostic_context *dc __attribute__((__unused__));
1522 {
1523   output_destroy_prefix (buffer);
1524 }
1525
1526 void 
1527 warn_deprecated_use (node)
1528      tree node;
1529 {
1530   if (node == 0 || !warn_deprecated_decl)
1531     return;
1532
1533   if (DECL_P (node))
1534     warning ("`%s' is deprecated (declared at %s:%d)",
1535              IDENTIFIER_POINTER (DECL_NAME (node)),
1536              DECL_SOURCE_FILE (node), DECL_SOURCE_LINE (node));
1537   else if (TYPE_P (node))
1538     {
1539       const char *what = NULL;
1540       tree decl = TYPE_STUB_DECL (node);
1541
1542       if (TREE_CODE (TYPE_NAME (node)) == IDENTIFIER_NODE)
1543         what = IDENTIFIER_POINTER (TYPE_NAME (node));
1544       else if (TREE_CODE (TYPE_NAME (node)) == TYPE_DECL
1545                && DECL_NAME (TYPE_NAME (node)))
1546         what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (node)));
1547         
1548       if (what)
1549         {
1550           if (decl)
1551             warning ("`%s' is deprecated (declared at %s:%d)", what,
1552                      DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1553           else
1554             warning ("`%s' is deprecated", what);
1555         }
1556       else if (decl)
1557         warning ("type is deprecated (declared at %s:%d)",
1558                  DECL_SOURCE_FILE (decl), DECL_SOURCE_LINE (decl));
1559       else
1560         warning ("type is deprecated");
1561     }
1562 }