OSDN Git Service

5435022b78fde867b1f0f118affb87e085e9bfc7
[pf3gnuchains/gcc-fork.git] / gcc / cp / error.c
1 /* Call-backs for C++ error reporting.
2    This code is non-reentrant.
3    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2002
4    Free Software Foundation, Inc.
5    This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "tree.h"
25 #include "cp-tree.h"
26 #include "real.h"
27 #include "obstack.h"
28 #include "toplev.h"
29 #include "flags.h"
30 #include "diagnostic.h"
31 #include "langhooks-def.h"
32
33 enum pad { none, before, after };
34
35 #define sorry_for_unsupported_tree(T)                                      \
36    sorry ("`%s' not supported by %s", tree_code_name[(int) TREE_CODE (T)], \
37              __FUNCTION__)
38
39 #define print_scope_operator(BUFFER)  output_add_string ((BUFFER), "::")
40 #define print_left_paren(BUFFER)      output_add_character ((BUFFER), '(')
41 #define print_right_paren(BUFFER)     output_add_character ((BUFFER), ')')
42 #define print_left_bracket(BUFFER)    output_add_character ((BUFFER), '[')
43 #define print_right_bracket(BUFFER)   output_add_character ((BUFFER), ']')
44 #define print_template_argument_list_start(BUFFER) \
45    print_non_consecutive_character ((BUFFER), '<')
46 #define print_template_argument_list_end(BUFFER)  \
47    print_non_consecutive_character ((BUFFER), '>')
48 #define print_whitespace(BUFFER, TFI)        \
49    do {                                      \
50      output_add_space (BUFFER);              \
51      put_whitespace (TFI) = none;            \
52    } while (0)
53 #define print_tree_identifier(BUFFER, TID) \
54    output_add_string ((BUFFER), IDENTIFIER_POINTER (TID))
55 #define print_identifier(BUFFER, ID) output_add_string ((BUFFER), (ID))
56 #define separate_with_comma(BUFFER) output_add_string ((BUFFER), ", ")
57
58 /* The global buffer where we dump everything.  It is there only for
59    transitional purpose.  It is expected, in the near future, to be
60    completely removed.  */
61 static output_buffer scratch_buffer_rec;
62 static output_buffer *scratch_buffer = &scratch_buffer_rec;
63
64 # define NEXT_CODE(T) (TREE_CODE (TREE_TYPE (T)))
65
66 #define reinit_global_formatting_buffer() \
67    output_clear_message_text (scratch_buffer)
68
69 static const char *args_to_string               PARAMS ((tree, int));
70 static const char *assop_to_string              PARAMS ((enum tree_code, int));
71 static const char *code_to_string               PARAMS ((enum tree_code, int));
72 static const char *cv_to_string                 PARAMS ((tree, int));
73 static const char *decl_to_string               PARAMS ((tree, int));
74 static const char *expr_to_string               PARAMS ((tree, int));
75 static const char *fndecl_to_string             PARAMS ((tree, int));
76 static const char *op_to_string                 PARAMS ((enum tree_code, int));
77 static const char *parm_to_string               PARAMS ((int, int));
78 static const char *type_to_string               PARAMS ((tree, int));
79
80 static void dump_type PARAMS ((tree, int));
81 static void dump_typename PARAMS ((tree, int));
82 static void dump_simple_decl PARAMS ((tree, tree, int));
83 static void dump_decl PARAMS ((tree, int));
84 static void dump_template_decl PARAMS ((tree, int));
85 static void dump_function_decl PARAMS ((tree, int));
86 static void dump_expr PARAMS ((tree, int));
87 static void dump_unary_op PARAMS ((const char *, tree, int));
88 static void dump_binary_op PARAMS ((const char *, tree, int));
89 static void dump_aggr_type PARAMS ((tree, int));
90 static enum pad dump_type_prefix PARAMS ((tree, int));
91 static void dump_type_suffix PARAMS ((tree, int));
92 static void dump_function_name PARAMS ((tree, int));
93 static void dump_expr_list PARAMS ((tree, int));
94 static void dump_global_iord PARAMS ((tree));
95 static enum pad dump_qualifiers PARAMS ((tree, enum pad));
96 static void dump_char PARAMS ((int));
97 static void dump_parameters PARAMS ((tree, int));
98 static void dump_exception_spec PARAMS ((tree, int));
99 static const char *class_key_or_enum PARAMS ((tree));
100 static void dump_template_argument PARAMS ((tree, int));
101 static void dump_template_argument_list PARAMS ((tree, int));
102 static void dump_template_parameter PARAMS ((tree, int));
103 static void dump_template_bindings PARAMS ((tree, tree));
104 static void dump_scope PARAMS ((tree, int));
105 static void dump_template_parms PARAMS ((tree, int, int));
106
107 static const char *function_category PARAMS ((tree));
108 static void maybe_print_instantiation_context PARAMS ((output_buffer *));
109 static void print_instantiation_full_context PARAMS ((output_buffer *));
110 static void print_instantiation_partial_context PARAMS ((output_buffer *, tree,
111                                                          const char *, int));
112 static void cp_diagnostic_starter PARAMS ((output_buffer *,
113                                            diagnostic_context *));
114 static void cp_diagnostic_finalizer PARAMS ((output_buffer *,
115                                              diagnostic_context *));
116 static void cp_print_error_function PARAMS ((output_buffer *,
117                                              diagnostic_context *));
118
119 static int cp_printer PARAMS ((output_buffer *));
120 static void print_non_consecutive_character PARAMS ((output_buffer *, int));
121 static void print_integer PARAMS ((output_buffer *, HOST_WIDE_INT));
122 static tree locate_error PARAMS ((const char *, va_list));
123
124 void
125 init_error ()
126 {
127   diagnostic_starter (global_dc) = cp_diagnostic_starter;
128   diagnostic_finalizer (global_dc) = cp_diagnostic_finalizer;
129   diagnostic_format_decoder (global_dc) = cp_printer;
130
131   init_output_buffer (scratch_buffer, /* prefix */NULL, /* line-width */0);
132 }
133
134 /* Dump a scope, if deemed necessary.  */
135
136 static void
137 dump_scope (scope, flags)
138      tree scope;
139      int flags;
140 {
141   int f = ~TFF_RETURN_TYPE & (flags & (TFF_SCOPE | TFF_CHASE_TYPEDEF));
142
143   if (scope == NULL_TREE)
144     return;
145
146   if (TREE_CODE (scope) == NAMESPACE_DECL)
147     {
148       if (scope != global_namespace)
149         {
150           dump_decl (scope, f);
151           print_scope_operator (scratch_buffer);
152         }
153     }
154   else if (AGGREGATE_TYPE_P (scope))
155     {
156       dump_type (scope, f);
157       print_scope_operator (scratch_buffer);
158     }
159   else if ((flags & TFF_SCOPE) && TREE_CODE (scope) == FUNCTION_DECL)
160     {
161       dump_function_decl (scope, f);
162       print_scope_operator (scratch_buffer);
163     }
164 }
165
166 /* Dump type qualifiers, providing padding as requested. Return an
167    indication of whether we dumped something.  */
168
169 static enum pad
170 dump_qualifiers (t, p)
171      tree t;
172      enum pad p;
173 {
174   static const int masks[] =
175     {TYPE_QUAL_CONST, TYPE_QUAL_VOLATILE, TYPE_QUAL_RESTRICT};
176   static const char *const names[] =
177     {"const", "volatile", "__restrict"};
178   int ix;
179   int quals = TYPE_QUALS (t);
180   int do_after = p == after;
181
182   if (quals)
183     {
184       for (ix = 0; ix != 3; ix++)
185         if (masks[ix] & quals)
186           {
187             if (p == before)
188               output_add_space (scratch_buffer);
189             p = before;
190             print_identifier (scratch_buffer, names[ix]);
191           }
192       if (do_after)
193         output_add_space (scratch_buffer);
194     }
195   else
196     p = none;
197   return p;
198 }
199
200 /* This must be large enough to hold any printed integer or floating-point
201    value.  */
202 static char digit_buffer[128];
203
204 /* Dump the template ARGument under control of FLAGS.  */
205
206 static void
207 dump_template_argument (arg, flags)
208      tree arg;
209      int flags;
210 {
211   if (TYPE_P (arg) || TREE_CODE (arg) == TEMPLATE_DECL)
212     dump_type (arg, flags & ~TFF_CLASS_KEY_OR_ENUM);
213   else
214     dump_expr (arg, (flags | TFF_EXPR_IN_PARENS) & ~TFF_CLASS_KEY_OR_ENUM);
215 }
216
217 /* Dump a template-argument-list ARGS (always a TREE_VEC) under control
218    of FLAGS.  */
219
220 static void
221 dump_template_argument_list (args, flags)
222      tree args;
223      int flags;
224 {
225   int n = TREE_VEC_LENGTH (args);
226   int need_comma = 0;
227   int i;
228
229   for (i = 0; i< n; ++i)
230     {
231       if (need_comma)
232         separate_with_comma (scratch_buffer);
233       dump_template_argument (TREE_VEC_ELT (args, i), flags);
234       need_comma = 1;
235     }
236 }
237
238 /* Dump a template parameter PARM (a TREE_LIST) under control of FLAGS.  */
239
240 static void
241 dump_template_parameter (parm, flags)
242      tree parm;
243      int flags;
244 {
245   tree p = TREE_VALUE (parm);
246   tree a = TREE_PURPOSE (parm);
247
248   if (TREE_CODE (p) == TYPE_DECL)
249     {
250       if (flags & TFF_DECL_SPECIFIERS)
251         {
252           print_identifier (scratch_buffer, "class");
253           if (DECL_NAME (p))
254             {
255               output_add_space (scratch_buffer);
256               print_tree_identifier (scratch_buffer, DECL_NAME (p));
257             }
258         }
259       else if (DECL_NAME (p))
260         print_tree_identifier (scratch_buffer, DECL_NAME (p));
261       else
262         print_identifier (scratch_buffer, "{template default argument error}");
263     }
264   else
265     dump_decl (p, flags | TFF_DECL_SPECIFIERS);
266
267   if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && a != NULL_TREE)
268     {
269       output_add_string (scratch_buffer, " = ");
270       if (TREE_CODE (p) == TYPE_DECL || TREE_CODE (p) == TEMPLATE_DECL)
271         dump_type (a, flags & ~TFF_CHASE_TYPEDEF);
272       else
273         dump_expr (a, flags | TFF_EXPR_IN_PARENS);
274     }
275 }
276
277 /* Dump, under control of FLAGS, a template-parameter-list binding.
278    PARMS is a TREE_LIST of TREE_VEC of TREE_LIST and ARGS is a
279    TREE_VEC.  */
280
281 static void
282 dump_template_bindings (parms, args)
283      tree parms, args;
284 {
285   int need_comma = 0;
286
287   while (parms)
288     {
289       tree p = TREE_VALUE (parms);
290       int lvl = TMPL_PARMS_DEPTH (parms);
291       int arg_idx = 0;
292       int i;
293
294       for (i = 0; i < TREE_VEC_LENGTH (p); ++i)
295         {
296           tree arg = NULL_TREE;
297
298           /* Don't crash if we had an invalid argument list.  */
299           if (TMPL_ARGS_DEPTH (args) >= lvl)
300             {
301               tree lvl_args = TMPL_ARGS_LEVEL (args, lvl);
302               if (NUM_TMPL_ARGS (lvl_args) > arg_idx)
303                 arg = TREE_VEC_ELT (lvl_args, arg_idx);
304             }
305
306           if (need_comma)
307             separate_with_comma (scratch_buffer);
308           dump_template_parameter (TREE_VEC_ELT (p, i), TFF_PLAIN_IDENTIFIER);
309           output_add_string (scratch_buffer, " = ");
310           if (arg)
311             dump_template_argument (arg, TFF_PLAIN_IDENTIFIER);
312           else
313             print_identifier (scratch_buffer, "<missing>");
314
315           ++arg_idx;
316           need_comma = 1;
317         }
318
319       parms = TREE_CHAIN (parms);
320     }
321 }
322
323 /* Dump into the obstack a human-readable equivalent of TYPE.  FLAGS
324    controls the format.  */
325
326 static void
327 dump_type (t, flags)
328      tree t;
329      int flags;
330 {
331   if (t == NULL_TREE)
332     return;
333
334   if (TYPE_PTRMEMFUNC_P (t))
335     goto offset_type;
336
337   switch (TREE_CODE (t))
338     {
339     case UNKNOWN_TYPE:
340       print_identifier (scratch_buffer, "<unknown type>");
341       break;
342
343     case TREE_LIST:
344       /* A list of function parms.  */
345       dump_parameters (t, flags);
346       break;
347
348     case IDENTIFIER_NODE:
349       print_tree_identifier (scratch_buffer, t);
350       break;
351
352     case TREE_VEC:
353       dump_type (BINFO_TYPE (t), flags);
354       break;
355
356     case RECORD_TYPE:
357     case UNION_TYPE:
358     case ENUMERAL_TYPE:
359       dump_aggr_type (t, flags);
360       break;
361
362     case TYPE_DECL:
363       if (flags & TFF_CHASE_TYPEDEF)
364         {
365           dump_type (DECL_ORIGINAL_TYPE (t)
366                      ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t), flags);
367           break;
368         }
369       /* else fallthrough */
370
371     case TEMPLATE_DECL:
372     case NAMESPACE_DECL:
373       dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
374       break;
375
376     case COMPLEX_TYPE:
377       output_add_string (scratch_buffer, "__complex__ ");
378       dump_type (TREE_TYPE (t), flags);
379       break;
380
381     case VECTOR_TYPE:
382       output_add_string (scratch_buffer, "vector ");
383       {
384         /* The subtype of a VECTOR_TYPE is something like intQI_type_node,
385            which has no name and is not very useful for diagnostics.  So
386            look up the equivalent C type and print its name.  */
387         tree elt = TREE_TYPE (t);
388         elt = c_common_type_for_mode (TYPE_MODE (elt), TREE_UNSIGNED (elt));
389         dump_type (elt, flags);
390       }
391       break;
392
393     case INTEGER_TYPE:
394       if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
395         output_add_string (scratch_buffer, "unsigned ");
396       else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t))
397         output_add_string (scratch_buffer, "signed ");
398
399       /* fall through.  */
400     case REAL_TYPE:
401     case VOID_TYPE:
402     case BOOLEAN_TYPE:
403       {
404         tree type;
405         dump_qualifiers (t, after);
406         type = flags & TFF_CHASE_TYPEDEF ? TYPE_MAIN_VARIANT (t) : t;
407         if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
408           print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (type));
409         else
410           /* Types like intQI_type_node and friends have no names.
411              These don't come up in user error messages, but it's nice
412              to be able to print them from the debugger.  */
413           print_identifier (scratch_buffer, "<anonymous>");
414       }
415       break;
416
417     case TEMPLATE_TEMPLATE_PARM:
418       /* For parameters inside template signature. */
419       if (TYPE_IDENTIFIER (t))
420         print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
421       else
422         print_identifier
423           (scratch_buffer, "<anonymous template template parameter>");
424       break;
425
426     case BOUND_TEMPLATE_TEMPLATE_PARM:
427       {
428         tree args = TYPE_TI_ARGS (t);
429         print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
430         print_template_argument_list_start (scratch_buffer);
431         dump_template_argument_list (args, flags);
432         print_template_argument_list_end (scratch_buffer);
433       }
434       break;
435
436     case TEMPLATE_TYPE_PARM:
437       dump_qualifiers (t, after);
438       if (TYPE_IDENTIFIER (t))
439         print_tree_identifier (scratch_buffer, TYPE_IDENTIFIER (t));
440       else
441         print_identifier
442           (scratch_buffer, "<anonymous template type parameter>");
443       break;
444
445       /* This is not always necessary for pointers and such, but doing this
446          reduces code size.  */
447     case ARRAY_TYPE:
448     case POINTER_TYPE:
449     case REFERENCE_TYPE:
450     case OFFSET_TYPE:
451     offset_type:
452     case FUNCTION_TYPE:
453     case METHOD_TYPE:
454     {
455       dump_type_prefix (t, flags);
456       dump_type_suffix (t, flags);
457       break;
458     }
459     case TYPENAME_TYPE:
460       if (!IMPLICIT_TYPENAME_P (t))
461         output_add_string (scratch_buffer, "typename ");
462       dump_typename (t, flags);
463       break;
464
465     case UNBOUND_CLASS_TEMPLATE:
466       dump_type (TYPE_CONTEXT (t), flags);
467       print_scope_operator (scratch_buffer);
468       print_identifier (scratch_buffer, "template ");
469       dump_type (DECL_NAME (TYPE_NAME (t)), flags);
470       break;
471
472     case TYPEOF_TYPE:
473       output_add_string (scratch_buffer, "__typeof (");
474       dump_expr (TYPE_FIELDS (t), flags & ~TFF_EXPR_IN_PARENS);
475       print_right_paren (scratch_buffer);
476       break;
477
478     default:
479       sorry_for_unsupported_tree (t);
480       /* Fall through to error. */
481
482     case ERROR_MARK:
483       print_identifier (scratch_buffer, "<type error>");
484       break;
485     }
486 }
487
488 /* Dump a TYPENAME_TYPE. We need to notice when the context is itself
489    a TYPENAME_TYPE.  */
490
491 static void
492 dump_typename (t, flags)
493      tree t;
494      int flags;
495 {
496   tree ctx = TYPE_CONTEXT (t);
497
498   if (TREE_CODE (ctx) == TYPENAME_TYPE)
499     dump_typename (ctx, flags);
500   else
501     dump_type (ctx, flags & ~TFF_CLASS_KEY_OR_ENUM);
502   print_scope_operator (scratch_buffer);
503   dump_decl (TYPENAME_TYPE_FULLNAME (t), flags);
504 }
505
506 /* Return the name of the supplied aggregate, or enumeral type.  */
507
508 static const char *
509 class_key_or_enum (t)
510      tree t;
511 {
512   if (TREE_CODE (t) == ENUMERAL_TYPE)
513     return "enum";
514   else if (TREE_CODE (t) == UNION_TYPE)
515     return "union";
516   else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
517     return "class";
518   else
519     return "struct";
520 }
521
522 /* Print out a class declaration T under the control of FLAGS,
523    in the form `class foo'.  */
524
525 static void
526 dump_aggr_type (t, flags)
527      tree t;
528      int flags;
529 {
530   tree name;
531   const char *variety = class_key_or_enum (t);
532   int typdef = 0;
533   int tmplate = 0;
534
535   dump_qualifiers (t, after);
536
537   if (flags & TFF_CLASS_KEY_OR_ENUM)
538     {
539       print_identifier (scratch_buffer, variety);
540       output_add_space (scratch_buffer);
541     }
542
543   if (flags & TFF_CHASE_TYPEDEF)
544     t = TYPE_MAIN_VARIANT (t);
545
546   name = TYPE_NAME (t);
547
548   if (name)
549     {
550       typdef = !DECL_ARTIFICIAL (name);
551       tmplate = !typdef && TREE_CODE (t) != ENUMERAL_TYPE
552                 && TYPE_LANG_SPECIFIC (t) && CLASSTYPE_TEMPLATE_INFO (t)
553                 && (CLASSTYPE_TEMPLATE_SPECIALIZATION (t)
554                     || TREE_CODE (CLASSTYPE_TI_TEMPLATE (t)) != TEMPLATE_DECL
555                     || DECL_TEMPLATE_SPECIALIZATION (CLASSTYPE_TI_TEMPLATE (t))
556                     || PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
557       dump_scope (CP_DECL_CONTEXT (name), flags | TFF_SCOPE);
558       if (tmplate)
559         {
560           /* Because the template names are mangled, we have to locate
561              the most general template, and use that name.  */
562           tree tpl = CLASSTYPE_TI_TEMPLATE (t);
563
564           while (DECL_TEMPLATE_INFO (tpl))
565             tpl = DECL_TI_TEMPLATE (tpl);
566           name = tpl;
567         }
568       name = DECL_NAME (name);
569     }
570
571   if (name == 0 || ANON_AGGRNAME_P (name))
572     {
573       if (flags & TFF_CLASS_KEY_OR_ENUM)
574         print_identifier (scratch_buffer, "<anonymous>");
575       else
576         output_printf (scratch_buffer, "<anonymous %s>", variety);
577     }
578   else
579     print_tree_identifier (scratch_buffer, name);
580   if (tmplate)
581     dump_template_parms (TYPE_TEMPLATE_INFO (t),
582                          !CLASSTYPE_USE_TEMPLATE (t),
583                          flags & ~TFF_TEMPLATE_HEADER);
584 }
585
586 /* Dump into the obstack the initial part of the output for a given type.
587    This is necessary when dealing with things like functions returning
588    functions.  Examples:
589
590    return type of `int (* fee ())()': pointer -> function -> int.  Both
591    pointer (and reference and offset) and function (and member) types must
592    deal with prefix and suffix.
593
594    Arrays must also do this for DECL nodes, like int a[], and for things like
595    int *[]&.
596
597    Return indicates how you should pad an object name after this. I.e. you
598    want to pad non-*, non-& cores, but not pad * or & types.  */
599
600 static enum pad
601 dump_type_prefix (t, flags)
602      tree t;
603      int flags;
604 {
605   enum pad padding = before;
606
607   if (TYPE_PTRMEMFUNC_P (t))
608     {
609       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
610       goto offset_type;
611     }
612
613   switch (TREE_CODE (t))
614     {
615     case POINTER_TYPE:
616     case REFERENCE_TYPE:
617       {
618         tree sub = TREE_TYPE (t);
619
620         padding = dump_type_prefix (sub, flags);
621         /* A tree for a member pointer looks like pointer to offset,
622            so let the OFFSET_TYPE case handle it.  */
623         if (!TYPE_PTRMEM_P (t))
624           {
625             if (TREE_CODE (sub) == ARRAY_TYPE)
626               {
627                 output_add_space (scratch_buffer);
628                 print_left_paren (scratch_buffer);
629               }
630             output_add_character
631               (scratch_buffer, "&*"[TREE_CODE (t) == POINTER_TYPE]);
632             padding = dump_qualifiers (t, before);
633           }
634       }
635       break;
636
637     case OFFSET_TYPE:
638     offset_type:
639       padding = dump_type_prefix (TREE_TYPE (t), flags);
640       if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */
641         {
642           if (padding != none)
643             output_add_space (scratch_buffer);
644           dump_type (TYPE_OFFSET_BASETYPE (t), flags);
645           print_scope_operator (scratch_buffer);
646         }
647       output_add_character (scratch_buffer, '*');
648       padding = dump_qualifiers (t, none);
649       break;
650
651       /* Can only be reached through function pointer -- this would not be
652          correct if FUNCTION_DECLs used it.  */
653     case FUNCTION_TYPE:
654       padding = dump_type_prefix (TREE_TYPE (t), flags);
655       if (padding != none)
656         output_add_space (scratch_buffer);
657       print_left_paren (scratch_buffer);
658       padding = none;
659       break;
660
661     case METHOD_TYPE:
662       padding = dump_type_prefix (TREE_TYPE (t), flags);
663       if (padding != none)
664         output_add_space (scratch_buffer);
665       print_left_paren (scratch_buffer);
666       padding = none;
667       dump_aggr_type (TYPE_METHOD_BASETYPE (t), flags);
668       print_scope_operator (scratch_buffer);
669       break;
670
671     case ARRAY_TYPE:
672       padding = dump_type_prefix (TREE_TYPE (t), flags);
673       break;
674
675     case ENUMERAL_TYPE:
676     case IDENTIFIER_NODE:
677     case INTEGER_TYPE:
678     case BOOLEAN_TYPE:
679     case REAL_TYPE:
680     case RECORD_TYPE:
681     case TEMPLATE_TYPE_PARM:
682     case TEMPLATE_TEMPLATE_PARM:
683     case BOUND_TEMPLATE_TEMPLATE_PARM:
684     case TREE_LIST:
685     case TYPE_DECL:
686     case TREE_VEC:
687     case UNION_TYPE:
688     case UNKNOWN_TYPE:
689     case VOID_TYPE:
690     case TYPENAME_TYPE:
691     case COMPLEX_TYPE:
692     case VECTOR_TYPE:
693       dump_type (t, flags);
694       padding = before;
695       break;
696
697     default:
698       sorry_for_unsupported_tree (t);
699       /* fall through.  */
700     case ERROR_MARK:
701       print_identifier (scratch_buffer, "<typeprefixerror>");
702       break;
703     }
704   return padding;
705 }
706
707 /* Dump the suffix of type T, under control of FLAGS.  This is the part
708    which appears after the identifier (or function parms).  */
709
710 static void
711 dump_type_suffix (t, flags)
712      tree t;
713      int flags;
714 {
715   if (TYPE_PTRMEMFUNC_P (t))
716     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
717
718   switch (TREE_CODE (t))
719     {
720     case POINTER_TYPE:
721     case REFERENCE_TYPE:
722     case OFFSET_TYPE:
723       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
724         print_right_paren (scratch_buffer);
725       dump_type_suffix (TREE_TYPE (t), flags);
726       break;
727
728       /* Can only be reached through function pointer */
729     case FUNCTION_TYPE:
730     case METHOD_TYPE:
731       {
732         tree arg;
733         print_right_paren (scratch_buffer);
734         arg = TYPE_ARG_TYPES (t);
735         if (TREE_CODE (t) == METHOD_TYPE)
736           arg = TREE_CHAIN (arg);
737
738         /* Function pointers don't have default args.  Not in standard C++,
739            anyway; they may in g++, but we'll just pretend otherwise.  */
740         dump_parameters (arg, flags & ~TFF_FUNCTION_DEFAULT_ARGUMENTS);
741
742         if (TREE_CODE (t) == METHOD_TYPE)
743           dump_qualifiers
744             (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
745         dump_exception_spec (TYPE_RAISES_EXCEPTIONS (t), flags);
746         dump_type_suffix (TREE_TYPE (t), flags);
747         break;
748       }
749
750     case ARRAY_TYPE:
751       print_left_bracket (scratch_buffer);
752       if (TYPE_DOMAIN (t))
753         {
754           if (host_integerp (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
755             print_integer
756               (scratch_buffer,
757                tree_low_cst (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0) + 1);
758           else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
759             dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0),
760                        flags & ~TFF_EXPR_IN_PARENS);
761           else
762             dump_expr (fold (cp_build_binary_op
763                              (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
764                               integer_one_node)),
765                        flags & ~TFF_EXPR_IN_PARENS);
766         }
767       print_right_bracket (scratch_buffer);
768       dump_type_suffix (TREE_TYPE (t), flags);
769       break;
770
771     case ENUMERAL_TYPE:
772     case IDENTIFIER_NODE:
773     case INTEGER_TYPE:
774     case BOOLEAN_TYPE:
775     case REAL_TYPE:
776     case RECORD_TYPE:
777     case TEMPLATE_TYPE_PARM:
778     case TEMPLATE_TEMPLATE_PARM:
779     case BOUND_TEMPLATE_TEMPLATE_PARM:
780     case TREE_LIST:
781     case TYPE_DECL:
782     case TREE_VEC:
783     case UNION_TYPE:
784     case UNKNOWN_TYPE:
785     case VOID_TYPE:
786     case TYPENAME_TYPE:
787     case COMPLEX_TYPE:
788     case VECTOR_TYPE:
789       break;
790
791     default:
792       sorry_for_unsupported_tree (t);
793     case ERROR_MARK:
794       /* Don't mark it here, we should have already done in
795          dump_type_prefix.  */
796       break;
797     }
798 }
799
800 static void
801 dump_global_iord (t)
802      tree t;
803 {
804   const char *p = NULL;
805
806   if (DECL_GLOBAL_CTOR_P (t))
807     p = "initializers";
808   else if (DECL_GLOBAL_DTOR_P (t))
809     p = "destructors";
810   else
811     abort ();
812
813   output_printf (scratch_buffer, "(static %s for %s)", p, input_filename);
814 }
815
816 static void
817 dump_simple_decl (t, type, flags)
818      tree t;
819      tree type;
820      int flags;
821 {
822   if (flags & TFF_DECL_SPECIFIERS)
823     {
824       if (dump_type_prefix (type, flags) != none)
825         output_add_space (scratch_buffer);
826     }
827   if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
828     dump_scope (CP_DECL_CONTEXT (t), flags);
829   if (DECL_NAME (t))
830     dump_decl (DECL_NAME (t), flags);
831   else
832     print_identifier (scratch_buffer, "<anonymous>");
833   if (flags & TFF_DECL_SPECIFIERS)
834     dump_type_suffix (type, flags);
835 }
836
837 /* Dump a human readable string for the decl T under control of FLAGS.  */
838
839 static void
840 dump_decl (t, flags)
841      tree t;
842      int flags;
843 {
844   if (t == NULL_TREE)
845     return;
846
847   switch (TREE_CODE (t))
848     {
849     case TYPE_DECL:
850       {
851         /* Don't say 'typedef class A' */
852         if (DECL_ARTIFICIAL (t))
853           {
854             if ((flags & TFF_DECL_SPECIFIERS)
855                 && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
856               /* Say `class T' not just `T'. */
857               output_add_string (scratch_buffer, "class ");
858
859             dump_type (TREE_TYPE (t), flags);
860             break;
861           }
862       }
863       if (flags & TFF_DECL_SPECIFIERS)
864         output_add_string (scratch_buffer, "typedef ");
865       dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
866                         ? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
867                         flags);
868       break;
869
870     case VAR_DECL:
871       if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
872         {
873           output_add_string (scratch_buffer, "vtable for ");
874           my_friendly_assert (TYPE_P (DECL_CONTEXT (t)), 20010720);
875           dump_type (DECL_CONTEXT (t), flags);
876           break;
877         }
878       /* else fall through */
879     case FIELD_DECL:
880     case PARM_DECL:
881       dump_simple_decl (t, TREE_TYPE (t), flags);
882       break;
883
884     case RESULT_DECL:
885       output_add_string (scratch_buffer, "<return value> ");
886       dump_simple_decl (t, TREE_TYPE (t), flags);
887       break;
888
889     case NAMESPACE_DECL:
890       dump_scope (CP_DECL_CONTEXT (t), flags);
891       if (DECL_NAME (t) == anonymous_namespace_name)
892         print_identifier (scratch_buffer, "<unnamed>");
893       else
894         print_tree_identifier (scratch_buffer, DECL_NAME (t));
895       break;
896
897     case SCOPE_REF:
898       dump_decl (TREE_OPERAND (t, 0), flags & ~TFF_DECL_SPECIFIERS);
899       print_scope_operator (scratch_buffer); 
900       dump_decl (TREE_OPERAND (t, 1), flags);
901       break;
902
903     case ARRAY_REF:
904       dump_decl (TREE_OPERAND (t, 0), flags);
905       print_left_bracket (scratch_buffer);
906       dump_decl (TREE_OPERAND (t, 1), flags);
907       print_right_bracket (scratch_buffer);
908       break;
909
910       /* So that we can do dump_decl on an aggr type.  */
911     case RECORD_TYPE:
912     case UNION_TYPE:
913     case ENUMERAL_TYPE:
914       dump_type (t, flags);
915       break;
916
917     case TYPE_EXPR:
918       abort ();
919       break;
920
921       /* These special cases are duplicated here so that other functions
922          can feed identifiers to error and get them demangled properly.  */
923     case IDENTIFIER_NODE:
924       if (IDENTIFIER_TYPENAME_P (t))
925         {
926           output_add_string (scratch_buffer, "operator ");
927           /* Not exactly IDENTIFIER_TYPE_VALUE.  */
928           dump_type (TREE_TYPE (t), flags);
929           break;
930         }
931       else
932         print_tree_identifier (scratch_buffer, t);
933       break;
934
935     case OVERLOAD:
936       t = OVL_CURRENT (t);
937       /* Fall through.  */
938
939     case FUNCTION_DECL:
940       if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
941         dump_global_iord (t);
942       else if (! DECL_LANG_SPECIFIC (t))
943         print_identifier (scratch_buffer, "<internal>");
944       else
945         dump_function_decl (t, flags);
946       break;
947
948     case TEMPLATE_DECL:
949       dump_template_decl (t, flags);
950       break;
951
952     case TEMPLATE_ID_EXPR:
953       {
954         tree args;
955         tree name = TREE_OPERAND (t, 0);
956         if (is_overloaded_fn (name))
957           name = DECL_NAME (get_first_fn (name));
958         dump_decl (name, flags);
959         print_template_argument_list_start (scratch_buffer);
960         for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
961           {
962             dump_template_argument (TREE_VALUE (args), flags);
963             if (TREE_CHAIN (args))
964               separate_with_comma (scratch_buffer);
965           }
966         print_template_argument_list_end (scratch_buffer);
967       }
968       break;
969
970     case LOOKUP_EXPR:
971       dump_decl (TREE_OPERAND (t, 0), flags);
972       break;
973
974     case LABEL_DECL:
975       print_tree_identifier (scratch_buffer, DECL_NAME (t));
976       break;
977
978     case CONST_DECL:
979       if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
980           || (DECL_INITIAL (t) &&
981               TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
982         dump_simple_decl (t, TREE_TYPE (t), flags);
983       else if (DECL_NAME (t))
984         dump_decl (DECL_NAME (t), flags);
985       else if (DECL_INITIAL (t))
986         dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
987       else
988         print_identifier (scratch_buffer, "enumerator");
989       break;
990
991     case USING_DECL:
992       output_add_string (scratch_buffer, "using ");
993       dump_type (DECL_INITIAL (t), flags);
994       print_scope_operator (scratch_buffer);
995       print_tree_identifier (scratch_buffer, DECL_NAME (t));
996       break;
997
998     default:
999       sorry_for_unsupported_tree (t);
1000       /* Fallthrough to error.  */
1001
1002     case ERROR_MARK:
1003       print_identifier (scratch_buffer, "<declaration error>");
1004       break;
1005     }
1006 }
1007
1008 /* Dump a template declaration T under control of FLAGS. This means the
1009    'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
1010
1011 static void
1012 dump_template_decl (t, flags)
1013      tree t;
1014      int flags;
1015 {
1016   tree orig_parms = DECL_TEMPLATE_PARMS (t);
1017   tree parms;
1018   int i;
1019
1020   if (flags & TFF_TEMPLATE_HEADER)
1021     {
1022       for (parms = orig_parms = nreverse (orig_parms);
1023            parms;
1024            parms = TREE_CHAIN (parms))
1025         {
1026           tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
1027           int len = TREE_VEC_LENGTH (inner_parms);
1028
1029           output_add_string (scratch_buffer, "template<");
1030
1031           /* If we've shown the template prefix, we'd better show the
1032              parameters' and decl's type too.  */
1033             flags |= TFF_DECL_SPECIFIERS;
1034
1035           for (i = 0; i < len; i++)
1036             {
1037               if (i)
1038                 separate_with_comma (scratch_buffer);
1039               dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
1040             }
1041           print_template_argument_list_end (scratch_buffer);
1042           output_add_space (scratch_buffer);
1043         }
1044       nreverse(orig_parms);
1045
1046       if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
1047         /* Say `template<arg> class TT' not just `template<arg> TT'. */
1048         output_add_string (scratch_buffer, "class ");
1049     }
1050
1051   if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
1052     dump_type (TREE_TYPE (t),
1053                ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
1054                 | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
1055   else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
1056     dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
1057   else if (TREE_TYPE (t) == NULL_TREE)
1058     abort ();
1059   else
1060     switch (NEXT_CODE (t))
1061     {
1062       case METHOD_TYPE:
1063       case FUNCTION_TYPE:
1064         dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
1065         break;
1066       default:
1067         /* This case can occur with some illegal code.  */
1068         dump_type (TREE_TYPE (t),
1069                    (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
1070                    | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0));
1071     }
1072 }
1073
1074 /* Pretty print a function decl. There are several ways we want to print a
1075    function declaration. The TFF_ bits in FLAGS tells us how to behave.
1076    As error can only apply the '#' flag once to give 0 and 1 for V, there
1077    is %D which doesn't print the throw specs, and %F which does. */
1078
1079 static void
1080 dump_function_decl (t, flags)
1081      tree t;
1082      int flags;
1083 {
1084   tree fntype;
1085   tree parmtypes;
1086   tree cname = NULL_TREE;
1087   tree template_args = NULL_TREE;
1088   tree template_parms = NULL_TREE;
1089   int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
1090
1091   if (TREE_CODE (t) == TEMPLATE_DECL)
1092     t = DECL_TEMPLATE_RESULT (t);
1093
1094   /* Pretty print template instantiations only.  */
1095   if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
1096     {
1097       tree tmpl;
1098
1099       template_args = DECL_TI_ARGS (t);
1100       tmpl = most_general_template (t);
1101       if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
1102         {
1103           template_parms = DECL_TEMPLATE_PARMS (tmpl);
1104           t = tmpl;
1105         }
1106     }
1107
1108   fntype = TREE_TYPE (t);
1109   parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
1110
1111   if (DECL_CLASS_SCOPE_P (t))
1112     cname = DECL_CONTEXT (t);
1113   /* this is for partially instantiated template methods */
1114   else if (TREE_CODE (fntype) == METHOD_TYPE)
1115     cname = TREE_TYPE (TREE_VALUE (parmtypes));
1116
1117   if (!(flags & TFF_DECL_SPECIFIERS))
1118     /* OK */;
1119   else if (DECL_STATIC_FUNCTION_P (t))
1120     print_identifier (scratch_buffer, "static ");
1121   else if (DECL_VIRTUAL_P (t))
1122     print_identifier (scratch_buffer, "virtual ");
1123
1124   /* Print the return type?  */
1125   if (show_return)
1126     show_return = !DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
1127                   && !DECL_DESTRUCTOR_P (t);
1128   if (show_return)
1129     {
1130       dump_type_prefix (TREE_TYPE (fntype), flags);
1131       output_add_space (scratch_buffer);
1132     }
1133
1134   /* Print the function name.  */
1135   if (cname)
1136     {
1137       dump_type (cname, flags);
1138       print_scope_operator (scratch_buffer);
1139     }
1140   else
1141     dump_scope (CP_DECL_CONTEXT (t), flags);
1142
1143   dump_function_name (t, flags);
1144
1145   if (1)
1146     {
1147       dump_parameters (parmtypes, flags);
1148
1149       if (TREE_CODE (fntype) == METHOD_TYPE)
1150         dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
1151                          before);
1152
1153       if (flags & TFF_EXCEPTION_SPECIFICATION)
1154         dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
1155
1156       if (show_return)
1157         dump_type_suffix (TREE_TYPE (fntype), flags);
1158     }
1159
1160   /* If T is a template instantiation, dump the parameter binding.  */
1161   if (template_parms != NULL_TREE && template_args != NULL_TREE)
1162     {
1163       output_add_string (scratch_buffer, " [with ");
1164       dump_template_bindings (template_parms, template_args);
1165       print_right_bracket (scratch_buffer);
1166     }
1167 }
1168
1169 /* Print a parameter list. If this is for a member function, the
1170    member object ptr (and any other hidden args) should have
1171    already been removed. */
1172
1173 static void
1174 dump_parameters (parmtypes, flags)
1175      tree parmtypes;
1176      int flags;
1177 {
1178   int first;
1179
1180   print_left_paren (scratch_buffer);
1181
1182   for (first = 1; parmtypes != void_list_node;
1183        parmtypes = TREE_CHAIN (parmtypes))
1184     {
1185       if (!first)
1186         separate_with_comma (scratch_buffer);
1187       first = 0;
1188       if (!parmtypes)
1189         {
1190           print_identifier (scratch_buffer, "...");
1191           break;
1192         }
1193       dump_type (TREE_VALUE (parmtypes), flags);
1194
1195       if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
1196         {
1197           output_add_string (scratch_buffer, " = ");
1198           dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
1199         }
1200     }
1201
1202   print_right_paren (scratch_buffer);
1203 }
1204
1205 /* Print an exception specification. T is the exception specification. */
1206
1207 static void
1208 dump_exception_spec (t, flags)
1209      tree t;
1210      int flags;
1211 {
1212   if (t)
1213     {
1214       output_add_string (scratch_buffer, " throw (");
1215       if (TREE_VALUE (t) != NULL_TREE)
1216         while (1)
1217           {
1218             dump_type (TREE_VALUE (t), flags);
1219             t = TREE_CHAIN (t);
1220             if (!t)
1221               break;
1222             separate_with_comma (scratch_buffer);
1223           }
1224       print_right_paren (scratch_buffer);
1225     }
1226 }
1227
1228 /* Handle the function name for a FUNCTION_DECL node, grokking operators
1229    and destructors properly.  */
1230
1231 static void
1232 dump_function_name (t, flags)
1233      tree t;
1234      int flags;
1235 {
1236   tree name = DECL_NAME (t);
1237
1238   /* Don't let the user see __comp_ctor et al.  */
1239   if (DECL_CONSTRUCTOR_P (t)
1240       || DECL_DESTRUCTOR_P (t))
1241     name = constructor_name (DECL_CONTEXT (t));
1242
1243   if (DECL_DESTRUCTOR_P (t))
1244     {
1245       output_add_character (scratch_buffer, '~');
1246       dump_decl (name, TFF_PLAIN_IDENTIFIER);
1247     }
1248   else if (DECL_CONV_FN_P (t))
1249     {
1250       /* This cannot use the hack that the operator's return
1251          type is stashed off of its name because it may be
1252          used for error reporting.  In the case of conflicting
1253          declarations, both will have the same name, yet
1254          the types will be different, hence the TREE_TYPE field
1255          of the first name will be clobbered by the second.  */
1256       output_add_string (scratch_buffer, "operator ");
1257       dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
1258     }
1259   else if (IDENTIFIER_OPNAME_P (name))
1260     print_tree_identifier (scratch_buffer, name);
1261   else
1262     dump_decl (name, flags);
1263
1264   if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
1265       && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
1266       && (DECL_TEMPLATE_SPECIALIZATION (t)
1267           || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
1268           || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
1269           || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
1270     dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags);
1271 }
1272
1273 /* Dump the template parameters from the template info INFO under control of
1274    FLAGS. PRIMARY indicates whether this is a primary template decl, or
1275    specialization (partial or complete). For partial specializations we show
1276    the specialized parameter values. For a primary template we show no
1277    decoration.  */
1278
1279 static void
1280 dump_template_parms (info, primary, flags)
1281      tree info;
1282      int primary;
1283      int flags;
1284 {
1285   tree args = info ? TI_ARGS (info) : NULL_TREE;
1286
1287   if (primary && flags & TFF_TEMPLATE_NAME)
1288     return;
1289   flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
1290   print_template_argument_list_start (scratch_buffer);
1291
1292   /* Be careful only to print things when we have them, so as not
1293          to crash producing error messages.  */
1294   if (args && !primary)
1295     {
1296       int len = 0;
1297       int ix = 0;
1298       int need_comma = 0;
1299
1300       if (TREE_CODE (args) == TREE_VEC)
1301         {
1302           if (TREE_VEC_LENGTH (args) > 0
1303               && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
1304             args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
1305
1306           len = TREE_VEC_LENGTH (args);
1307         }
1308       else if (TREE_CODE (args) == TREE_LIST)
1309         len = -1;
1310       while (ix != len && args)
1311         {
1312           tree arg;
1313           if (len >= 0)
1314             {
1315               arg = TREE_VEC_ELT (args, ix);
1316               ix++;
1317             }
1318           else
1319             {
1320               arg = TREE_VALUE (args);
1321               args = TREE_CHAIN (args);
1322             }
1323           if (need_comma)
1324             separate_with_comma (scratch_buffer);
1325           
1326           if (!arg)
1327             print_identifier (scratch_buffer, "<template parameter error>");
1328           else
1329             dump_template_argument (arg, flags);
1330           need_comma = 1;
1331         }
1332     }
1333   else if (primary)
1334     {
1335       tree tpl = TI_TEMPLATE (info);
1336       tree parms = DECL_TEMPLATE_PARMS (tpl);
1337       int len, ix;
1338
1339       parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
1340       len = parms ? TREE_VEC_LENGTH (parms) : 0;
1341
1342       for (ix = 0; ix != len; ix++)
1343         {
1344           tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
1345
1346           if (ix)
1347             separate_with_comma (scratch_buffer);
1348
1349           dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
1350         }
1351     }
1352   print_template_argument_list_end (scratch_buffer);
1353 }
1354
1355 static void
1356 dump_char (c)
1357      int c;
1358 {
1359   switch (c)
1360     {
1361     case TARGET_NEWLINE:
1362       output_add_string (scratch_buffer, "\\n");
1363       break;
1364     case TARGET_TAB:
1365       output_add_string (scratch_buffer, "\\t");
1366       break;
1367     case TARGET_VT:
1368       output_add_string (scratch_buffer, "\\v");
1369       break;
1370     case TARGET_BS:
1371       output_add_string (scratch_buffer, "\\b");
1372       break;
1373     case TARGET_CR:
1374       output_add_string (scratch_buffer, "\\r");
1375       break;
1376     case TARGET_FF:
1377       output_add_string (scratch_buffer, "\\f");
1378       break;
1379     case TARGET_BELL:
1380       output_add_string (scratch_buffer, "\\a");
1381       break;
1382     case '\\':
1383       output_add_string (scratch_buffer, "\\\\");
1384       break;
1385     case '\'':
1386       output_add_string (scratch_buffer, "\\'");
1387       break;
1388     case '\"':
1389       output_add_string (scratch_buffer, "\\\"");
1390       break;
1391     default:
1392       if (ISPRINT (c))
1393         output_add_character (scratch_buffer, c);
1394       else
1395         {
1396           sprintf (digit_buffer, "\\%03o", (int) c);
1397           output_add_string (scratch_buffer, digit_buffer);
1398         }
1399     }
1400 }
1401
1402 /* Print out a list of initializers (subr of dump_expr) */
1403
1404 static void
1405 dump_expr_list (l, flags)
1406      tree l;
1407      int flags;
1408 {
1409   while (l)
1410     {
1411       dump_expr (TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
1412       l = TREE_CHAIN (l);
1413       if (l)
1414         separate_with_comma (scratch_buffer);
1415     }
1416 }
1417
1418 /* Print out an expression E under control of FLAGS. */
1419
1420 static void
1421 dump_expr (t, flags)
1422      tree t;
1423      int flags;
1424 {
1425   switch (TREE_CODE (t))
1426     {
1427     case VAR_DECL:
1428     case PARM_DECL:
1429     case FIELD_DECL:
1430     case CONST_DECL:
1431     case FUNCTION_DECL:
1432     case TEMPLATE_DECL:
1433     case NAMESPACE_DECL:
1434     case OVERLOAD:
1435       dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
1436       break;
1437
1438     case INTEGER_CST:
1439       {
1440         tree type = TREE_TYPE (t);
1441         my_friendly_assert (type != 0, 81);
1442
1443         /* If it's an enum, output its tag, rather than its value.  */
1444         if (TREE_CODE (type) == ENUMERAL_TYPE)
1445           {
1446             tree values = TYPE_VALUES (type);
1447
1448             for (; values;
1449                  values = TREE_CHAIN (values))
1450               if (tree_int_cst_equal (TREE_VALUE (values), t))
1451                 break;
1452
1453             if (values)
1454               print_tree_identifier (scratch_buffer, TREE_PURPOSE (values));
1455             else
1456               {
1457                 /* Value must have been cast.  */
1458                 print_left_paren (scratch_buffer);
1459                 dump_type (type, flags);
1460                 print_right_paren (scratch_buffer);
1461                 goto do_int;
1462               }
1463           }
1464         else if (type == boolean_type_node)
1465           {
1466             if (t == boolean_false_node || integer_zerop (t))
1467               print_identifier (scratch_buffer, "false");
1468             else if (t == boolean_true_node)
1469               print_identifier (scratch_buffer, "true");
1470           }
1471         else if (type == char_type_node)
1472           {
1473             output_add_character (scratch_buffer, '\'');
1474             dump_char (tree_low_cst (t, 0));
1475             output_add_character (scratch_buffer, '\'');
1476           }
1477         else
1478           {
1479             do_int:
1480             if (! host_integerp (t, 0))
1481               {
1482                 tree val = t;
1483
1484                 if (tree_int_cst_sgn (val) < 0)
1485                   {
1486                     output_add_character (scratch_buffer, '-');
1487                     val = build_int_2 (-TREE_INT_CST_LOW (val),
1488                                        ~TREE_INT_CST_HIGH (val)
1489                                        + !TREE_INT_CST_LOW (val));
1490                   }
1491                 /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
1492                    systems?  */
1493                 {
1494                   static char format[10]; /* "%x%09999x\0" */
1495                   if (!format[0])
1496                     sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
1497                   sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
1498                            TREE_INT_CST_LOW (val));
1499                   output_add_string (scratch_buffer, digit_buffer);
1500                 }
1501               }
1502             else
1503               print_integer (scratch_buffer, TREE_INT_CST_LOW (t));
1504           }
1505       }
1506       break;
1507
1508     case REAL_CST:
1509       {
1510         const unsigned char *p = (const unsigned char *) &TREE_REAL_CST (t);
1511         size_t i;
1512         strcpy (digit_buffer, "0x");
1513         for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
1514           sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
1515       }
1516       output_add_string (scratch_buffer, digit_buffer);
1517       break;
1518
1519     case PTRMEM_CST:
1520       output_add_character (scratch_buffer, '&');
1521       dump_type (PTRMEM_CST_CLASS (t), flags);
1522       print_scope_operator (scratch_buffer);
1523       print_tree_identifier
1524         (scratch_buffer, DECL_NAME (PTRMEM_CST_MEMBER (t)));
1525       break;
1526
1527     case STRING_CST:
1528       {
1529         const char *p = TREE_STRING_POINTER (t);
1530         int len = TREE_STRING_LENGTH (t) - 1;
1531         int i;
1532
1533         output_add_character (scratch_buffer, '\"');
1534         for (i = 0; i < len; i++)
1535           dump_char (p[i]);
1536         output_add_character (scratch_buffer, '\"');
1537       }
1538       break;
1539
1540     case COMPOUND_EXPR:
1541       print_left_paren (scratch_buffer);
1542       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1543       separate_with_comma (scratch_buffer);
1544       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1545       print_right_paren (scratch_buffer);
1546       break;
1547
1548     case COND_EXPR:
1549       print_left_paren (scratch_buffer);
1550       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1551       output_add_string (scratch_buffer, " ? ");
1552       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1553       output_add_string (scratch_buffer, " : ");
1554       dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
1555       print_right_paren (scratch_buffer);
1556       break;
1557
1558     case SAVE_EXPR:
1559       if (TREE_HAS_CONSTRUCTOR (t))
1560         {
1561           output_add_string (scratch_buffer, "new ");
1562           dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
1563         }
1564       else
1565         {
1566           dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1567         }
1568       break;
1569
1570     case AGGR_INIT_EXPR:
1571       {
1572         tree fn = NULL_TREE;
1573
1574         if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
1575           fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
1576
1577         if (fn && TREE_CODE (fn) == FUNCTION_DECL)
1578           {
1579             if (DECL_CONSTRUCTOR_P (fn))
1580               print_tree_identifier
1581                 (scratch_buffer, TYPE_IDENTIFIER (TREE_TYPE (t)));
1582             else
1583               dump_decl (fn, 0);
1584           }
1585         else
1586           dump_expr (TREE_OPERAND (t, 0), 0);
1587       }
1588       print_left_paren (scratch_buffer);
1589       if (TREE_OPERAND (t, 1))
1590         dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1591       print_right_paren (scratch_buffer);
1592       break;
1593
1594     case CALL_EXPR:
1595       {
1596         tree fn = TREE_OPERAND (t, 0);
1597         tree args = TREE_OPERAND (t, 1);
1598
1599         if (TREE_CODE (fn) == ADDR_EXPR)
1600           fn = TREE_OPERAND (fn, 0);
1601
1602         if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
1603           {
1604             tree ob = TREE_VALUE (args);
1605             if (TREE_CODE (ob) == ADDR_EXPR)
1606               {
1607                 dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1608                 output_add_character (scratch_buffer, '.');
1609               }
1610             else if (TREE_CODE (ob) != PARM_DECL
1611                      || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1612               {
1613                 dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1614                 output_add_string (scratch_buffer, "->");
1615               }
1616             args = TREE_CHAIN (args);
1617           }
1618         dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
1619         print_left_paren (scratch_buffer);
1620         dump_expr_list (args, flags);
1621         print_right_paren (scratch_buffer);
1622       }
1623       break;
1624
1625     case NEW_EXPR:
1626       {
1627         tree type = TREE_OPERAND (t, 1);
1628         if (NEW_EXPR_USE_GLOBAL (t))
1629           print_scope_operator (scratch_buffer);
1630         output_add_string (scratch_buffer, "new ");
1631         if (TREE_OPERAND (t, 0))
1632           {
1633             print_left_paren (scratch_buffer);
1634             dump_expr_list (TREE_OPERAND (t, 0), flags);
1635             output_add_string (scratch_buffer, ") ");
1636           }
1637         if (TREE_CODE (type) == ARRAY_REF)
1638           type = build_cplus_array_type
1639             (TREE_OPERAND (type, 0),
1640              build_index_type (fold (build (MINUS_EXPR, integer_type_node,
1641                                             TREE_OPERAND (type, 1),
1642                                             integer_one_node))));
1643         dump_type (type, flags);
1644         if (TREE_OPERAND (t, 2))
1645           {
1646             print_left_paren (scratch_buffer);
1647             dump_expr_list (TREE_OPERAND (t, 2), flags);
1648             print_right_paren (scratch_buffer);
1649           }
1650       }
1651       break;
1652
1653     case TARGET_EXPR:
1654       /* Note that this only works for G++ target exprs.  If somebody
1655          builds a general TARGET_EXPR, there's no way to represent that
1656          it initializes anything other that the parameter slot for the
1657          default argument.  Note we may have cleared out the first
1658          operand in expand_expr, so don't go killing ourselves.  */
1659       if (TREE_OPERAND (t, 1))
1660         dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1661       break;
1662
1663     case INIT_EXPR:
1664     case MODIFY_EXPR:
1665     case PLUS_EXPR:
1666     case MINUS_EXPR:
1667     case MULT_EXPR:
1668     case TRUNC_DIV_EXPR:
1669     case TRUNC_MOD_EXPR:
1670     case MIN_EXPR:
1671     case MAX_EXPR:
1672     case LSHIFT_EXPR:
1673     case RSHIFT_EXPR:
1674     case BIT_IOR_EXPR:
1675     case BIT_XOR_EXPR:
1676     case BIT_AND_EXPR:
1677     case BIT_ANDTC_EXPR:
1678     case TRUTH_ANDIF_EXPR:
1679     case TRUTH_ORIF_EXPR:
1680     case LT_EXPR:
1681     case LE_EXPR:
1682     case GT_EXPR:
1683     case GE_EXPR:
1684     case EQ_EXPR:
1685     case NE_EXPR:
1686     case EXACT_DIV_EXPR:
1687       dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
1688       break;
1689
1690     case CEIL_DIV_EXPR:
1691     case FLOOR_DIV_EXPR:
1692     case ROUND_DIV_EXPR:
1693       dump_binary_op ("/", t, flags);
1694       break;
1695
1696     case CEIL_MOD_EXPR:
1697     case FLOOR_MOD_EXPR:
1698     case ROUND_MOD_EXPR:
1699       dump_binary_op ("%", t, flags);
1700       break;
1701
1702     case COMPONENT_REF:
1703       {
1704         tree ob = TREE_OPERAND (t, 0);
1705         if (TREE_CODE (ob) == INDIRECT_REF)
1706           {
1707             ob = TREE_OPERAND (ob, 0);
1708             if (TREE_CODE (ob) != PARM_DECL
1709                 || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1710               {
1711                 dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1712                 output_add_string (scratch_buffer, "->");
1713               }
1714           }
1715         else
1716           {
1717             dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1718             output_add_character (scratch_buffer, '.');
1719           }
1720         dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
1721       }
1722       break;
1723
1724     case ARRAY_REF:
1725       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1726       print_left_bracket (scratch_buffer);
1727       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1728       print_right_bracket (scratch_buffer);
1729       break;
1730
1731     case CONVERT_EXPR:
1732       if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
1733         {
1734           print_left_paren (scratch_buffer);
1735           dump_type (TREE_TYPE (t), flags);
1736           print_right_paren (scratch_buffer);
1737           dump_expr (TREE_OPERAND (t, 0), flags);
1738         }
1739       else
1740         dump_unary_op ("+", t, flags);
1741       break;
1742
1743     case ADDR_EXPR:
1744       if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
1745           || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
1746           /* An ADDR_EXPR can have reference type.  In that case, we
1747              shouldn't print the `&' doing so indicates to the user
1748              that the expression has pointer type.  */
1749           || (TREE_TYPE (t)
1750               && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
1751         dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1752       else
1753         dump_unary_op ("&", t, flags);
1754       break;
1755
1756     case INDIRECT_REF:
1757       if (TREE_HAS_CONSTRUCTOR (t))
1758         {
1759           t = TREE_OPERAND (t, 0);
1760           my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
1761           dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1762           print_left_paren (scratch_buffer);
1763           dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1764           print_right_paren (scratch_buffer);
1765         }
1766       else
1767         {
1768           if (TREE_OPERAND (t,0) != NULL_TREE
1769               && TREE_TYPE (TREE_OPERAND (t, 0))
1770               && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
1771             dump_expr (TREE_OPERAND (t, 0), flags);
1772           else
1773             dump_unary_op ("*", t, flags);
1774         }
1775       break;
1776
1777     case NEGATE_EXPR:
1778     case BIT_NOT_EXPR:
1779     case TRUTH_NOT_EXPR:
1780     case PREDECREMENT_EXPR:
1781     case PREINCREMENT_EXPR:
1782       dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
1783       break;
1784
1785     case POSTDECREMENT_EXPR:
1786     case POSTINCREMENT_EXPR:
1787       print_left_paren (scratch_buffer);
1788       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1789       print_identifier
1790         (scratch_buffer, operator_name_info[(int)TREE_CODE (t)].name);
1791       print_right_paren (scratch_buffer);
1792       break;
1793
1794     case NON_LVALUE_EXPR:
1795       /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
1796          should be another level of INDIRECT_REF so that I don't have to do
1797          this.  */
1798       if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
1799         {
1800           tree next = TREE_TYPE (TREE_TYPE (t));
1801
1802           while (TREE_CODE (next) == POINTER_TYPE)
1803             next = TREE_TYPE (next);
1804
1805           if (TREE_CODE (next) == FUNCTION_TYPE)
1806             {
1807               if (flags & TFF_EXPR_IN_PARENS)
1808                 print_left_paren (scratch_buffer);
1809               output_add_character (scratch_buffer, '*');
1810               dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1811               if (flags & TFF_EXPR_IN_PARENS)
1812                 print_right_paren (scratch_buffer);
1813               break;
1814             }
1815           /* else FALLTHRU */
1816         }
1817       dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1818       break;
1819
1820     case NOP_EXPR:
1821       dump_expr (TREE_OPERAND (t, 0), flags);
1822       break;
1823
1824     case EXPR_WITH_FILE_LOCATION:
1825       dump_expr (EXPR_WFL_NODE (t), flags);
1826       break;
1827
1828     case CONSTRUCTOR:
1829       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
1830         {
1831           tree idx = build_component_ref (t, pfn_identifier, NULL_TREE, 0);
1832
1833           if (integer_zerop (idx))
1834             {
1835               /* A NULL pointer-to-member constant.  */
1836               output_add_string (scratch_buffer, "((");
1837               dump_type (TREE_TYPE (t), flags);
1838               output_add_string (scratch_buffer, ") 0)");
1839               break;
1840             }
1841           else if (host_integerp (idx, 0))
1842             {
1843               tree virtuals;
1844               unsigned HOST_WIDE_INT n;
1845
1846               t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
1847               t = TYPE_METHOD_BASETYPE (t);
1848               virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
1849
1850               n = tree_low_cst (idx, 0);
1851
1852               /* Map vtable index back one, to allow for the null pointer to
1853                  member.  */
1854               --n;
1855
1856               while (n > 0 && virtuals)
1857                 {
1858                   --n;
1859                   virtuals = TREE_CHAIN (virtuals);
1860                 }
1861               if (virtuals)
1862                 {
1863                   dump_expr (BV_FN (virtuals),
1864                              flags | TFF_EXPR_IN_PARENS);
1865                   break;
1866                 }
1867             }
1868         }
1869       output_add_character (scratch_buffer, '{');
1870       dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
1871       output_add_character (scratch_buffer, '}');
1872       break;
1873
1874     case OFFSET_REF:
1875       {
1876         tree ob = TREE_OPERAND (t, 0);
1877         if (is_dummy_object (ob))
1878           {
1879             t = TREE_OPERAND (t, 1);
1880             if (TREE_CODE (t) == FUNCTION_DECL)
1881               /* A::f */
1882               dump_expr (t, flags | TFF_EXPR_IN_PARENS);
1883             else if (BASELINK_P (t))
1884               dump_expr (OVL_CURRENT (TREE_VALUE (t)), flags | TFF_EXPR_IN_PARENS);
1885             else
1886               dump_decl (t, flags);
1887           }
1888         else
1889           {
1890             if (TREE_CODE (ob) == INDIRECT_REF)
1891               {
1892                 dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1893                 output_add_string (scratch_buffer, "->*");
1894               }
1895             else
1896               {
1897                 dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1898                 output_add_string (scratch_buffer, ".*");
1899               }
1900             dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1901           }
1902         break;
1903       }
1904
1905     case TEMPLATE_PARM_INDEX:
1906       dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
1907       break;
1908
1909     case IDENTIFIER_NODE:
1910       print_tree_identifier (scratch_buffer, t);
1911       break;
1912
1913     case SCOPE_REF:
1914       dump_type (TREE_OPERAND (t, 0), flags);
1915       print_scope_operator (scratch_buffer);
1916       dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1917       break;
1918
1919     case CAST_EXPR:
1920       if (TREE_OPERAND (t, 0) == NULL_TREE
1921           || TREE_CHAIN (TREE_OPERAND (t, 0)))
1922         {
1923           dump_type (TREE_TYPE (t), flags);
1924           print_left_paren (scratch_buffer);
1925           dump_expr_list (TREE_OPERAND (t, 0), flags);
1926           print_right_paren (scratch_buffer);
1927         }
1928       else
1929         {
1930           print_left_paren (scratch_buffer);
1931           dump_type (TREE_TYPE (t), flags);
1932           output_add_string (scratch_buffer, ")(");
1933           dump_expr_list (TREE_OPERAND (t, 0), flags);
1934           print_right_paren (scratch_buffer);
1935         }
1936       break;
1937
1938     case STATIC_CAST_EXPR:
1939       output_add_string (scratch_buffer, "static_cast<");
1940       goto cast;
1941     case REINTERPRET_CAST_EXPR:
1942       output_add_string (scratch_buffer, "reinterpret_cast<");
1943       goto cast;
1944     case CONST_CAST_EXPR:
1945       output_add_string (scratch_buffer, "const_cast<");
1946       goto cast;
1947     case DYNAMIC_CAST_EXPR:
1948       output_add_string (scratch_buffer, "dynamic_cast<");
1949     cast:
1950       dump_type (TREE_TYPE (t), flags);
1951       output_add_string (scratch_buffer, ">(");
1952       dump_expr (TREE_OPERAND (t, 0), flags);
1953       print_right_paren (scratch_buffer);
1954       break;
1955
1956     case LOOKUP_EXPR:
1957       print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0));
1958       break;
1959
1960     case ARROW_EXPR:
1961       dump_expr (TREE_OPERAND (t, 0), flags);
1962       output_add_string (scratch_buffer, "->");
1963       break;
1964
1965     case SIZEOF_EXPR:
1966     case ALIGNOF_EXPR:
1967       if (TREE_CODE (t) == SIZEOF_EXPR)
1968         output_add_string (scratch_buffer, "sizeof (");
1969       else
1970         {
1971           my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0);
1972           output_add_string (scratch_buffer, "__alignof__ (");
1973         }
1974       if (TYPE_P (TREE_OPERAND (t, 0)))
1975         dump_type (TREE_OPERAND (t, 0), flags);
1976       else
1977         dump_unary_op ("*", t, flags | TFF_EXPR_IN_PARENS);
1978       print_right_paren (scratch_buffer);
1979       break;
1980
1981     case DEFAULT_ARG:
1982       print_identifier (scratch_buffer, "<unparsed>");
1983       break;
1984
1985     case TRY_CATCH_EXPR:
1986     case WITH_CLEANUP_EXPR:
1987     case CLEANUP_POINT_EXPR:
1988       dump_expr (TREE_OPERAND (t, 0), flags);
1989       break;
1990
1991     case PSEUDO_DTOR_EXPR:
1992       dump_expr (TREE_OPERAND (t, 2), flags);
1993       output_add_character (scratch_buffer, '.');
1994       dump_type (TREE_OPERAND (t, 0), flags);
1995       output_add_string (scratch_buffer, "::~");
1996       dump_type (TREE_OPERAND (t, 1), flags);
1997       break;
1998
1999     case TEMPLATE_ID_EXPR:
2000       dump_decl (t, flags);
2001       break;
2002
2003     case STMT_EXPR:
2004       /* We don't yet have a way of dumping statements in a
2005          human-readable format.  */
2006       output_add_string (scratch_buffer, "({...})");
2007       break;
2008
2009     case BIND_EXPR:
2010       output_add_character (scratch_buffer, '{');
2011       dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
2012       output_add_character (scratch_buffer, '}');
2013       break;
2014
2015     case LOOP_EXPR:
2016       output_add_string (scratch_buffer, "while (1) { ");
2017       dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2018       output_add_character (scratch_buffer, '}');
2019       break;
2020
2021     case EXIT_EXPR:
2022       output_add_string (scratch_buffer, "if (");
2023       dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2024       output_add_string (scratch_buffer, ") break; ");
2025       break;
2026
2027     case TREE_LIST:
2028       if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
2029         {
2030           print_tree_identifier (scratch_buffer, DECL_NAME (TREE_VALUE (t)));
2031           break;
2032         }
2033       /* else fall through */
2034
2035       /*  This list is incomplete, but should suffice for now.
2036           It is very important that `sorry' does not call
2037           `report_error_function'.  That could cause an infinite loop.  */
2038     default:
2039       sorry_for_unsupported_tree (t);
2040       /* fall through to ERROR_MARK...  */
2041     case ERROR_MARK:
2042       print_identifier (scratch_buffer, "<expression error>");
2043       break;
2044     }
2045 }
2046
2047 static void
2048 dump_binary_op (opstring, t, flags)
2049      const char *opstring;
2050      tree t;
2051      int flags;
2052 {
2053   print_left_paren (scratch_buffer);
2054   dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
2055   output_add_space (scratch_buffer);
2056   if (opstring)
2057     print_identifier (scratch_buffer, opstring);
2058   else
2059     print_identifier (scratch_buffer, "<unknown operator>");
2060   output_add_space (scratch_buffer);
2061   dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
2062   print_right_paren (scratch_buffer);
2063 }
2064
2065 static void
2066 dump_unary_op (opstring, t, flags)
2067      const char *opstring;
2068      tree t;
2069      int flags;
2070 {
2071   if (flags & TFF_EXPR_IN_PARENS)
2072     print_left_paren (scratch_buffer);
2073   print_identifier (scratch_buffer, opstring);
2074   dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2075   if (flags & TFF_EXPR_IN_PARENS)
2076     print_right_paren (scratch_buffer);
2077 }
2078
2079 /* Exported interface to stringifying types, exprs and decls under TFF_*
2080    control.  */
2081
2082 const char *
2083 type_as_string (typ, flags)
2084      tree typ;
2085      int flags;
2086 {
2087   reinit_global_formatting_buffer ();
2088
2089   dump_type (typ, flags);
2090
2091   return output_finalize_message (scratch_buffer);
2092 }
2093
2094 const char *
2095 expr_as_string (decl, flags)
2096      tree decl;
2097      int flags;
2098 {
2099   reinit_global_formatting_buffer ();
2100
2101   dump_expr (decl, flags);
2102
2103   return output_finalize_message (scratch_buffer);
2104 }
2105
2106 const char *
2107 decl_as_string (decl, flags)
2108      tree decl;
2109      int flags;
2110 {
2111   reinit_global_formatting_buffer ();
2112
2113   dump_decl (decl, flags);
2114
2115   return output_finalize_message (scratch_buffer);
2116 }
2117
2118 const char *
2119 context_as_string (context, flags)
2120      tree context;
2121      int flags;
2122 {
2123   reinit_global_formatting_buffer ();
2124
2125   dump_scope (context, flags);
2126
2127   return output_finalize_message (scratch_buffer);
2128 }
2129
2130 /* Generate the three forms of printable names for cxx_printable_name.  */
2131
2132 const char *
2133 lang_decl_name (decl, v)
2134      tree decl;
2135      int v;
2136 {
2137   if (v >= 2)
2138     return decl_as_string (decl, TFF_DECL_SPECIFIERS);
2139
2140   reinit_global_formatting_buffer ();
2141
2142   if (v == 1 && DECL_CLASS_SCOPE_P (decl))
2143     {
2144       dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
2145       print_scope_operator (scratch_buffer);
2146     }
2147
2148   if (TREE_CODE (decl) == FUNCTION_DECL)
2149     dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
2150   else
2151     dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
2152
2153   return output_finalize_message (scratch_buffer);
2154 }
2155
2156 const char *
2157 cp_file_of (t)
2158      tree t;
2159 {
2160   if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2161     return DECL_SOURCE_FILE (DECL_CONTEXT (t));
2162   else if (TYPE_P (t))
2163     return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
2164   else if (TREE_CODE (t) == OVERLOAD)
2165     return DECL_SOURCE_FILE (OVL_FUNCTION (t));
2166   else
2167     return DECL_SOURCE_FILE (t);
2168 }
2169
2170 int
2171 cp_line_of (t)
2172      tree t;
2173 {
2174   int line = 0;
2175   if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2176     line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
2177   if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
2178       && TYPE_MAIN_DECL (TREE_TYPE (t)))
2179     t = TREE_TYPE (t);
2180
2181   if (TYPE_P (t))
2182     line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
2183   else if (TREE_CODE (t) == OVERLOAD)
2184     line = DECL_SOURCE_LINE (OVL_FUNCTION (t));
2185   else
2186     line = DECL_SOURCE_LINE (t);
2187
2188   if (line == 0)
2189     return lineno;
2190
2191   return line;
2192 }
2193
2194 /* Now the interfaces from error et al to dump_type et al. Each takes an
2195    on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
2196    function.  */
2197
2198 static const char *
2199 decl_to_string (decl, verbose)
2200      tree decl;
2201      int verbose;
2202 {
2203   int flags = 0;
2204
2205   if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
2206       || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
2207     flags = TFF_CLASS_KEY_OR_ENUM;
2208   if (verbose)
2209     flags |= TFF_DECL_SPECIFIERS | TFF_FUNCTION_DEFAULT_ARGUMENTS;
2210   else if (TREE_CODE (decl) == FUNCTION_DECL)
2211     flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
2212   flags |= TFF_TEMPLATE_HEADER;
2213
2214   reinit_global_formatting_buffer ();
2215
2216   dump_decl (decl, flags);
2217
2218   return output_finalize_message (scratch_buffer);
2219 }
2220
2221 static const char *
2222 expr_to_string (decl, verbose)
2223      tree decl;
2224      int verbose ATTRIBUTE_UNUSED;
2225 {
2226   reinit_global_formatting_buffer ();
2227
2228   dump_expr (decl, 0);
2229
2230   return output_finalize_message (scratch_buffer);
2231 }
2232
2233 static const char *
2234 fndecl_to_string (fndecl, verbose)
2235      tree fndecl;
2236      int verbose;
2237 {
2238   int flags;
2239
2240   flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
2241   if (verbose)
2242     flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
2243   reinit_global_formatting_buffer ();
2244
2245   dump_decl (fndecl, flags);
2246
2247   return output_finalize_message (scratch_buffer);
2248 }
2249
2250
2251 static const char *
2252 code_to_string (c, v)
2253      enum tree_code c;
2254      int v ATTRIBUTE_UNUSED;
2255 {
2256   return tree_code_name [c];
2257 }
2258
2259 const char *
2260 language_to_string (c, v)
2261      enum languages c;
2262      int v ATTRIBUTE_UNUSED;
2263 {
2264   switch (c)
2265     {
2266     case lang_c:
2267       return "C";
2268
2269     case lang_cplusplus:
2270       return "C++";
2271
2272     case lang_java:
2273       return "Java";
2274
2275     default:
2276       abort ();
2277       return 0;
2278     }
2279 }
2280
2281 /* Return the proper printed version of a parameter to a C++ function.  */
2282
2283 static const char *
2284 parm_to_string (p, v)
2285      int p;
2286      int v ATTRIBUTE_UNUSED;
2287 {
2288   if (p < 0)
2289     return "`this'";
2290
2291   sprintf (digit_buffer, "%d", p+1);
2292   return digit_buffer;
2293 }
2294
2295 static const char *
2296 op_to_string (p, v)
2297      enum tree_code p;
2298      int v ATTRIBUTE_UNUSED;
2299 {
2300   tree id;
2301
2302   id = operator_name_info[(int) p].identifier;
2303   return id ? IDENTIFIER_POINTER (id) : "{unknown}";
2304 }
2305
2306 static const char *
2307 type_to_string (typ, verbose)
2308      tree typ;
2309      int verbose;
2310 {
2311   int flags;
2312
2313   flags = 0;
2314   if (verbose)
2315     flags |= TFF_CLASS_KEY_OR_ENUM;
2316   flags |= TFF_TEMPLATE_HEADER;
2317
2318   reinit_global_formatting_buffer ();
2319
2320   dump_type (typ, flags);
2321
2322   return output_finalize_message (scratch_buffer);
2323 }
2324
2325 static const char *
2326 assop_to_string (p, v)
2327      enum tree_code p;
2328      int v ATTRIBUTE_UNUSED;
2329 {
2330   tree id;
2331
2332   id = assignment_operator_name_info[(int) p].identifier;
2333   return id ? IDENTIFIER_POINTER (id) : "{unknown}";
2334 }
2335
2336 static const char *
2337 args_to_string (p, verbose)
2338      tree p;
2339      int verbose;
2340 {
2341   int flags = 0;
2342   if (verbose)
2343     flags |= TFF_CLASS_KEY_OR_ENUM;
2344
2345   if (p == NULL_TREE)
2346     return "";
2347
2348   if (TYPE_P (TREE_VALUE (p)))
2349     return type_as_string (p, flags);
2350
2351   reinit_global_formatting_buffer ();
2352   for (; p; p = TREE_CHAIN (p))
2353     {
2354       if (TREE_VALUE (p) == null_node)
2355         print_identifier (scratch_buffer, "NULL");
2356       else
2357         dump_type (error_type (TREE_VALUE (p)), flags);
2358       if (TREE_CHAIN (p))
2359         separate_with_comma (scratch_buffer);
2360     }
2361   return output_finalize_message (scratch_buffer);
2362 }
2363
2364 static const char *
2365 cv_to_string (p, v)
2366      tree p;
2367      int v;
2368 {
2369   reinit_global_formatting_buffer ();
2370
2371   dump_qualifiers (p, v ? before : none);
2372
2373   return output_finalize_message (scratch_buffer);
2374 }
2375
2376 /* Langhook for print_error_function.  */
2377 void
2378 cxx_print_error_function (context, file)
2379      diagnostic_context *context;
2380      const char *file;
2381 {
2382   output_state os;
2383
2384   lhd_print_error_function (context, file);
2385   os = diagnostic_state (context);
2386   output_set_prefix ((output_buffer *)context, file);
2387   maybe_print_instantiation_context ((output_buffer *)context);
2388   diagnostic_state (context) = os;
2389 }
2390
2391 static void
2392 cp_diagnostic_starter (buffer, dc)
2393      output_buffer *buffer;
2394      diagnostic_context *dc;
2395 {
2396   report_problematic_module (buffer);
2397   cp_print_error_function (buffer, dc);
2398   maybe_print_instantiation_context (buffer);
2399   output_set_prefix (buffer,
2400                      context_as_prefix (diagnostic_file_location (dc),
2401                                         diagnostic_line_location (dc),
2402                                         diagnostic_is_warning (dc)));
2403 }
2404
2405 static void
2406 cp_diagnostic_finalizer (buffer, dc)
2407      output_buffer *buffer;
2408      diagnostic_context *dc __attribute__ ((__unused__));
2409 {
2410   output_destroy_prefix (buffer);
2411 }
2412
2413 /* Print current function onto BUFFER, in the process of reporting
2414    a diagnostic message.  Called from cp_diagnostic_starter.  */
2415 static void
2416 cp_print_error_function (buffer, dc)
2417      output_buffer *buffer;
2418      diagnostic_context *dc;
2419 {
2420   if (error_function_changed ())
2421     {
2422       char *prefix = diagnostic_file_location (dc)
2423         ? file_name_as_prefix (diagnostic_file_location (dc))
2424         : NULL;
2425       output_state os;
2426
2427       os = output_buffer_state (buffer);
2428       output_set_prefix (buffer, prefix);
2429
2430       if (current_function_decl == NULL)
2431         output_add_string (buffer, "At global scope:");
2432       else
2433         output_printf
2434           (buffer, "In %s `%s':", function_category (current_function_decl),
2435            cxx_printable_name (current_function_decl, 2));
2436       output_add_newline (buffer);
2437
2438       record_last_error_function ();
2439       output_destroy_prefix (buffer);
2440       output_buffer_state (buffer) = os;
2441     }
2442 }
2443
2444 /* Returns a description of FUNCTION using standard terminology.  */
2445 static const char *
2446 function_category (fn)
2447      tree fn;
2448 {
2449   if (DECL_FUNCTION_MEMBER_P (fn))
2450     {
2451       if (DECL_STATIC_FUNCTION_P (fn))
2452         return "static member function";
2453       else if (DECL_COPY_CONSTRUCTOR_P (fn))
2454         return "copy constructor";
2455       else if (DECL_CONSTRUCTOR_P (fn))
2456         return "constructor";
2457       else if (DECL_DESTRUCTOR_P (fn))
2458         return "destructor";
2459       else
2460         return "member function";
2461     }
2462   else
2463     return "function";
2464 }
2465
2466 /* Report the full context of a current template instantiation,
2467    onto BUFFER.  */
2468 static void
2469 print_instantiation_full_context (buffer)
2470      output_buffer *buffer;
2471 {
2472   tree p = current_instantiation ();
2473   int line = lineno;
2474   const char *file = input_filename;
2475
2476   if (p)
2477     {
2478       if (current_function_decl != TINST_DECL (p)
2479           && current_function_decl != NULL_TREE)
2480         /* We can get here during the processing of some synthesized
2481            method.  Then, TINST_DECL (p) will be the function that's causing
2482            the synthesis.  */
2483         ;
2484       else
2485         {
2486           if (current_function_decl == TINST_DECL (p))
2487             /* Avoid redundancy with the the "In function" line.  */;
2488           else
2489             output_verbatim (buffer, "%s: In instantiation of `%s':\n", file,
2490                              decl_as_string (TINST_DECL (p),
2491                                              TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2492
2493           line = TINST_LINE (p);
2494           file = TINST_FILE (p);
2495           p = TREE_CHAIN (p);
2496         }
2497     }
2498
2499   print_instantiation_partial_context (buffer, p, file, line);
2500 }
2501
2502 /* Same as above but less verbose.  */
2503 static void
2504 print_instantiation_partial_context (buffer, t, file, line)
2505      output_buffer *buffer;
2506      tree t;
2507      const char *file;
2508      int line;
2509 {
2510   for (; t; t = TREE_CHAIN (t))
2511     {
2512       output_verbatim
2513         (buffer, "%s:%d:   instantiated from `%s'\n", file, line,
2514          decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2515       line = TINST_LINE (t);
2516       file = TINST_FILE (t);
2517     }
2518   output_verbatim (buffer, "%s:%d:   instantiated from here\n", file, line);
2519 }
2520
2521 /* Called from cp_thing to print the template context for an error.  */
2522 static void
2523 maybe_print_instantiation_context (buffer)
2524      output_buffer *buffer;
2525 {
2526   if (!problematic_instantiation_changed () || current_instantiation () == 0)
2527     return;
2528
2529   record_last_problematic_instantiation ();
2530   print_instantiation_full_context (buffer);
2531 }
2532
2533 /* Report the bare minimum context of a template instantiation.  */
2534 void
2535 print_instantiation_context ()
2536 {
2537   print_instantiation_partial_context
2538     (diagnostic_buffer, current_instantiation (), input_filename, lineno);
2539   flush_diagnostic_buffer ();
2540 }
2541 \f
2542 /* Called from output_format -- during diagnostic message processing --
2543    to handle C++ specific format specifier with the following meanings:
2544    %A   function argument-list.
2545    %C   tree code.
2546    %D   declaration.
2547    %E   expression.
2548    %F   function declaration.
2549    %L   language as used in extern "lang".
2550    %O   binary operator.
2551    %P   function parameter whose position is indicated by an integer.
2552    %Q   assignment operator.
2553    %T   type.
2554    %V   cv-qualifier.  */
2555 static int
2556 cp_printer (buffer)
2557      output_buffer *buffer;
2558 {
2559   int verbose = 0;
2560   const char *result;
2561 #define next_tree    va_arg (output_buffer_format_args (buffer), tree)
2562 #define next_tcode   va_arg (output_buffer_format_args (buffer), enum tree_code)
2563 #define next_lang    va_arg (output_buffer_format_args (buffer), enum languages)
2564 #define next_int     va_arg (output_buffer_format_args (buffer), int)
2565
2566   if (*output_buffer_text_cursor (buffer) == '+')
2567     ++output_buffer_text_cursor (buffer);
2568   if (*output_buffer_text_cursor (buffer) == '#')
2569     {
2570       verbose = 1;
2571       ++output_buffer_text_cursor (buffer);
2572     }
2573
2574   switch (*output_buffer_text_cursor (buffer))
2575     {
2576     case 'A': result = args_to_string (next_tree, verbose);     break;
2577     case 'C': result = code_to_string (next_tcode, verbose);    break;
2578     case 'D': result = decl_to_string (next_tree, verbose);     break;
2579     case 'E': result = expr_to_string (next_tree, verbose);     break;
2580     case 'F': result = fndecl_to_string (next_tree, verbose);   break;
2581     case 'L': result = language_to_string (next_lang, verbose); break;
2582     case 'O': result = op_to_string (next_tcode, verbose);      break;
2583     case 'P': result = parm_to_string (next_int, verbose);      break;
2584     case 'Q': result = assop_to_string (next_tcode, verbose);   break;
2585     case 'T': result = type_to_string (next_tree, verbose);     break;
2586     case 'V': result = cv_to_string (next_tree, verbose);       break;
2587  
2588     default:
2589       return 0;
2590     }
2591
2592   output_add_string (buffer, result);
2593   return 1;
2594 #undef next_tree
2595 #undef next_tcode
2596 #undef next_lang
2597 #undef next_int
2598 }
2599
2600 static void
2601 print_integer (buffer, i)
2602      output_buffer *buffer;
2603      HOST_WIDE_INT i;
2604 {
2605   sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) i);
2606   output_add_string (buffer, digit_buffer);
2607 }
2608
2609 static void
2610 print_non_consecutive_character (buffer, c)
2611      output_buffer *buffer;
2612      int c;
2613 {
2614   const char *p = output_last_position (buffer);
2615
2616   if (p != NULL && *p == c)
2617     output_add_space (buffer);
2618   output_add_character (buffer, c);
2619 }
2620
2621 /* These are temporary wrapper functions which handle the historic
2622    behavior of cp_*_at.  */
2623
2624 static tree
2625 locate_error (msgid, ap)
2626      const char *msgid;
2627      va_list ap;
2628 {
2629   tree here = 0, t;
2630   int plus = 0;
2631   const char *f;
2632
2633   for (f = msgid; *f; f++)
2634     {
2635       plus = 0;
2636       if (*f == '%')
2637         {
2638           f++;
2639           if (*f == '+')
2640             f++, plus = 1;
2641           if (*f == '#')
2642             f++;
2643
2644           switch (*f)
2645             {
2646               /* Just ignore these possibilities.  */
2647             case '%':                                           break;
2648             case 'd':   (void) va_arg (ap, int);                break;
2649             case 's':   (void) va_arg (ap, char *);             break;
2650             case 'L':   (void) va_arg (ap, enum languages);     break;
2651             case 'C':
2652             case 'O':
2653             case 'Q':   (void) va_arg (ap, enum tree_code);     break;
2654
2655               /* These take a tree, which may be where the error is
2656                  located.  */
2657             case 'A':
2658             case 'D':
2659             case 'E':
2660             case 'F':
2661             case 'P':
2662             case 'T':
2663             case 'V':
2664               t = va_arg (ap, tree);
2665               if (!here || plus)
2666                 here = t;
2667               break;
2668
2669             default:
2670               errorcount = 0;  /* damn ICE suppression */
2671               internal_error ("unexpected letter `%c' in locate_error\n", *f);
2672             }
2673         }
2674     }
2675
2676   if (here == 0)
2677     here = va_arg (ap, tree);
2678
2679   return here;
2680 }
2681
2682
2683 void
2684 cp_error_at VPARAMS ((const char *msgid, ...))
2685 {
2686   tree here;
2687   diagnostic_context dc;
2688
2689   VA_OPEN (ap, msgid);
2690   VA_FIXEDARG (ap, const char *, msgid);
2691   here = locate_error (msgid, ap);
2692   VA_CLOSE (ap);
2693
2694   VA_OPEN (ap, msgid);
2695   VA_FIXEDARG (ap, const char *, msgid);
2696
2697   set_diagnostic_context (&dc, msgid, &ap,
2698                           cp_file_of (here),
2699                           cp_line_of (here), /* warning = */ 0);
2700   report_diagnostic (&dc);
2701   VA_CLOSE (ap);
2702 }
2703
2704 void
2705 cp_warning_at VPARAMS ((const char *msgid, ...))
2706 {
2707   tree here;
2708   diagnostic_context dc;
2709
2710   VA_OPEN (ap, msgid);
2711   VA_FIXEDARG (ap, const char *, msgid);
2712   here = locate_error (msgid, ap);
2713   VA_CLOSE (ap);
2714
2715   VA_OPEN (ap, msgid);
2716   VA_FIXEDARG (ap, const char *, msgid);
2717
2718   set_diagnostic_context (&dc, msgid, &ap,
2719                           cp_file_of (here),
2720                           cp_line_of (here), /* warning = */ 1);
2721   report_diagnostic (&dc);
2722   VA_CLOSE (ap);
2723 }
2724
2725 void
2726 cp_pedwarn_at VPARAMS ((const char *msgid, ...))
2727 {
2728   tree here;
2729   diagnostic_context dc;
2730
2731   VA_OPEN (ap, msgid);
2732   VA_FIXEDARG (ap, const char *, msgid);
2733   here = locate_error (msgid, ap);
2734   VA_CLOSE (ap);
2735
2736   VA_OPEN (ap, msgid);
2737   VA_FIXEDARG (ap, const char *, msgid);
2738
2739   set_diagnostic_context (&dc, msgid, &ap,
2740                           cp_file_of (here),
2741                           cp_line_of (here),
2742                           /* warning = */ !flag_pedantic_errors);
2743   report_diagnostic (&dc);
2744   VA_CLOSE (ap);
2745 }