OSDN Git Service

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