OSDN Git Service

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