error.c revision 117395
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
7GNU CC is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2, or (at your option)
10any later version.
11
12GNU CC is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU CC; see the file COPYING.  If not, write to
19the Free Software Foundation, 59 Temple Place - Suite 330,
20Boston, 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
32enum 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.  */
55static output_buffer scratch_buffer_rec;
56static 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
63static const char *args_to_string		PARAMS ((tree, int));
64static const char *assop_to_string		PARAMS ((enum tree_code, int));
65static const char *code_to_string		PARAMS ((enum tree_code, int));
66static const char *cv_to_string			PARAMS ((tree, int));
67static const char *decl_to_string		PARAMS ((tree, int));
68static const char *expr_to_string		PARAMS ((tree, int));
69static const char *fndecl_to_string		PARAMS ((tree, int));
70static const char *op_to_string			PARAMS ((enum tree_code, int));
71static const char *parm_to_string		PARAMS ((int, int));
72static const char *type_to_string		PARAMS ((tree, int));
73
74static void dump_type PARAMS ((tree, int));
75static void dump_typename PARAMS ((tree, int));
76static void dump_simple_decl PARAMS ((tree, tree, int));
77static void dump_decl PARAMS ((tree, int));
78static void dump_template_decl PARAMS ((tree, int));
79static void dump_function_decl PARAMS ((tree, int));
80static void dump_expr PARAMS ((tree, int));
81static void dump_unary_op PARAMS ((const char *, tree, int));
82static void dump_binary_op PARAMS ((const char *, tree, int));
83static void dump_aggr_type PARAMS ((tree, int));
84static enum pad dump_type_prefix PARAMS ((tree, int));
85static void dump_type_suffix PARAMS ((tree, int));
86static void dump_function_name PARAMS ((tree, int));
87static void dump_expr_list PARAMS ((tree, int));
88static void dump_global_iord PARAMS ((tree));
89static enum pad dump_qualifiers PARAMS ((tree, enum pad));
90static void dump_char PARAMS ((int));
91static void dump_parameters PARAMS ((tree, int));
92static void dump_exception_spec PARAMS ((tree, int));
93static const char *class_key_or_enum PARAMS ((tree));
94static void dump_template_argument PARAMS ((tree, int));
95static void dump_template_argument_list PARAMS ((tree, int));
96static void dump_template_parameter PARAMS ((tree, int));
97static void dump_template_bindings PARAMS ((tree, tree));
98static void dump_scope PARAMS ((tree, int));
99static void dump_template_parms PARAMS ((tree, int, int));
100
101static const char *function_category PARAMS ((tree));
102static void maybe_print_instantiation_context PARAMS ((diagnostic_context *));
103static void print_instantiation_full_context PARAMS ((diagnostic_context *));
104static void print_instantiation_partial_context PARAMS ((diagnostic_context *,
105                                                         tree,
106                                                         const char *, int));
107static void cp_diagnostic_starter PARAMS ((diagnostic_context *,
108                                           diagnostic_info *));
109static void cp_diagnostic_finalizer PARAMS ((diagnostic_context *,
110                                             diagnostic_info *));
111static void cp_print_error_function PARAMS ((diagnostic_context *,
112                                             diagnostic_info *));
113
114static bool cp_printer PARAMS ((output_buffer *, text_info *));
115static void print_non_consecutive_character PARAMS ((output_buffer *, int));
116static void print_integer PARAMS ((output_buffer *, HOST_WIDE_INT));
117static tree locate_error PARAMS ((const char *, va_list));
118
119void
120init_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
131static void
132dump_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
164static enum pad
165dump_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.  */
197static char digit_buffer[128];
198
199/* Dump the template ARGument under control of FLAGS.  */
200
201static void
202dump_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
215static void
216dump_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
235static void
236dump_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
276static void
277dump_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
321static void
322dump_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
486static void
487dump_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
503static const char *
504class_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
520static void
521dump_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
595static enum pad
596dump_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    case TYPEOF_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
706static void
707dump_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    case TYPEOF_TYPE:
786      break;
787
788    default:
789      sorry_for_unsupported_tree (t);
790    case ERROR_MARK:
791      /* Don't mark it here, we should have already done in
792         dump_type_prefix.  */
793      break;
794    }
795}
796
797static void
798dump_global_iord (t)
799     tree t;
800{
801  const char *p = NULL;
802
803  if (DECL_GLOBAL_CTOR_P (t))
804    p = "initializers";
805  else if (DECL_GLOBAL_DTOR_P (t))
806    p = "destructors";
807  else
808    abort ();
809
810  output_printf (scratch_buffer, "(static %s for %s)", p, input_filename);
811}
812
813static void
814dump_simple_decl (t, type, flags)
815     tree t;
816     tree type;
817     int flags;
818{
819  if (flags & TFF_DECL_SPECIFIERS)
820    {
821      if (dump_type_prefix (type, flags) != none)
822        output_add_space (scratch_buffer);
823    }
824  if (!DECL_INITIAL (t) || TREE_CODE (DECL_INITIAL (t)) != TEMPLATE_PARM_INDEX)
825    dump_scope (CP_DECL_CONTEXT (t), flags);
826  if (DECL_NAME (t))
827    dump_decl (DECL_NAME (t), flags);
828  else
829    print_identifier (scratch_buffer, "<anonymous>");
830  if (flags & TFF_DECL_SPECIFIERS)
831    dump_type_suffix (type, flags);
832}
833
834/* Dump a human readable string for the decl T under control of FLAGS.  */
835
836static void
837dump_decl (t, flags)
838     tree t;
839     int flags;
840{
841  if (t == NULL_TREE)
842    return;
843
844  switch (TREE_CODE (t))
845    {
846    case TYPE_DECL:
847      {
848	/* Don't say 'typedef class A' */
849        if (DECL_ARTIFICIAL (t))
850	  {
851	    if ((flags & TFF_DECL_SPECIFIERS)
852	        && TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
853	      /* Say `class T' not just `T'.  */
854	      output_add_string (scratch_buffer, "class ");
855
856	    dump_type (TREE_TYPE (t), flags);
857	    break;
858	  }
859      }
860      if (flags & TFF_DECL_SPECIFIERS)
861	output_add_string (scratch_buffer, "typedef ");
862      dump_simple_decl (t, DECL_ORIGINAL_TYPE (t)
863			? DECL_ORIGINAL_TYPE (t) : TREE_TYPE (t),
864	                flags);
865      break;
866
867    case VAR_DECL:
868      if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
869	{
870	  output_add_string (scratch_buffer, "vtable for ");
871	  my_friendly_assert (TYPE_P (DECL_CONTEXT (t)), 20010720);
872	  dump_type (DECL_CONTEXT (t), flags);
873	  break;
874	}
875      /* else fall through */
876    case FIELD_DECL:
877    case PARM_DECL:
878      dump_simple_decl (t, TREE_TYPE (t), flags);
879      break;
880
881    case RESULT_DECL:
882      output_add_string (scratch_buffer, "<return value> ");
883      dump_simple_decl (t, TREE_TYPE (t), flags);
884      break;
885
886    case NAMESPACE_DECL:
887      dump_scope (CP_DECL_CONTEXT (t), flags);
888      if (DECL_NAME (t) == anonymous_namespace_name)
889	print_identifier (scratch_buffer, "<unnamed>");
890      else
891	print_tree_identifier (scratch_buffer, DECL_NAME (t));
892      break;
893
894    case SCOPE_REF:
895      dump_decl (TREE_OPERAND (t, 0), flags & ~TFF_DECL_SPECIFIERS);
896      print_scope_operator (scratch_buffer);
897      dump_decl (TREE_OPERAND (t, 1), flags);
898      break;
899
900    case ARRAY_REF:
901      dump_decl (TREE_OPERAND (t, 0), flags);
902      print_left_bracket (scratch_buffer);
903      dump_decl (TREE_OPERAND (t, 1), flags);
904      print_right_bracket (scratch_buffer);
905      break;
906
907      /* So that we can do dump_decl on an aggr type.  */
908    case RECORD_TYPE:
909    case UNION_TYPE:
910    case ENUMERAL_TYPE:
911      dump_type (t, flags);
912      break;
913
914    case TYPE_EXPR:
915      abort ();
916      break;
917
918      /* These special cases are duplicated here so that other functions
919	 can feed identifiers to error and get them demangled properly.  */
920    case IDENTIFIER_NODE:
921      if (IDENTIFIER_TYPENAME_P (t))
922	{
923	  output_add_string (scratch_buffer, "operator ");
924	  /* Not exactly IDENTIFIER_TYPE_VALUE.  */
925	  dump_type (TREE_TYPE (t), flags);
926	  break;
927	}
928      else
929	print_tree_identifier (scratch_buffer, t);
930      break;
931
932    case OVERLOAD:
933      if (OVL_CHAIN (t))
934	{
935	  t = OVL_CURRENT (t);
936	  if (DECL_CLASS_SCOPE_P (t))
937	    {
938	      dump_type (DECL_CONTEXT (t), flags);
939	      output_add_string (scratch_buffer, "::");
940	    }
941	  else if (DECL_CONTEXT (t))
942	    {
943	      dump_decl (DECL_CONTEXT (t), flags);
944	      output_add_string (scratch_buffer, "::");
945	    }
946	  dump_decl (DECL_NAME (t), flags);
947	  break;
948	}
949
950      /* If there's only one function, just treat it like an ordinary
951	 FUNCTION_DECL.  */
952      t = OVL_CURRENT (t);
953      /* Fall through.  */
954
955    case FUNCTION_DECL:
956      if (DECL_GLOBAL_CTOR_P (t) || DECL_GLOBAL_DTOR_P (t))
957	dump_global_iord (t);
958      else if (! DECL_LANG_SPECIFIC (t))
959	print_identifier (scratch_buffer, "<internal>");
960      else
961        dump_function_decl (t, flags);
962      break;
963
964    case TEMPLATE_DECL:
965      dump_template_decl (t, flags);
966      break;
967
968    case TEMPLATE_ID_EXPR:
969      {
970	tree args;
971	tree name = TREE_OPERAND (t, 0);
972	if (is_overloaded_fn (name))
973	  name = DECL_NAME (get_first_fn (name));
974	dump_decl (name, flags);
975	print_template_argument_list_start (scratch_buffer);
976	for (args = TREE_OPERAND (t, 1); args; args = TREE_CHAIN (args))
977	  {
978	    dump_template_argument (TREE_VALUE (args), flags);
979	    if (TREE_CHAIN (args))
980	      separate_with_comma (scratch_buffer);
981	  }
982	print_template_argument_list_end (scratch_buffer);
983      }
984      break;
985
986    case LOOKUP_EXPR:
987      dump_decl (TREE_OPERAND (t, 0), flags);
988      break;
989
990    case LABEL_DECL:
991      print_tree_identifier (scratch_buffer, DECL_NAME (t));
992      break;
993
994    case CONST_DECL:
995      if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
996	  || (DECL_INITIAL (t) &&
997	      TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_PARM_INDEX))
998	dump_simple_decl (t, TREE_TYPE (t), flags);
999      else if (DECL_NAME (t))
1000	dump_decl (DECL_NAME (t), flags);
1001      else if (DECL_INITIAL (t))
1002	dump_expr (DECL_INITIAL (t), flags | TFF_EXPR_IN_PARENS);
1003      else
1004	print_identifier (scratch_buffer, "enumerator");
1005      break;
1006
1007    case USING_DECL:
1008      output_add_string (scratch_buffer, "using ");
1009      dump_type (DECL_INITIAL (t), flags);
1010      print_scope_operator (scratch_buffer);
1011      dump_decl (DECL_NAME (t), flags);
1012      break;
1013
1014    case BASELINK:
1015      dump_decl (BASELINK_FUNCTIONS (t), flags);
1016      break;
1017
1018    default:
1019      sorry_for_unsupported_tree (t);
1020      /* Fallthrough to error.  */
1021
1022    case ERROR_MARK:
1023      print_identifier (scratch_buffer, "<declaration error>");
1024      break;
1025    }
1026}
1027
1028/* Dump a template declaration T under control of FLAGS. This means the
1029   'template <...> leaders plus the 'class X' or 'void fn(...)' part.  */
1030
1031static void
1032dump_template_decl (t, flags)
1033     tree t;
1034     int flags;
1035{
1036  tree orig_parms = DECL_TEMPLATE_PARMS (t);
1037  tree parms;
1038  int i;
1039
1040  if (flags & TFF_TEMPLATE_HEADER)
1041    {
1042      for (parms = orig_parms = nreverse (orig_parms);
1043           parms;
1044           parms = TREE_CHAIN (parms))
1045        {
1046	  tree inner_parms = INNERMOST_TEMPLATE_PARMS (parms);
1047          int len = TREE_VEC_LENGTH (inner_parms);
1048
1049          output_add_string (scratch_buffer, "template<");
1050
1051	  /* If we've shown the template prefix, we'd better show the
1052	     parameters' and decl's type too.  */
1053	    flags |= TFF_DECL_SPECIFIERS;
1054
1055          for (i = 0; i < len; i++)
1056            {
1057              if (i)
1058                separate_with_comma (scratch_buffer);
1059              dump_template_parameter (TREE_VEC_ELT (inner_parms, i), flags);
1060            }
1061          print_template_argument_list_end (scratch_buffer);
1062          output_add_space (scratch_buffer);
1063        }
1064      nreverse(orig_parms);
1065
1066      if (DECL_TEMPLATE_TEMPLATE_PARM_P (t))
1067	/* Say `template<arg> class TT' not just `template<arg> TT'.  */
1068	output_add_string (scratch_buffer, "class ");
1069    }
1070
1071  if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
1072    dump_type (TREE_TYPE (t),
1073               ((flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
1074                | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0)));
1075  else if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == VAR_DECL)
1076    dump_decl (DECL_TEMPLATE_RESULT (t), flags | TFF_TEMPLATE_NAME);
1077  else if (TREE_TYPE (t) == NULL_TREE)
1078    abort ();
1079  else
1080    switch (NEXT_CODE (t))
1081    {
1082      case METHOD_TYPE:
1083      case FUNCTION_TYPE:
1084        dump_function_decl (t, flags | TFF_TEMPLATE_NAME);
1085        break;
1086      default:
1087        /* This case can occur with some invalid code.  */
1088        dump_type (TREE_TYPE (t),
1089                   (flags & ~TFF_CLASS_KEY_OR_ENUM) | TFF_TEMPLATE_NAME
1090                   | (flags & TFF_DECL_SPECIFIERS ? TFF_CLASS_KEY_OR_ENUM : 0));
1091    }
1092}
1093
1094/* Pretty print a function decl. There are several ways we want to print a
1095   function declaration. The TFF_ bits in FLAGS tells us how to behave.
1096   As error can only apply the '#' flag once to give 0 and 1 for V, there
1097   is %D which doesn't print the throw specs, and %F which does.  */
1098
1099static void
1100dump_function_decl (t, flags)
1101     tree t;
1102     int flags;
1103{
1104  tree fntype;
1105  tree parmtypes;
1106  tree cname = NULL_TREE;
1107  tree template_args = NULL_TREE;
1108  tree template_parms = NULL_TREE;
1109  int show_return = flags & TFF_RETURN_TYPE || flags & TFF_DECL_SPECIFIERS;
1110
1111  if (TREE_CODE (t) == TEMPLATE_DECL)
1112    t = DECL_TEMPLATE_RESULT (t);
1113
1114  /* Pretty print template instantiations only.  */
1115  if (DECL_USE_TEMPLATE (t) && DECL_TEMPLATE_INFO (t))
1116    {
1117      tree tmpl;
1118
1119      template_args = DECL_TI_ARGS (t);
1120      tmpl = most_general_template (t);
1121      if (tmpl && TREE_CODE (tmpl) == TEMPLATE_DECL)
1122	{
1123	  template_parms = DECL_TEMPLATE_PARMS (tmpl);
1124	  t = tmpl;
1125	}
1126    }
1127
1128  fntype = TREE_TYPE (t);
1129  parmtypes = FUNCTION_FIRST_USER_PARMTYPE (t);
1130
1131  if (DECL_CLASS_SCOPE_P (t))
1132    cname = DECL_CONTEXT (t);
1133  /* this is for partially instantiated template methods */
1134  else if (TREE_CODE (fntype) == METHOD_TYPE)
1135    cname = TREE_TYPE (TREE_VALUE (parmtypes));
1136
1137  if (!(flags & TFF_DECL_SPECIFIERS))
1138    /* OK */;
1139  else if (DECL_STATIC_FUNCTION_P (t))
1140    print_identifier (scratch_buffer, "static ");
1141  else if (DECL_VIRTUAL_P (t))
1142    print_identifier (scratch_buffer, "virtual ");
1143
1144  /* Print the return type?  */
1145  if (show_return)
1146    show_return = !DECL_CONV_FN_P (t)  && !DECL_CONSTRUCTOR_P (t)
1147                  && !DECL_DESTRUCTOR_P (t);
1148  if (show_return)
1149    {
1150      dump_type_prefix (TREE_TYPE (fntype), flags);
1151      output_add_space (scratch_buffer);
1152    }
1153
1154  /* Print the function name.  */
1155  if (cname)
1156    {
1157      dump_type (cname, flags);
1158      print_scope_operator (scratch_buffer);
1159    }
1160  else
1161    dump_scope (CP_DECL_CONTEXT (t), flags);
1162
1163  dump_function_name (t, flags);
1164
1165  if (1)
1166    {
1167      dump_parameters (parmtypes, flags);
1168
1169      if (TREE_CODE (fntype) == METHOD_TYPE)
1170	dump_qualifiers (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))),
1171			 before);
1172
1173      if (flags & TFF_EXCEPTION_SPECIFICATION)
1174	dump_exception_spec (TYPE_RAISES_EXCEPTIONS (fntype), flags);
1175
1176      if (show_return)
1177	dump_type_suffix (TREE_TYPE (fntype), flags);
1178    }
1179
1180  /* If T is a template instantiation, dump the parameter binding.  */
1181  if (template_parms != NULL_TREE && template_args != NULL_TREE)
1182    {
1183      output_add_string (scratch_buffer, " [with ");
1184      dump_template_bindings (template_parms, template_args);
1185      print_right_bracket (scratch_buffer);
1186    }
1187}
1188
1189/* Print a parameter list. If this is for a member function, the
1190   member object ptr (and any other hidden args) should have
1191   already been removed.  */
1192
1193static void
1194dump_parameters (parmtypes, flags)
1195     tree parmtypes;
1196     int flags;
1197{
1198  int first;
1199
1200  print_left_paren (scratch_buffer);
1201
1202  for (first = 1; parmtypes != void_list_node;
1203       parmtypes = TREE_CHAIN (parmtypes))
1204    {
1205      if (!first)
1206        separate_with_comma (scratch_buffer);
1207      first = 0;
1208      if (!parmtypes)
1209        {
1210          print_identifier (scratch_buffer, "...");
1211          break;
1212        }
1213      dump_type (TREE_VALUE (parmtypes), flags);
1214
1215      if ((flags & TFF_FUNCTION_DEFAULT_ARGUMENTS) && TREE_PURPOSE (parmtypes))
1216        {
1217          output_add_string (scratch_buffer, " = ");
1218          dump_expr (TREE_PURPOSE (parmtypes), flags | TFF_EXPR_IN_PARENS);
1219        }
1220    }
1221
1222  print_right_paren (scratch_buffer);
1223}
1224
1225/* Print an exception specification. T is the exception specification.  */
1226
1227static void
1228dump_exception_spec (t, flags)
1229     tree t;
1230     int flags;
1231{
1232  if (t)
1233    {
1234      output_add_string (scratch_buffer, " throw (");
1235      if (TREE_VALUE (t) != NULL_TREE)
1236        while (1)
1237          {
1238            dump_type (TREE_VALUE (t), flags);
1239            t = TREE_CHAIN (t);
1240            if (!t)
1241              break;
1242            separate_with_comma (scratch_buffer);
1243          }
1244      print_right_paren (scratch_buffer);
1245    }
1246}
1247
1248/* Handle the function name for a FUNCTION_DECL node, grokking operators
1249   and destructors properly.  */
1250
1251static void
1252dump_function_name (t, flags)
1253     tree t;
1254     int flags;
1255{
1256  tree name = DECL_NAME (t);
1257
1258  if (TREE_CODE (t) == TEMPLATE_DECL)
1259    t = DECL_TEMPLATE_RESULT (t);
1260
1261  /* Don't let the user see __comp_ctor et al.  */
1262  if (DECL_CONSTRUCTOR_P (t)
1263      || DECL_DESTRUCTOR_P (t))
1264    name = constructor_name (DECL_CONTEXT (t));
1265
1266  if (DECL_DESTRUCTOR_P (t))
1267    {
1268      output_add_character (scratch_buffer, '~');
1269      dump_decl (name, TFF_PLAIN_IDENTIFIER);
1270    }
1271  else if (DECL_CONV_FN_P (t))
1272    {
1273      /* This cannot use the hack that the operator's return
1274	 type is stashed off of its name because it may be
1275	 used for error reporting.  In the case of conflicting
1276	 declarations, both will have the same name, yet
1277	 the types will be different, hence the TREE_TYPE field
1278	 of the first name will be clobbered by the second.  */
1279      output_add_string (scratch_buffer, "operator ");
1280      dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
1281    }
1282  else if (IDENTIFIER_OPNAME_P (name))
1283    print_tree_identifier (scratch_buffer, name);
1284  else
1285    dump_decl (name, flags);
1286
1287  if (DECL_LANG_SPECIFIC (t) && DECL_TEMPLATE_INFO (t)
1288      && !DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (t)
1289      && (DECL_TEMPLATE_SPECIALIZATION (t)
1290	  || TREE_CODE (DECL_TI_TEMPLATE (t)) != TEMPLATE_DECL
1291	  || DECL_TEMPLATE_SPECIALIZATION (DECL_TI_TEMPLATE (t))
1292	  || PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (t))))
1293    dump_template_parms (DECL_TEMPLATE_INFO (t), !DECL_USE_TEMPLATE (t), flags);
1294}
1295
1296/* Dump the template parameters from the template info INFO under control of
1297   FLAGS. PRIMARY indicates whether this is a primary template decl, or
1298   specialization (partial or complete). For partial specializations we show
1299   the specialized parameter values. For a primary template we show no
1300   decoration.  */
1301
1302static void
1303dump_template_parms (info, primary, flags)
1304     tree info;
1305     int primary;
1306     int flags;
1307{
1308  tree args = info ? TI_ARGS (info) : NULL_TREE;
1309
1310  if (primary && flags & TFF_TEMPLATE_NAME)
1311    return;
1312  flags &= ~(TFF_CLASS_KEY_OR_ENUM | TFF_TEMPLATE_NAME);
1313  print_template_argument_list_start (scratch_buffer);
1314
1315  /* Be careful only to print things when we have them, so as not
1316	 to crash producing error messages.  */
1317  if (args && !primary)
1318    {
1319      int len = 0;
1320      int ix = 0;
1321      int need_comma = 0;
1322
1323      if (TREE_CODE (args) == TREE_VEC)
1324        {
1325          if (TREE_VEC_LENGTH (args) > 0
1326	      && TREE_CODE (TREE_VEC_ELT (args, 0)) == TREE_VEC)
1327	    args = TREE_VEC_ELT (args, TREE_VEC_LENGTH (args) - 1);
1328
1329          len = TREE_VEC_LENGTH (args);
1330        }
1331      else if (TREE_CODE (args) == TREE_LIST)
1332        len = -1;
1333      while (ix != len && args)
1334        {
1335          tree arg;
1336          if (len >= 0)
1337            {
1338              arg = TREE_VEC_ELT (args, ix);
1339              ix++;
1340            }
1341          else
1342            {
1343              arg = TREE_VALUE (args);
1344              args = TREE_CHAIN (args);
1345            }
1346          if (need_comma)
1347            separate_with_comma (scratch_buffer);
1348
1349          if (!arg)
1350            print_identifier (scratch_buffer, "<template parameter error>");
1351          else
1352            dump_template_argument (arg, flags);
1353          need_comma = 1;
1354        }
1355    }
1356  else if (primary)
1357    {
1358      tree tpl = TI_TEMPLATE (info);
1359      tree parms = DECL_TEMPLATE_PARMS (tpl);
1360      int len, ix;
1361
1362      parms = TREE_CODE (parms) == TREE_LIST ? TREE_VALUE (parms) : NULL_TREE;
1363      len = parms ? TREE_VEC_LENGTH (parms) : 0;
1364
1365      for (ix = 0; ix != len; ix++)
1366        {
1367          tree parm = TREE_VALUE (TREE_VEC_ELT (parms, ix));
1368
1369          if (ix)
1370            separate_with_comma (scratch_buffer);
1371
1372          dump_decl (parm, flags & ~TFF_DECL_SPECIFIERS);
1373        }
1374    }
1375  print_template_argument_list_end (scratch_buffer);
1376}
1377
1378static void
1379dump_char (c)
1380     int c;
1381{
1382  switch (c)
1383    {
1384    case TARGET_NEWLINE:
1385      output_add_string (scratch_buffer, "\\n");
1386      break;
1387    case TARGET_TAB:
1388      output_add_string (scratch_buffer, "\\t");
1389      break;
1390    case TARGET_VT:
1391      output_add_string (scratch_buffer, "\\v");
1392      break;
1393    case TARGET_BS:
1394      output_add_string (scratch_buffer, "\\b");
1395      break;
1396    case TARGET_CR:
1397      output_add_string (scratch_buffer, "\\r");
1398      break;
1399    case TARGET_FF:
1400      output_add_string (scratch_buffer, "\\f");
1401      break;
1402    case TARGET_BELL:
1403      output_add_string (scratch_buffer, "\\a");
1404      break;
1405    case '\\':
1406      output_add_string (scratch_buffer, "\\\\");
1407      break;
1408    case '\'':
1409      output_add_string (scratch_buffer, "\\'");
1410      break;
1411    case '\"':
1412      output_add_string (scratch_buffer, "\\\"");
1413      break;
1414    default:
1415      if (ISPRINT (c))
1416	output_add_character (scratch_buffer, c);
1417      else
1418	{
1419	  sprintf (digit_buffer, "\\%03o", (int) c);
1420	  output_add_string (scratch_buffer, digit_buffer);
1421	}
1422    }
1423}
1424
1425/* Print out a list of initializers (subr of dump_expr) */
1426
1427static void
1428dump_expr_list (l, flags)
1429     tree l;
1430     int flags;
1431{
1432  while (l)
1433    {
1434      dump_expr (TREE_VALUE (l), flags | TFF_EXPR_IN_PARENS);
1435      l = TREE_CHAIN (l);
1436      if (l)
1437	separate_with_comma (scratch_buffer);
1438    }
1439}
1440
1441/* Print out an expression E under control of FLAGS.  */
1442
1443static void
1444dump_expr (t, flags)
1445     tree t;
1446     int flags;
1447{
1448  if (t == 0)
1449    return;
1450
1451  switch (TREE_CODE (t))
1452    {
1453    case VAR_DECL:
1454    case PARM_DECL:
1455    case FIELD_DECL:
1456    case CONST_DECL:
1457    case FUNCTION_DECL:
1458    case TEMPLATE_DECL:
1459    case NAMESPACE_DECL:
1460    case OVERLOAD:
1461      dump_decl (t, flags & ~TFF_DECL_SPECIFIERS);
1462      break;
1463
1464    case INTEGER_CST:
1465      {
1466	tree type = TREE_TYPE (t);
1467	my_friendly_assert (type != 0, 81);
1468
1469	/* If it's an enum, output its tag, rather than its value.  */
1470	if (TREE_CODE (type) == ENUMERAL_TYPE)
1471	  {
1472	    tree values = TYPE_VALUES (type);
1473
1474	    for (; values;
1475	         values = TREE_CHAIN (values))
1476	      if (tree_int_cst_equal (TREE_VALUE (values), t))
1477	        break;
1478
1479	    if (values)
1480	      print_tree_identifier (scratch_buffer, TREE_PURPOSE (values));
1481	    else
1482	      {
1483                /* Value must have been cast.  */
1484                print_left_paren (scratch_buffer);
1485                dump_type (type, flags);
1486                print_right_paren (scratch_buffer);
1487                goto do_int;
1488	      }
1489	  }
1490	else if (type == boolean_type_node)
1491	  {
1492	    if (t == boolean_false_node || integer_zerop (t))
1493	      print_identifier (scratch_buffer, "false");
1494	    else if (t == boolean_true_node)
1495	      print_identifier (scratch_buffer, "true");
1496	  }
1497	else if (type == char_type_node)
1498	  {
1499	    output_add_character (scratch_buffer, '\'');
1500	    if (host_integerp (t, TREE_UNSIGNED (type)))
1501	      dump_char (tree_low_cst (t, TREE_UNSIGNED (type)));
1502	    else
1503	      output_printf (scratch_buffer, "\\x%x",
1504			     (unsigned int) TREE_INT_CST_LOW (t));
1505	    output_add_character (scratch_buffer, '\'');
1506	  }
1507	else
1508	  {
1509	    do_int:
1510	    if (! host_integerp (t, 0))
1511	      {
1512	        tree val = t;
1513
1514	        if (tree_int_cst_sgn (val) < 0)
1515	          {
1516		    output_add_character (scratch_buffer, '-');
1517		    val = build_int_2 (-TREE_INT_CST_LOW (val),
1518				       ~TREE_INT_CST_HIGH (val)
1519	                               + !TREE_INT_CST_LOW (val));
1520	          }
1521	        /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
1522	           systems?  */
1523	        {
1524	          static char format[10]; /* "%x%09999x\0" */
1525	          if (!format[0])
1526		    sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
1527	          sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
1528		           TREE_INT_CST_LOW (val));
1529	          output_add_string (scratch_buffer, digit_buffer);
1530	        }
1531	      }
1532	    else
1533	      print_integer (scratch_buffer, TREE_INT_CST_LOW (t));
1534	  }
1535      }
1536      break;
1537
1538    case REAL_CST:
1539      real_to_decimal (digit_buffer, &TREE_REAL_CST (t),
1540		       sizeof (digit_buffer), 0, 1);
1541      output_add_string (scratch_buffer, digit_buffer);
1542      break;
1543
1544    case PTRMEM_CST:
1545      output_add_character (scratch_buffer, '&');
1546      dump_type (PTRMEM_CST_CLASS (t), flags);
1547      print_scope_operator (scratch_buffer);
1548      print_tree_identifier
1549        (scratch_buffer, DECL_NAME (PTRMEM_CST_MEMBER (t)));
1550      break;
1551
1552    case STRING_CST:
1553      {
1554	const char *p = TREE_STRING_POINTER (t);
1555	int len = TREE_STRING_LENGTH (t) - 1;
1556	int i;
1557
1558	output_add_character (scratch_buffer, '\"');
1559	for (i = 0; i < len; i++)
1560	  dump_char (p[i]);
1561	output_add_character (scratch_buffer, '\"');
1562      }
1563      break;
1564
1565    case COMPOUND_EXPR:
1566      print_left_paren (scratch_buffer);
1567      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1568      separate_with_comma (scratch_buffer);
1569      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1570      print_right_paren (scratch_buffer);
1571      break;
1572
1573    case COND_EXPR:
1574      print_left_paren (scratch_buffer);
1575      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1576      output_add_string (scratch_buffer, " ? ");
1577      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1578      output_add_string (scratch_buffer, " : ");
1579      dump_expr (TREE_OPERAND (t, 2), flags | TFF_EXPR_IN_PARENS);
1580      print_right_paren (scratch_buffer);
1581      break;
1582
1583    case SAVE_EXPR:
1584      if (TREE_HAS_CONSTRUCTOR (t))
1585	{
1586	  output_add_string (scratch_buffer, "new ");
1587	  dump_type (TREE_TYPE (TREE_TYPE (t)), flags);
1588	}
1589      else
1590	{
1591	  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1592	}
1593      break;
1594
1595    case AGGR_INIT_EXPR:
1596      {
1597	tree fn = NULL_TREE;
1598
1599	if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
1600	  fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
1601
1602	if (fn && TREE_CODE (fn) == FUNCTION_DECL)
1603	  {
1604	    if (DECL_CONSTRUCTOR_P (fn))
1605	      print_tree_identifier
1606                (scratch_buffer, TYPE_IDENTIFIER (TREE_TYPE (t)));
1607	    else
1608	      dump_decl (fn, 0);
1609	  }
1610	else
1611	  dump_expr (TREE_OPERAND (t, 0), 0);
1612      }
1613      print_left_paren (scratch_buffer);
1614      if (TREE_OPERAND (t, 1))
1615	dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1616      print_right_paren (scratch_buffer);
1617      break;
1618
1619    case CALL_EXPR:
1620      {
1621	tree fn = TREE_OPERAND (t, 0);
1622	tree args = TREE_OPERAND (t, 1);
1623
1624	if (TREE_CODE (fn) == ADDR_EXPR)
1625	  fn = TREE_OPERAND (fn, 0);
1626
1627	if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
1628	  {
1629	    tree ob = TREE_VALUE (args);
1630	    if (TREE_CODE (ob) == ADDR_EXPR)
1631	      {
1632		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1633		output_add_character (scratch_buffer, '.');
1634	      }
1635	    else if (TREE_CODE (ob) != PARM_DECL
1636		     || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1637	      {
1638		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1639		output_add_string (scratch_buffer, "->");
1640	      }
1641	    args = TREE_CHAIN (args);
1642	  }
1643	dump_expr (fn, flags | TFF_EXPR_IN_PARENS);
1644	print_left_paren (scratch_buffer);
1645	dump_expr_list (args, flags);
1646	print_right_paren (scratch_buffer);
1647      }
1648      break;
1649
1650    case NEW_EXPR:
1651      {
1652	tree type = TREE_OPERAND (t, 1);
1653	tree init = TREE_OPERAND (t, 2);
1654	if (NEW_EXPR_USE_GLOBAL (t))
1655	  print_scope_operator (scratch_buffer);
1656	output_add_string (scratch_buffer, "new ");
1657	if (TREE_OPERAND (t, 0))
1658	  {
1659	    print_left_paren (scratch_buffer);
1660	    dump_expr_list (TREE_OPERAND (t, 0), flags);
1661	    output_add_string (scratch_buffer, ") ");
1662	  }
1663	if (TREE_CODE (type) == ARRAY_REF)
1664	  type = build_cplus_array_type
1665	    (TREE_OPERAND (type, 0),
1666	     build_index_type (fold (build (MINUS_EXPR, integer_type_node,
1667					    TREE_OPERAND (type, 1),
1668					    integer_one_node))));
1669	dump_type (type, flags);
1670	if (init)
1671	  {
1672	    print_left_paren (scratch_buffer);
1673	    if (TREE_CODE (init) == TREE_LIST)
1674	      dump_expr_list (init, flags);
1675	    else if (init == void_zero_node)
1676	      /* This representation indicates an empty initializer,
1677		 e.g.: "new int()".  */
1678	      ;
1679	    else
1680	      dump_expr (init, flags);
1681	    print_right_paren (scratch_buffer);
1682	  }
1683      }
1684      break;
1685
1686    case TARGET_EXPR:
1687      /* Note that this only works for G++ target exprs.  If somebody
1688	 builds a general TARGET_EXPR, there's no way to represent that
1689	 it initializes anything other that the parameter slot for the
1690	 default argument.  Note we may have cleared out the first
1691	 operand in expand_expr, so don't go killing ourselves.  */
1692      if (TREE_OPERAND (t, 1))
1693	dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1694      break;
1695
1696    case INIT_EXPR:
1697    case MODIFY_EXPR:
1698    case PLUS_EXPR:
1699    case MINUS_EXPR:
1700    case MULT_EXPR:
1701    case TRUNC_DIV_EXPR:
1702    case TRUNC_MOD_EXPR:
1703    case MIN_EXPR:
1704    case MAX_EXPR:
1705    case LSHIFT_EXPR:
1706    case RSHIFT_EXPR:
1707    case BIT_IOR_EXPR:
1708    case BIT_XOR_EXPR:
1709    case BIT_AND_EXPR:
1710    case BIT_ANDTC_EXPR:
1711    case TRUTH_ANDIF_EXPR:
1712    case TRUTH_ORIF_EXPR:
1713    case LT_EXPR:
1714    case LE_EXPR:
1715    case GT_EXPR:
1716    case GE_EXPR:
1717    case EQ_EXPR:
1718    case NE_EXPR:
1719    case EXACT_DIV_EXPR:
1720      dump_binary_op (operator_name_info[(int) TREE_CODE (t)].name, t, flags);
1721      break;
1722
1723    case CEIL_DIV_EXPR:
1724    case FLOOR_DIV_EXPR:
1725    case ROUND_DIV_EXPR:
1726      dump_binary_op ("/", t, flags);
1727      break;
1728
1729    case CEIL_MOD_EXPR:
1730    case FLOOR_MOD_EXPR:
1731    case ROUND_MOD_EXPR:
1732      dump_binary_op ("%", t, flags);
1733      break;
1734
1735    case COMPONENT_REF:
1736      {
1737	tree ob = TREE_OPERAND (t, 0);
1738	if (TREE_CODE (ob) == INDIRECT_REF)
1739	  {
1740	    ob = TREE_OPERAND (ob, 0);
1741	    if (TREE_CODE (ob) != PARM_DECL
1742		|| strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1743	      {
1744		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1745		output_add_string (scratch_buffer, "->");
1746	      }
1747	  }
1748	else
1749	  {
1750	    dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1751	    output_add_character (scratch_buffer, '.');
1752	  }
1753	dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
1754      }
1755      break;
1756
1757    case ARRAY_REF:
1758      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1759      print_left_bracket (scratch_buffer);
1760      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1761      print_right_bracket (scratch_buffer);
1762      break;
1763
1764    case CONVERT_EXPR:
1765      if (TREE_TYPE (t) && VOID_TYPE_P (TREE_TYPE (t)))
1766	{
1767	  print_left_paren (scratch_buffer);
1768	  dump_type (TREE_TYPE (t), flags);
1769	  print_right_paren (scratch_buffer);
1770	  dump_expr (TREE_OPERAND (t, 0), flags);
1771	}
1772      else
1773	dump_unary_op ("+", t, flags);
1774      break;
1775
1776    case ADDR_EXPR:
1777      if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
1778	  || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST
1779	  /* An ADDR_EXPR can have reference type.  In that case, we
1780	     shouldn't print the `&' doing so indicates to the user
1781	     that the expression has pointer type.  */
1782	  || (TREE_TYPE (t)
1783	      && TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE))
1784	dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1785      else
1786	dump_unary_op ("&", t, flags);
1787      break;
1788
1789    case INDIRECT_REF:
1790      if (TREE_HAS_CONSTRUCTOR (t))
1791	{
1792	  t = TREE_OPERAND (t, 0);
1793	  my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
1794	  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1795	  print_left_paren (scratch_buffer);
1796	  dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)), flags);
1797	  print_right_paren (scratch_buffer);
1798	}
1799      else
1800	{
1801	  if (TREE_OPERAND (t,0) != NULL_TREE
1802	      && TREE_TYPE (TREE_OPERAND (t, 0))
1803	      && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
1804	    dump_expr (TREE_OPERAND (t, 0), flags);
1805	  else
1806	    dump_unary_op ("*", t, flags);
1807	}
1808      break;
1809
1810    case NEGATE_EXPR:
1811    case BIT_NOT_EXPR:
1812    case TRUTH_NOT_EXPR:
1813    case PREDECREMENT_EXPR:
1814    case PREINCREMENT_EXPR:
1815      dump_unary_op (operator_name_info [(int)TREE_CODE (t)].name, t, flags);
1816      break;
1817
1818    case POSTDECREMENT_EXPR:
1819    case POSTINCREMENT_EXPR:
1820      print_left_paren (scratch_buffer);
1821      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1822      print_identifier
1823        (scratch_buffer, operator_name_info[(int)TREE_CODE (t)].name);
1824      print_right_paren (scratch_buffer);
1825      break;
1826
1827    case NON_LVALUE_EXPR:
1828      /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
1829	 should be another level of INDIRECT_REF so that I don't have to do
1830	 this.  */
1831      if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
1832	{
1833	  tree next = TREE_TYPE (TREE_TYPE (t));
1834
1835	  while (TREE_CODE (next) == POINTER_TYPE)
1836	    next = TREE_TYPE (next);
1837
1838	  if (TREE_CODE (next) == FUNCTION_TYPE)
1839	    {
1840	      if (flags & TFF_EXPR_IN_PARENS)
1841	        print_left_paren (scratch_buffer);
1842	      output_add_character (scratch_buffer, '*');
1843	      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
1844	      if (flags & TFF_EXPR_IN_PARENS)
1845	        print_right_paren (scratch_buffer);
1846	      break;
1847	    }
1848	  /* else FALLTHRU */
1849	}
1850      dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
1851      break;
1852
1853    case NOP_EXPR:
1854      dump_expr (TREE_OPERAND (t, 0), flags);
1855      break;
1856
1857    case EXPR_WITH_FILE_LOCATION:
1858      dump_expr (EXPR_WFL_NODE (t), flags);
1859      break;
1860
1861    case CONSTRUCTOR:
1862      if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
1863	{
1864	  tree idx = build_ptrmemfunc_access_expr (t, pfn_identifier);
1865
1866	  if (integer_zerop (idx))
1867	    {
1868	      /* A NULL pointer-to-member constant.  */
1869	      output_add_string (scratch_buffer, "((");
1870	      dump_type (TREE_TYPE (t), flags);
1871	      output_add_string (scratch_buffer, ") 0)");
1872	      break;
1873	    }
1874	  else if (host_integerp (idx, 0))
1875	    {
1876	      tree virtuals;
1877	      unsigned HOST_WIDE_INT n;
1878
1879	      t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
1880	      t = TYPE_METHOD_BASETYPE (t);
1881	      virtuals = TYPE_BINFO_VIRTUALS (TYPE_MAIN_VARIANT (t));
1882
1883	      n = tree_low_cst (idx, 0);
1884
1885	      /* Map vtable index back one, to allow for the null pointer to
1886		 member.  */
1887	      --n;
1888
1889	      while (n > 0 && virtuals)
1890		{
1891		  --n;
1892		  virtuals = TREE_CHAIN (virtuals);
1893		}
1894	      if (virtuals)
1895		{
1896		  dump_expr (BV_FN (virtuals),
1897	                     flags | TFF_EXPR_IN_PARENS);
1898		  break;
1899		}
1900	    }
1901	}
1902      /* We've gotten an rvalue of the form 'T()'.  */
1903      else if (TREE_TYPE (t))
1904        {
1905          dump_type (TREE_TYPE (t), flags);
1906          print_left_paren (scratch_buffer);
1907          print_right_paren (scratch_buffer);
1908        }
1909      else
1910        {
1911          output_add_character (scratch_buffer, '{');
1912          dump_expr_list (CONSTRUCTOR_ELTS (t), flags);
1913          output_add_character (scratch_buffer, '}');
1914        }
1915      break;
1916
1917    case OFFSET_REF:
1918      {
1919	tree ob = TREE_OPERAND (t, 0);
1920	if (is_dummy_object (ob))
1921	  {
1922	    t = TREE_OPERAND (t, 1);
1923	    if (TREE_CODE (t) == FUNCTION_DECL)
1924	      /* A::f */
1925	      dump_expr (t, flags | TFF_EXPR_IN_PARENS);
1926	    else if (BASELINK_P (t))
1927	      dump_expr (OVL_CURRENT (BASELINK_FUNCTIONS (t)),
1928			 flags | TFF_EXPR_IN_PARENS);
1929	    else
1930	      dump_decl (t, flags);
1931	  }
1932	else
1933	  {
1934	    if (TREE_CODE (ob) == INDIRECT_REF)
1935	      {
1936		dump_expr (TREE_OPERAND (ob, 0), flags | TFF_EXPR_IN_PARENS);
1937		output_add_string (scratch_buffer, "->*");
1938	      }
1939	    else
1940	      {
1941		dump_expr (ob, flags | TFF_EXPR_IN_PARENS);
1942		output_add_string (scratch_buffer, ".*");
1943	      }
1944	    dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1945	  }
1946	break;
1947      }
1948
1949    case TEMPLATE_PARM_INDEX:
1950      dump_decl (TEMPLATE_PARM_DECL (t), flags & ~TFF_DECL_SPECIFIERS);
1951      break;
1952
1953    case IDENTIFIER_NODE:
1954      print_tree_identifier (scratch_buffer, t);
1955      break;
1956
1957    case SCOPE_REF:
1958      dump_type (TREE_OPERAND (t, 0), flags);
1959      print_scope_operator (scratch_buffer);
1960      dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
1961      break;
1962
1963    case CAST_EXPR:
1964      if (TREE_OPERAND (t, 0) == NULL_TREE
1965	  || TREE_CHAIN (TREE_OPERAND (t, 0)))
1966	{
1967	  dump_type (TREE_TYPE (t), flags);
1968	  print_left_paren (scratch_buffer);
1969	  dump_expr_list (TREE_OPERAND (t, 0), flags);
1970	  print_right_paren (scratch_buffer);
1971	}
1972      else
1973	{
1974	  print_left_paren (scratch_buffer);
1975	  dump_type (TREE_TYPE (t), flags);
1976          output_add_string (scratch_buffer, ")(");
1977	  dump_expr_list (TREE_OPERAND (t, 0), flags);
1978	  print_right_paren (scratch_buffer);
1979	}
1980      break;
1981
1982    case STATIC_CAST_EXPR:
1983      output_add_string (scratch_buffer, "static_cast<");
1984      goto cast;
1985    case REINTERPRET_CAST_EXPR:
1986      output_add_string (scratch_buffer, "reinterpret_cast<");
1987      goto cast;
1988    case CONST_CAST_EXPR:
1989      output_add_string (scratch_buffer, "const_cast<");
1990      goto cast;
1991    case DYNAMIC_CAST_EXPR:
1992      output_add_string (scratch_buffer, "dynamic_cast<");
1993    cast:
1994      dump_type (TREE_TYPE (t), flags);
1995      output_add_string (scratch_buffer, ">(");
1996      dump_expr (TREE_OPERAND (t, 0), flags);
1997      print_right_paren (scratch_buffer);
1998      break;
1999
2000    case LOOKUP_EXPR:
2001      print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0));
2002      break;
2003
2004    case ARROW_EXPR:
2005      dump_expr (TREE_OPERAND (t, 0), flags);
2006      output_add_string (scratch_buffer, "->");
2007      break;
2008
2009    case SIZEOF_EXPR:
2010    case ALIGNOF_EXPR:
2011      if (TREE_CODE (t) == SIZEOF_EXPR)
2012	output_add_string (scratch_buffer, "sizeof (");
2013      else
2014	{
2015	  my_friendly_assert (TREE_CODE (t) == ALIGNOF_EXPR, 0);
2016	  output_add_string (scratch_buffer, "__alignof__ (");
2017	}
2018      if (TYPE_P (TREE_OPERAND (t, 0)))
2019	dump_type (TREE_OPERAND (t, 0), flags);
2020      else
2021	dump_unary_op ("*", t, flags | TFF_EXPR_IN_PARENS);
2022      print_right_paren (scratch_buffer);
2023      break;
2024
2025    case DEFAULT_ARG:
2026      print_identifier (scratch_buffer, "<unparsed>");
2027      break;
2028
2029    case TRY_CATCH_EXPR:
2030    case WITH_CLEANUP_EXPR:
2031    case CLEANUP_POINT_EXPR:
2032      dump_expr (TREE_OPERAND (t, 0), flags);
2033      break;
2034
2035    case PSEUDO_DTOR_EXPR:
2036      dump_expr (TREE_OPERAND (t, 2), flags);
2037      output_add_character (scratch_buffer, '.');
2038      dump_type (TREE_OPERAND (t, 0), flags);
2039      output_add_string (scratch_buffer, "::~");
2040      dump_type (TREE_OPERAND (t, 1), flags);
2041      break;
2042
2043    case TEMPLATE_ID_EXPR:
2044      dump_decl (t, flags);
2045      break;
2046
2047    case STMT_EXPR:
2048      /* We don't yet have a way of dumping statements in a
2049	 human-readable format.  */
2050      output_add_string (scratch_buffer, "({...})");
2051      break;
2052
2053    case BIND_EXPR:
2054      output_add_character (scratch_buffer, '{');
2055      dump_expr (TREE_OPERAND (t, 1), flags & ~TFF_EXPR_IN_PARENS);
2056      output_add_character (scratch_buffer, '}');
2057      break;
2058
2059    case LOOP_EXPR:
2060      output_add_string (scratch_buffer, "while (1) { ");
2061      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2062      output_add_character (scratch_buffer, '}');
2063      break;
2064
2065    case EXIT_EXPR:
2066      output_add_string (scratch_buffer, "if (");
2067      dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2068      output_add_string (scratch_buffer, ") break; ");
2069      break;
2070
2071    case BASELINK:
2072      print_tree_identifier (scratch_buffer, DECL_NAME (get_first_fn (t)));
2073      break;
2074
2075    case TREE_LIST:
2076      if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
2077	{
2078	  print_tree_identifier (scratch_buffer, DECL_NAME (TREE_VALUE (t)));
2079	  break;
2080	}
2081      /* else fall through */
2082
2083      /*  This list is incomplete, but should suffice for now.
2084	  It is very important that `sorry' does not call
2085	  `report_error_function'.  That could cause an infinite loop.  */
2086    default:
2087      sorry_for_unsupported_tree (t);
2088      /* fall through to ERROR_MARK...  */
2089    case ERROR_MARK:
2090      print_identifier (scratch_buffer, "<expression error>");
2091      break;
2092    }
2093}
2094
2095static void
2096dump_binary_op (opstring, t, flags)
2097     const char *opstring;
2098     tree t;
2099     int flags;
2100{
2101  print_left_paren (scratch_buffer);
2102  dump_expr (TREE_OPERAND (t, 0), flags | TFF_EXPR_IN_PARENS);
2103  output_add_space (scratch_buffer);
2104  if (opstring)
2105    print_identifier (scratch_buffer, opstring);
2106  else
2107    print_identifier (scratch_buffer, "<unknown operator>");
2108  output_add_space (scratch_buffer);
2109  dump_expr (TREE_OPERAND (t, 1), flags | TFF_EXPR_IN_PARENS);
2110  print_right_paren (scratch_buffer);
2111}
2112
2113static void
2114dump_unary_op (opstring, t, flags)
2115     const char *opstring;
2116     tree t;
2117     int flags;
2118{
2119  if (flags & TFF_EXPR_IN_PARENS)
2120    print_left_paren (scratch_buffer);
2121  print_identifier (scratch_buffer, opstring);
2122  dump_expr (TREE_OPERAND (t, 0), flags & ~TFF_EXPR_IN_PARENS);
2123  if (flags & TFF_EXPR_IN_PARENS)
2124    print_right_paren (scratch_buffer);
2125}
2126
2127/* Exported interface to stringifying types, exprs and decls under TFF_*
2128   control.  */
2129
2130const char *
2131type_as_string (typ, flags)
2132     tree typ;
2133     int flags;
2134{
2135  reinit_global_formatting_buffer ();
2136
2137  dump_type (typ, flags);
2138
2139  return output_finalize_message (scratch_buffer);
2140}
2141
2142const char *
2143expr_as_string (decl, flags)
2144     tree decl;
2145     int flags;
2146{
2147  reinit_global_formatting_buffer ();
2148
2149  dump_expr (decl, flags);
2150
2151  return output_finalize_message (scratch_buffer);
2152}
2153
2154const char *
2155decl_as_string (decl, flags)
2156     tree decl;
2157     int flags;
2158{
2159  reinit_global_formatting_buffer ();
2160
2161  dump_decl (decl, flags);
2162
2163  return output_finalize_message (scratch_buffer);
2164}
2165
2166const char *
2167context_as_string (context, flags)
2168     tree context;
2169     int flags;
2170{
2171  reinit_global_formatting_buffer ();
2172
2173  dump_scope (context, flags);
2174
2175  return output_finalize_message (scratch_buffer);
2176}
2177
2178/* Generate the three forms of printable names for cxx_printable_name.  */
2179
2180const char *
2181lang_decl_name (decl, v)
2182     tree decl;
2183     int v;
2184{
2185  if (v >= 2)
2186    return decl_as_string (decl, TFF_DECL_SPECIFIERS);
2187
2188  reinit_global_formatting_buffer ();
2189
2190  if (v == 1 && DECL_CLASS_SCOPE_P (decl))
2191    {
2192      dump_type (CP_DECL_CONTEXT (decl), TFF_PLAIN_IDENTIFIER);
2193      print_scope_operator (scratch_buffer);
2194    }
2195
2196  if (TREE_CODE (decl) == FUNCTION_DECL)
2197    dump_function_name (decl, TFF_PLAIN_IDENTIFIER);
2198  else
2199    dump_decl (DECL_NAME (decl), TFF_PLAIN_IDENTIFIER);
2200
2201  return output_finalize_message (scratch_buffer);
2202}
2203
2204const char *
2205cp_file_of (t)
2206     tree t;
2207{
2208  if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2209    return DECL_SOURCE_FILE (DECL_CONTEXT (t));
2210  else if (TYPE_P (t))
2211    return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
2212  else if (TREE_CODE (t) == OVERLOAD)
2213    return DECL_SOURCE_FILE (OVL_FUNCTION (t));
2214  else
2215    return DECL_SOURCE_FILE (t);
2216}
2217
2218int
2219cp_line_of (t)
2220     tree t;
2221{
2222  int line = 0;
2223  if (TREE_CODE (t) == PARM_DECL && DECL_CONTEXT (t))
2224    line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
2225  if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t)
2226      && TYPE_MAIN_DECL (TREE_TYPE (t)))
2227    t = TREE_TYPE (t);
2228
2229  if (TYPE_P (t))
2230    line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
2231  else if (TREE_CODE (t) == OVERLOAD)
2232    line = DECL_SOURCE_LINE (OVL_FUNCTION (t));
2233  else
2234    line = DECL_SOURCE_LINE (t);
2235
2236  if (line == 0)
2237    return lineno;
2238
2239  return line;
2240}
2241
2242/* Now the interfaces from error et al to dump_type et al. Each takes an
2243   on/off VERBOSE flag and supply the appropriate TFF_ flags to a dump_
2244   function.  */
2245
2246static const char *
2247decl_to_string (decl, verbose)
2248     tree decl;
2249     int verbose;
2250{
2251  int flags = 0;
2252
2253  if (TREE_CODE (decl) == TYPE_DECL || TREE_CODE (decl) == RECORD_TYPE
2254      || TREE_CODE (decl) == UNION_TYPE || TREE_CODE (decl) == ENUMERAL_TYPE)
2255    flags = TFF_CLASS_KEY_OR_ENUM;
2256  if (verbose)
2257    flags |= TFF_DECL_SPECIFIERS;
2258  else if (TREE_CODE (decl) == FUNCTION_DECL)
2259    flags |= TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE;
2260  flags |= TFF_TEMPLATE_HEADER;
2261
2262  reinit_global_formatting_buffer ();
2263
2264  dump_decl (decl, flags);
2265
2266  return output_finalize_message (scratch_buffer);
2267}
2268
2269static const char *
2270expr_to_string (decl, verbose)
2271     tree decl;
2272     int verbose ATTRIBUTE_UNUSED;
2273{
2274  reinit_global_formatting_buffer ();
2275
2276  dump_expr (decl, 0);
2277
2278  return output_finalize_message (scratch_buffer);
2279}
2280
2281static const char *
2282fndecl_to_string (fndecl, verbose)
2283     tree fndecl;
2284     int verbose;
2285{
2286  int flags;
2287
2288  flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
2289  if (verbose)
2290    flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
2291  reinit_global_formatting_buffer ();
2292
2293  dump_decl (fndecl, flags);
2294
2295  return output_finalize_message (scratch_buffer);
2296}
2297
2298
2299static const char *
2300code_to_string (c, v)
2301     enum tree_code c;
2302     int v ATTRIBUTE_UNUSED;
2303{
2304  return tree_code_name [c];
2305}
2306
2307const char *
2308language_to_string (c, v)
2309     enum languages c;
2310     int v ATTRIBUTE_UNUSED;
2311{
2312  switch (c)
2313    {
2314    case lang_c:
2315      return "C";
2316
2317    case lang_cplusplus:
2318      return "C++";
2319
2320    case lang_java:
2321      return "Java";
2322
2323    default:
2324      abort ();
2325      return 0;
2326    }
2327}
2328
2329/* Return the proper printed version of a parameter to a C++ function.  */
2330
2331static const char *
2332parm_to_string (p, v)
2333     int p;
2334     int v ATTRIBUTE_UNUSED;
2335{
2336  if (p < 0)
2337    return "`this'";
2338
2339  sprintf (digit_buffer, "%d", p+1);
2340  return digit_buffer;
2341}
2342
2343static const char *
2344op_to_string (p, v)
2345     enum tree_code p;
2346     int v ATTRIBUTE_UNUSED;
2347{
2348  tree id;
2349
2350  id = operator_name_info[(int) p].identifier;
2351  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
2352}
2353
2354static const char *
2355type_to_string (typ, verbose)
2356     tree typ;
2357     int verbose;
2358{
2359  int flags;
2360
2361  flags = 0;
2362  if (verbose)
2363    flags |= TFF_CLASS_KEY_OR_ENUM;
2364  flags |= TFF_TEMPLATE_HEADER;
2365
2366  reinit_global_formatting_buffer ();
2367
2368  dump_type (typ, flags);
2369
2370  return output_finalize_message (scratch_buffer);
2371}
2372
2373static const char *
2374assop_to_string (p, v)
2375     enum tree_code p;
2376     int v ATTRIBUTE_UNUSED;
2377{
2378  tree id;
2379
2380  id = assignment_operator_name_info[(int) p].identifier;
2381  return id ? IDENTIFIER_POINTER (id) : "{unknown}";
2382}
2383
2384static const char *
2385args_to_string (p, verbose)
2386     tree p;
2387     int verbose;
2388{
2389  int flags = 0;
2390  if (verbose)
2391    flags |= TFF_CLASS_KEY_OR_ENUM;
2392
2393  if (p == NULL_TREE)
2394    return "";
2395
2396  if (TYPE_P (TREE_VALUE (p)))
2397    return type_as_string (p, flags);
2398
2399  reinit_global_formatting_buffer ();
2400  for (; p; p = TREE_CHAIN (p))
2401    {
2402      if (TREE_VALUE (p) == null_node)
2403	print_identifier (scratch_buffer, "NULL");
2404      else
2405	dump_type (error_type (TREE_VALUE (p)), flags);
2406      if (TREE_CHAIN (p))
2407	separate_with_comma (scratch_buffer);
2408    }
2409  return output_finalize_message (scratch_buffer);
2410}
2411
2412static const char *
2413cv_to_string (p, v)
2414     tree p;
2415     int v;
2416{
2417  reinit_global_formatting_buffer ();
2418
2419  dump_qualifiers (p, v ? before : none);
2420
2421  return output_finalize_message (scratch_buffer);
2422}
2423
2424/* Langhook for print_error_function.  */
2425void
2426cxx_print_error_function (context, file)
2427     diagnostic_context *context;
2428     const char *file;
2429{
2430  lhd_print_error_function (context, file);
2431  output_set_prefix (&context->buffer, file);
2432  maybe_print_instantiation_context (context);
2433}
2434
2435static void
2436cp_diagnostic_starter (context, diagnostic)
2437     diagnostic_context *context;
2438     diagnostic_info *diagnostic;
2439{
2440  diagnostic_report_current_module (context);
2441  cp_print_error_function (context, diagnostic);
2442  maybe_print_instantiation_context (context);
2443  output_set_prefix (&context->buffer, diagnostic_build_prefix (diagnostic));
2444}
2445
2446static void
2447cp_diagnostic_finalizer (context, diagnostic)
2448     diagnostic_context *context;
2449     diagnostic_info *diagnostic __attribute__((unused));
2450{
2451  output_destroy_prefix (&context->buffer);
2452}
2453
2454/* Print current function onto BUFFER, in the process of reporting
2455   a diagnostic message.  Called from cp_diagnostic_starter.  */
2456static void
2457cp_print_error_function (context, diagnostic)
2458     diagnostic_context *context;
2459     diagnostic_info *diagnostic;
2460{
2461  if (diagnostic_last_function_changed (context))
2462    {
2463      const char *old_prefix = output_prefix (&context->buffer);
2464      char *new_prefix = diagnostic->location.file
2465        ? file_name_as_prefix (diagnostic->location.file)
2466        : NULL;
2467
2468      output_set_prefix (&context->buffer, new_prefix);
2469
2470      if (current_function_decl == NULL)
2471        output_add_string (&context->buffer, "At global scope:");
2472      else
2473        output_printf (&context->buffer, "In %s `%s':",
2474                       function_category (current_function_decl),
2475                       cxx_printable_name (current_function_decl, 2));
2476      output_add_newline (&context->buffer);
2477
2478      diagnostic_set_last_function (context);
2479      output_destroy_prefix (&context->buffer);
2480      context->buffer.state.prefix = old_prefix;
2481    }
2482}
2483
2484/* Returns a description of FUNCTION using standard terminology.  */
2485static const char *
2486function_category (fn)
2487     tree fn;
2488{
2489  if (DECL_FUNCTION_MEMBER_P (fn))
2490    {
2491      if (DECL_STATIC_FUNCTION_P (fn))
2492        return "static member function";
2493      else if (DECL_COPY_CONSTRUCTOR_P (fn))
2494        return "copy constructor";
2495      else if (DECL_CONSTRUCTOR_P (fn))
2496        return "constructor";
2497      else if (DECL_DESTRUCTOR_P (fn))
2498        return "destructor";
2499      else
2500        return "member function";
2501    }
2502  else
2503    return "function";
2504}
2505
2506/* Report the full context of a current template instantiation,
2507   onto BUFFER.  */
2508static void
2509print_instantiation_full_context (context)
2510     diagnostic_context *context;
2511{
2512  tree p = current_instantiation ();
2513  int line = lineno;
2514  const char *file = input_filename;
2515
2516  if (p)
2517    {
2518      if (current_function_decl != TINST_DECL (p)
2519	  && current_function_decl != NULL_TREE)
2520	/* We can get here during the processing of some synthesized
2521	   method.  Then, TINST_DECL (p) will be the function that's causing
2522	   the synthesis.  */
2523	;
2524      else
2525	{
2526	  if (current_function_decl == TINST_DECL (p))
2527	    /* Avoid redundancy with the the "In function" line.  */;
2528	  else
2529	    output_verbatim (&context->buffer,
2530                             "%s: In instantiation of `%s':\n", file,
2531                             decl_as_string (TINST_DECL (p),
2532                                             TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2533
2534	  line = TINST_LINE (p);
2535	  file = TINST_FILE (p);
2536	  p = TREE_CHAIN (p);
2537	}
2538    }
2539
2540  print_instantiation_partial_context (context, p, file, line);
2541}
2542
2543/* Same as above but less verbose.  */
2544static void
2545print_instantiation_partial_context (context, t, file, line)
2546     diagnostic_context *context;
2547     tree t;
2548     const char *file;
2549     int line;
2550{
2551  for (; t; t = TREE_CHAIN (t))
2552    {
2553      output_verbatim
2554        (&context->buffer, "%s:%d:   instantiated from `%s'\n", file, line,
2555         decl_as_string (TINST_DECL (t), TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
2556      line = TINST_LINE (t);
2557      file = TINST_FILE (t);
2558    }
2559  output_verbatim (&context->buffer, "%s:%d:   instantiated from here\n", file, line);
2560}
2561
2562/* Called from cp_thing to print the template context for an error.  */
2563static void
2564maybe_print_instantiation_context (context)
2565     diagnostic_context *context;
2566{
2567  if (!problematic_instantiation_changed () || current_instantiation () == 0)
2568    return;
2569
2570  record_last_problematic_instantiation ();
2571  print_instantiation_full_context (context);
2572}
2573
2574/* Report the bare minimum context of a template instantiation.  */
2575void
2576print_instantiation_context ()
2577{
2578  print_instantiation_partial_context
2579    (global_dc, current_instantiation (), input_filename, lineno);
2580  diagnostic_flush_buffer (global_dc);
2581}
2582
2583/* Called from output_format -- during diagnostic message processing --
2584   to handle C++ specific format specifier with the following meanings:
2585   %A   function argument-list.
2586   %C	tree code.
2587   %D   declaration.
2588   %E   expression.
2589   %F   function declaration.
2590   %L	language as used in extern "lang".
2591   %O	binary operator.
2592   %P   function parameter whose position is indicated by an integer.
2593   %Q	assignment operator.
2594   %T   type.
2595   %V   cv-qualifier.  */
2596static bool
2597cp_printer (buffer, text)
2598     output_buffer *buffer;
2599     text_info *text;
2600{
2601  int verbose = 0;
2602  const char *result;
2603#define next_tree    va_arg (*text->args_ptr, tree)
2604#define next_tcode   va_arg (*text->args_ptr, enum tree_code)
2605#define next_lang    va_arg (*text->args_ptr, enum languages)
2606#define next_int     va_arg (*text->args_ptr, int)
2607
2608  if (*text->format_spec == '+')
2609    ++text->format_spec;
2610  if (*text->format_spec == '#')
2611    {
2612      verbose = 1;
2613      ++text->format_spec;
2614    }
2615
2616  switch (*text->format_spec)
2617    {
2618    case 'A': result = args_to_string (next_tree, verbose);	break;
2619    case 'C': result = code_to_string (next_tcode, verbose);	break;
2620    case 'D': result = decl_to_string (next_tree, verbose);	break;
2621    case 'E': result = expr_to_string (next_tree, verbose);	break;
2622    case 'F': result = fndecl_to_string (next_tree, verbose);	break;
2623    case 'L': result = language_to_string (next_lang, verbose); break;
2624    case 'O': result = op_to_string (next_tcode, verbose);	break;
2625    case 'P': result = parm_to_string (next_int, verbose);	break;
2626    case 'Q': result = assop_to_string (next_tcode, verbose);	break;
2627    case 'T': result = type_to_string (next_tree, verbose);	break;
2628    case 'V': result = cv_to_string (next_tree, verbose);	break;
2629
2630    default:
2631      return false;
2632    }
2633
2634  output_add_string (buffer, result);
2635  return true;
2636#undef next_tree
2637#undef next_tcode
2638#undef next_lang
2639#undef next_int
2640}
2641
2642static void
2643print_integer (buffer, i)
2644     output_buffer *buffer;
2645     HOST_WIDE_INT i;
2646{
2647  sprintf (digit_buffer, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT) i);
2648  output_add_string (buffer, digit_buffer);
2649}
2650
2651static void
2652print_non_consecutive_character (buffer, c)
2653     output_buffer *buffer;
2654     int c;
2655{
2656  const char *p = output_last_position (buffer);
2657
2658  if (p != NULL && *p == c)
2659    output_add_space (buffer);
2660  output_add_character (buffer, c);
2661}
2662
2663/* These are temporary wrapper functions which handle the historic
2664   behavior of cp_*_at.  */
2665
2666static tree
2667locate_error (msgid, ap)
2668     const char *msgid;
2669     va_list ap;
2670{
2671  tree here = 0, t;
2672  int plus = 0;
2673  const char *f;
2674
2675  for (f = msgid; *f; f++)
2676    {
2677      plus = 0;
2678      if (*f == '%')
2679	{
2680	  f++;
2681	  if (*f == '+')
2682	    f++, plus = 1;
2683	  if (*f == '#')
2684	    f++;
2685
2686	  switch (*f)
2687	    {
2688	      /* Just ignore these possibilities.  */
2689	    case '%':						break;
2690	    case 'd':	(void) va_arg (ap, int);		break;
2691	    case 's':	(void) va_arg (ap, char *);		break;
2692	    case 'L':	(void) va_arg (ap, enum languages);	break;
2693	    case 'C':
2694	    case 'O':
2695	    case 'Q':	(void) va_arg (ap, enum tree_code);	break;
2696
2697	      /* These take a tree, which may be where the error is
2698		 located.  */
2699	    case 'A':
2700	    case 'D':
2701	    case 'E':
2702	    case 'F':
2703	    case 'P':
2704	    case 'T':
2705	    case 'V':
2706	      t = va_arg (ap, tree);
2707	      if (!here || plus)
2708		here = t;
2709	      break;
2710
2711	    default:
2712	      errorcount = 0;  /* damn ICE suppression */
2713	      internal_error ("unexpected letter `%c' in locate_error\n", *f);
2714	    }
2715	}
2716    }
2717
2718  if (here == 0)
2719    here = va_arg (ap, tree);
2720
2721  return here;
2722}
2723
2724
2725void
2726cp_error_at VPARAMS ((const char *msgid, ...))
2727{
2728  tree here;
2729  diagnostic_info diagnostic;
2730
2731  VA_OPEN (ap, msgid);
2732  VA_FIXEDARG (ap, const char *, msgid);
2733  here = locate_error (msgid, ap);
2734  VA_CLOSE (ap);
2735
2736  VA_OPEN (ap, msgid);
2737  VA_FIXEDARG (ap, const char *, msgid);
2738
2739  diagnostic_set_info (&diagnostic, msgid, &ap,
2740                       cp_file_of (here), cp_line_of (here), DK_ERROR);
2741  report_diagnostic (&diagnostic);
2742  VA_CLOSE (ap);
2743}
2744
2745void
2746cp_warning_at VPARAMS ((const char *msgid, ...))
2747{
2748  tree here;
2749  diagnostic_info diagnostic;
2750
2751  VA_OPEN (ap, msgid);
2752  VA_FIXEDARG (ap, const char *, msgid);
2753  here = locate_error (msgid, ap);
2754  VA_CLOSE (ap);
2755
2756  VA_OPEN (ap, msgid);
2757  VA_FIXEDARG (ap, const char *, msgid);
2758
2759  diagnostic_set_info (&diagnostic, msgid, &ap,
2760                       cp_file_of (here), cp_line_of (here), DK_WARNING);
2761  report_diagnostic (&diagnostic);
2762  VA_CLOSE (ap);
2763}
2764
2765void
2766cp_pedwarn_at VPARAMS ((const char *msgid, ...))
2767{
2768  tree here;
2769  diagnostic_info diagnostic;
2770
2771  VA_OPEN (ap, msgid);
2772  VA_FIXEDARG (ap, const char *, msgid);
2773  here = locate_error (msgid, ap);
2774  VA_CLOSE (ap);
2775
2776  VA_OPEN (ap, msgid);
2777  VA_FIXEDARG (ap, const char *, msgid);
2778
2779  diagnostic_set_info (&diagnostic, msgid, &ap,
2780                       cp_file_of (here), cp_line_of (here),
2781                       pedantic_error_kind());
2782  report_diagnostic (&diagnostic);
2783  VA_CLOSE (ap);
2784}
2785