OSDN Git Service

90th Cygnus<->FSF quick merge
[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 Free Software Foundation, Inc.
4
5    This file is part of GNU CC.
6
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING.  If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.  */
21
22 #include "config.h"
23 #include "tree.h"
24 #include "cp-tree.h"
25 #include "obstack.h"
26 #include <ctype.h>
27
28 typedef char* cp_printer ();
29
30 #define A args_as_string
31 #define C code_as_string
32 #define D decl_as_string
33 #define E expr_as_string
34 #define L language_as_string
35 #define O op_as_string
36 #define P parm_as_string
37 #define Q assop_as_string
38 #define T type_as_string
39 #define V cv_as_string
40
41 #define _ (cp_printer *) 0
42 cp_printer * cp_printers[256] =
43
44 /*0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F */
45   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */
46   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */
47   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
48   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
49   _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */
50   P, Q, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */
51   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
52   _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
53 };
54 #undef C
55 #undef D
56 #undef E
57 #undef L
58 #undef O
59 #undef P
60 #undef Q
61 #undef T
62 #undef V
63 #undef _
64
65 #define obstack_chunk_alloc xmalloc
66 #define obstack_chunk_free free
67
68 /* Obstack where we build text strings for overloading, etc.  */
69 static struct obstack scratch_obstack;
70 static char *scratch_firstobj;
71
72 # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
73 # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
74 # define OB_PUTC2(C1,C2)        \
75   (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
76 # define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
77 # define OB_PUTID(ID)  \
78   (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID),     \
79                  IDENTIFIER_LENGTH (ID)))
80 # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
81 # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
82 # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
83                            OB_PUTCP (digit_buffer); } while (0)
84 # define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
85
86 # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
87
88 static void dump_type (), dump_decl (), dump_function_decl ();
89 static void dump_expr (), dump_unary_op (), dump_binary_op ();
90 static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix ();
91 static void dump_function_name ();
92
93 void
94 init_error ()
95 {
96   gcc_obstack_init (&scratch_obstack);
97   scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
98 }
99
100 enum pad { none, before, after };
101
102 static void
103 dump_readonly_or_volatile (t, p)
104      tree t;
105      enum pad p;
106 {
107   if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
108     {
109       if (p == before) OB_PUTC (' ');
110       if (TYPE_READONLY (t))
111         OB_PUTS ("const");
112       if (TYPE_READONLY (t) && TYPE_VOLATILE (t))
113         OB_PUTC (' ');
114       if (TYPE_VOLATILE (t))
115         OB_PUTS ("volatile");
116       if (p == after) OB_PUTC (' ');
117     }
118 }
119
120 /* This must be large enough to hold any printed integer or floating-point
121    value.  */
122 static char digit_buffer[128];
123
124 /* Dump into the obstack a human-readable equivalent of TYPE.  */
125
126 static void
127 dump_type (t, v)
128      tree t;
129      int v;                     /* verbose? */
130 {
131   if (t == NULL_TREE)
132     return;
133   
134   if (TYPE_PTRMEMFUNC_P (t))
135     goto offset_type;
136
137   switch (TREE_CODE (t))
138     {
139     case ERROR_MARK:
140       OB_PUTS ("{error}");
141       break;
142
143     case UNKNOWN_TYPE:
144       OB_PUTS ("{unknown type}");
145       break;
146
147     case TREE_LIST:
148       /* i.e. function taking no arguments */
149       if (t != void_list_node)
150         {
151           dump_type (TREE_VALUE (t), v);
152           /* Can this happen other than for default arguments? */
153           if (TREE_PURPOSE (t) && v)
154             {
155               OB_PUTS (" = ");
156               dump_expr (TREE_PURPOSE (t));
157             }
158           if (TREE_CHAIN (t))
159             {
160               if (TREE_CHAIN (t) != void_list_node)
161                 {
162                   OB_PUTC2 (',', ' ');
163                   dump_type (TREE_CHAIN (t), v);
164                 }
165             }
166           else OB_PUTS (" ...");
167         }
168       break;
169
170     case IDENTIFIER_NODE:
171       OB_PUTID (t);
172       break;
173
174     case TREE_VEC:
175       dump_type (BINFO_TYPE (t), v);
176       break;
177
178     case RECORD_TYPE:
179     case UNION_TYPE:
180     case ENUMERAL_TYPE:
181       if (TYPE_LANG_SPECIFIC (t)
182           && (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t)))
183         {
184           if (TYPE_READONLY (t) | TYPE_VOLATILE (t))
185             dump_readonly_or_volatile (t);
186           dump_type (SIGNATURE_TYPE (t), v);
187           if (IS_SIGNATURE_POINTER (t))
188             OB_PUTC ('*');
189           else
190             OB_PUTC ('&');
191         }
192       else
193         dump_aggr_type (t, v);
194       break;
195
196     case TYPE_DECL:
197       dump_decl (t, v);
198       break;
199
200     case INTEGER_TYPE:
201       if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
202         OB_PUTS ("unsigned ");
203       else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t))
204         OB_PUTS ("signed ");
205
206       /* fall through.  */
207     case REAL_TYPE:
208     case VOID_TYPE:
209     case BOOLEAN_TYPE:
210       dump_readonly_or_volatile (t, after);
211       OB_PUTID (TYPE_IDENTIFIER (t));
212       break;
213
214     case TEMPLATE_TYPE_PARM:
215       if (TYPE_IDENTIFIER (t))
216         OB_PUTID (TYPE_IDENTIFIER (t));
217       else
218         OB_PUTS ("{anonymous template type parm}");
219       break;
220
221       /* This is not always necessary for pointers and such, but doing this
222          reduces code size.  */
223     case ARRAY_TYPE:
224     case POINTER_TYPE:
225     case REFERENCE_TYPE:
226     case OFFSET_TYPE:
227     offset_type:
228     case FUNCTION_TYPE:
229     case METHOD_TYPE:
230       dump_type_prefix (t, v);
231       dump_type_suffix (t, v);
232       break;
233
234     case TYPENAME_TYPE:
235       OB_PUTS ("typename ");
236       dump_type (TYPE_CONTEXT (t), 0);
237       OB_PUTS ("::");
238       OB_PUTID (TYPE_IDENTIFIER (t));
239       break;
240
241     default:
242       sorry ("`%s' not supported by dump_type",
243              tree_code_name[(int) TREE_CODE (t)]);
244     }
245 }
246
247 static char *
248 aggr_variety (t)
249      tree t;
250 {
251   if (TREE_CODE (t) == ENUMERAL_TYPE)
252     return "enum";
253   else if (TREE_CODE (t) == UNION_TYPE)
254     return "union";
255   else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
256     return "class";
257   else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t))
258     return "signature";
259   else
260     return "struct";
261 }
262
263 /* Print out a class declaration, in the form `class foo'.  */
264
265 static void
266 dump_aggr_type (t, v)
267      tree t;
268      int v;                     /* verbose? */
269 {
270   tree name;
271   char *variety = aggr_variety (t);
272
273   dump_readonly_or_volatile (t, after);
274
275   if (v > 0)
276     {
277       OB_PUTCP (variety);
278       OB_PUTC (' ');
279     }
280   
281   name = TYPE_NAME (t);
282
283   if (name && DECL_CONTEXT (name))
284     {
285       /* FUNCTION_DECL or RECORD_TYPE */
286       dump_decl (DECL_CONTEXT (name), 0);
287       OB_PUTC2 (':', ':');
288     }
289
290   /* kludge around weird behavior on g++.brendan/line1.C */
291   if (name && TREE_CODE (name) != IDENTIFIER_NODE)
292     name = DECL_NAME (name);
293
294   if (name == 0 || ANON_AGGRNAME_P (name))
295     {
296       OB_PUTS ("{anonymous");
297       if (!v)
298         {
299           OB_PUTC (' ');
300           OB_PUTCP (variety);
301         }
302       OB_PUTC ('}');
303     }
304   else
305     OB_PUTID (name);
306 }
307
308 /* Dump into the obstack the initial part of the output for a given type.
309    This is necessary when dealing with things like functions returning
310    functions.  Examples:
311
312    return type of `int (* fee ())()': pointer -> function -> int.  Both
313    pointer (and reference and offset) and function (and member) types must
314    deal with prefix and suffix.
315
316    Arrays must also do this for DECL nodes, like int a[], and for things like
317    int *[]&.  */
318
319 static void
320 dump_type_prefix (t, v)
321      tree t;
322      int v;                     /* verbosity */
323 {
324   if (TYPE_PTRMEMFUNC_P (t))
325     {
326       t = TYPE_PTRMEMFUNC_FN_TYPE (t);
327       goto offset_type;
328     }
329   
330   switch (TREE_CODE (t))
331     {
332     case POINTER_TYPE:
333       {
334         tree sub = TREE_TYPE (t);
335         
336         dump_type_prefix (sub, v);
337         /* A tree for a member pointer looks like pointer to offset,
338            so let the OFFSET_TYPE case handle it.  */
339         if (TREE_CODE (sub) != OFFSET_TYPE)
340           {
341             switch (TREE_CODE (sub))
342               {
343                 /* We don't want int ( *)() */
344               case FUNCTION_TYPE:
345               case METHOD_TYPE:
346                 break;
347                 
348               case ARRAY_TYPE:
349                 OB_PUTC2 (' ', '(');
350                 break;
351
352               case POINTER_TYPE:
353                 /* We don't want "char * *" */
354                 if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
355                   break;
356                 /* But we do want "char *const *" */
357                 
358               default:
359                 OB_PUTC (' ');
360               }
361             OB_PUTC ('*');
362             dump_readonly_or_volatile (t, none);
363           }
364       }
365       break;
366
367     case REFERENCE_TYPE:
368       {
369         tree sub = TREE_TYPE (t);
370         dump_type_prefix (sub, v);
371
372         switch (TREE_CODE (sub))
373           {
374           case ARRAY_TYPE:
375             OB_PUTC2 (' ', '(');
376             break;
377
378           case POINTER_TYPE:
379             /* We don't want "char * &" */
380             if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
381               break;
382             /* But we do want "char *const &" */
383
384           default:
385             OB_PUTC (' ');
386           }
387       }
388       OB_PUTC ('&');
389       dump_readonly_or_volatile (t, none);
390       break;
391
392     case OFFSET_TYPE:
393     offset_type:
394       dump_type_prefix (TREE_TYPE (t), v);
395       if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */
396         {
397           OB_PUTC (' ');
398           dump_type (TYPE_OFFSET_BASETYPE (t), 0);
399           OB_PUTC2 (':', ':');
400         }
401       OB_PUTC ('*');
402       dump_readonly_or_volatile (t, none);
403       break;
404
405       /* Can only be reached through function pointer -- this would not be
406          correct if FUNCTION_DECLs used it.  */
407     case FUNCTION_TYPE:
408       dump_type_prefix (TREE_TYPE (t), v);
409       OB_PUTC2 (' ', '(');
410       break;
411
412     case METHOD_TYPE:
413       dump_type_prefix (TREE_TYPE (t), v);
414       OB_PUTC2 (' ', '(');
415       dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0);
416       OB_PUTC2 (':', ':');
417       break;
418
419     case ARRAY_TYPE:
420       dump_type_prefix (TREE_TYPE (t), v);
421       break;
422
423     case ENUMERAL_TYPE:
424     case ERROR_MARK:
425     case IDENTIFIER_NODE:
426     case INTEGER_TYPE:
427     case BOOLEAN_TYPE:
428     case REAL_TYPE:
429     case RECORD_TYPE:
430     case TEMPLATE_TYPE_PARM:
431     case TREE_LIST:
432     case TYPE_DECL:
433     case TREE_VEC:
434     case UNION_TYPE:
435     case UNKNOWN_TYPE:
436     case VOID_TYPE:
437     case TYPENAME_TYPE:
438       dump_type (t, v);
439       break;
440       
441     default:
442       sorry ("`%s' not supported by dump_type_prefix",
443              tree_code_name[(int) TREE_CODE (t)]);
444     }
445 }
446
447 static void
448 dump_type_suffix (t, v)
449      tree t;
450      int v;                     /* verbose? */
451 {
452   if (TYPE_PTRMEMFUNC_P (t))
453     t = TYPE_PTRMEMFUNC_FN_TYPE (t);
454
455   switch (TREE_CODE (t))
456     {
457     case POINTER_TYPE:
458     case REFERENCE_TYPE:
459     case OFFSET_TYPE:
460       if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
461         OB_PUTC (')');
462       dump_type_suffix (TREE_TYPE (t), v);
463       break;
464
465       /* Can only be reached through function pointer */
466     case FUNCTION_TYPE:
467     case METHOD_TYPE:
468       {
469         tree arg;
470         OB_PUTC2 (')', '(');
471         arg = TYPE_ARG_TYPES (t);
472         if (TREE_CODE (t) == METHOD_TYPE)
473           arg = TREE_CHAIN (arg);
474
475         if (arg)
476           dump_type (arg, v);
477         else
478           OB_PUTS ("...");
479         OB_PUTC (')');
480         if (TREE_CODE (t) == METHOD_TYPE)
481           dump_readonly_or_volatile
482             (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
483         dump_type_suffix (TREE_TYPE (t), v);
484         break;
485       }
486
487     case ARRAY_TYPE:
488       OB_PUTC ('[');
489       if (TYPE_DOMAIN (t))
490         {
491           if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == INTEGER_CST)
492             OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
493           else if (TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == MINUS_EXPR)
494             dump_expr (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0), 0);
495           else
496             dump_expr (fold (build_binary_op
497                              (PLUS_EXPR, TYPE_MAX_VALUE (TYPE_DOMAIN (t)),
498                               integer_one_node, 1)), 0);
499         }
500       OB_PUTC (']');
501       dump_type_suffix (TREE_TYPE (t), v);
502       break;
503       
504     case ENUMERAL_TYPE:
505     case ERROR_MARK:
506     case IDENTIFIER_NODE:
507     case INTEGER_TYPE:
508     case BOOLEAN_TYPE:
509     case REAL_TYPE:
510     case RECORD_TYPE:
511     case TEMPLATE_TYPE_PARM:
512     case TREE_LIST:
513     case TYPE_DECL:
514     case TREE_VEC:
515     case UNION_TYPE:
516     case UNKNOWN_TYPE:
517     case VOID_TYPE:
518     case TYPENAME_TYPE:
519       break;
520
521     default:
522       sorry ("`%s' not supported by dump_type_suffix",
523              tree_code_name[(int) TREE_CODE (t)]);
524     }
525 }
526
527 /* Return a function declaration which corresponds to the IDENTIFIER_NODE
528    argument.  */
529
530 tree
531 ident_fndecl (t)
532      tree t;
533 {
534   tree n = lookup_name (t, 0);
535
536   if (n == NULL_TREE)
537     return NULL_TREE;
538
539   if (TREE_CODE (n) == FUNCTION_DECL)
540     return n;
541   else if (TREE_CODE (n) == TREE_LIST
542            && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
543     return TREE_VALUE (n);
544
545   my_friendly_abort (66);
546   return NULL_TREE;
547 }
548
549 #ifndef NO_DOLLAR_IN_LABEL
550 #  define GLOBAL_THING "_GLOBAL_$"
551 #else
552 #  ifndef NO_DOT_IN_LABEL
553 #    define GLOBAL_THING "_GLOBAL_."
554 #  else
555 #    define GLOBAL_THING "_GLOBAL__"
556 #  endif
557 #endif
558
559 #define GLOBAL_IORD_P(NODE) \
560   ! strncmp (IDENTIFIER_POINTER(NODE), GLOBAL_THING, sizeof (GLOBAL_THING) - 1)
561
562 void
563 dump_global_iord (t)
564      tree t;
565 {
566   char *name = IDENTIFIER_POINTER (t);
567
568   OB_PUTS ("(static ");
569   if (name [sizeof (GLOBAL_THING) - 1] == 'I')
570     OB_PUTS ("initializers");
571   else if (name [sizeof (GLOBAL_THING) - 1] == 'D')
572     OB_PUTS ("destructors");
573   else
574     my_friendly_abort (352);
575   
576   OB_PUTS (" for ");
577   OB_PUTCP (input_filename);
578   OB_PUTC (')');
579 }
580
581 static void
582 dump_decl (t, v)
583      tree t;
584      int v;                     /* verbosity */
585 {
586   if (t == NULL_TREE)
587     return;
588
589   switch (TREE_CODE (t))
590     {
591     case ERROR_MARK:
592       OB_PUTS (" /* decl error */ ");
593       break;
594
595     case TYPE_DECL:
596       {
597         /* Don't say 'typedef class A' */
598         if (DECL_ARTIFICIAL (t))
599           {
600             dump_type (TREE_TYPE (t), v);
601             break;
602           }
603       }
604       if (v > 0)
605         OB_PUTS ("typedef ");
606       goto general;
607       break;
608       
609     case VAR_DECL:
610       if (DECL_NAME (t) && VTABLE_NAME_P (DECL_NAME (t)))
611         {
612           OB_PUTS ("vtable for ");
613           dump_type (DECL_CONTEXT (t), v);
614           break;
615         }
616       /* else fall through */
617     case FIELD_DECL:
618     case PARM_DECL:
619     general:
620       if (v > 0)
621         {
622           dump_type_prefix (TREE_TYPE (t), v);
623           OB_PUTC (' ');
624           dump_readonly_or_volatile (t, after);
625         }
626       /* DECL_CLASS_CONTEXT isn't being set in some cases.  Hmm...  */
627       if (DECL_CONTEXT (t)
628           && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't')
629         {
630           dump_type (DECL_CONTEXT (t), 0);
631           OB_PUTC2 (':', ':');
632         }
633       if (DECL_NAME (t))
634         dump_decl (DECL_NAME (t), v);
635       else
636         OB_PUTS ("{anon}");
637       if (v > 0)
638         dump_type_suffix (TREE_TYPE (t), v);
639       break;
640
641     case NAMESPACE_DECL:
642       OB_PUTID (DECL_NAME (t));
643       break;
644
645     case ARRAY_REF:
646       dump_decl (TREE_OPERAND (t, 0), v);
647       OB_PUTC ('[');
648       dump_decl (TREE_OPERAND (t, 1), v);
649       OB_PUTC (']');
650       break;
651
652       /* So that we can do dump_decl in dump_aggr_type and have it work for
653          both class and function scope.  */
654     case RECORD_TYPE:
655     case UNION_TYPE:
656     case ENUMERAL_TYPE:
657       dump_type (t, v);
658       break;
659
660     case TYPE_EXPR:
661       my_friendly_abort (69);
662       break;
663
664       /* These special cases are duplicated here so that other functions
665          can feed identifiers to cp_error and get them demangled properly.  */
666     case IDENTIFIER_NODE:
667       { tree f;
668         if (DESTRUCTOR_NAME_P (t)
669             && (f = ident_fndecl (t))
670             && DECL_LANGUAGE (f) == lang_cplusplus)
671           {
672             OB_PUTC ('~');
673             dump_decl (DECL_NAME (f), 0);
674           }
675         else if (IDENTIFIER_TYPENAME_P (t))
676           {
677             OB_PUTS ("operator ");
678             /* Not exactly IDENTIFIER_TYPE_VALUE.  */
679             dump_type (TREE_TYPE (t), 0);
680             break;
681           }
682         else if (IDENTIFIER_OPNAME_P (t))
683           {
684             char *name_string = operator_name_string (t);
685             OB_PUTS ("operator ");
686             OB_PUTCP (name_string);
687           }
688         else
689           OB_PUTID (t);
690       }
691       break;
692
693     case FUNCTION_DECL:
694       if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
695         dump_global_iord (DECL_ASSEMBLER_NAME (t));
696       else
697         dump_function_decl (t, v);
698       break;
699
700     case TEMPLATE_DECL:
701       {
702         tree args = DECL_TEMPLATE_PARMS (t);
703         int i, len = args ? TREE_VEC_LENGTH (args) : 0;
704         OB_PUTS ("template <");
705         for (i = 0; i < len; i++)
706           {
707             tree arg = TREE_VEC_ELT (args, i);
708             tree defval = TREE_PURPOSE (arg);
709             arg = TREE_VALUE (arg);
710             if (TREE_CODE (arg) == TYPE_DECL)
711               {
712                 OB_PUTS ("class ");
713                 OB_PUTID (DECL_NAME (arg));
714               }
715             else
716               dump_decl (arg, 1);
717
718             if (defval)
719               {
720                 OB_PUTS (" = ");
721                 dump_decl (defval, 1);
722               }
723                 
724             OB_PUTC2 (',', ' ');
725           }
726         if (len != 0)
727           OB_UNPUT (2);
728         OB_PUTC2 ('>', ' ');
729
730         if (TREE_CODE (DECL_TEMPLATE_RESULT (t)) == TYPE_DECL)
731           dump_type (TREE_TYPE (t), v);
732         else if (TREE_TYPE (t) == NULL_TREE)
733            my_friendly_abort (353);
734         else switch (NEXT_CODE (t))
735           {
736           case METHOD_TYPE:
737           case FUNCTION_TYPE:
738             dump_function_decl (t, v);
739             break;
740
741           default:
742             my_friendly_abort (353);
743           }
744       }
745       break;
746
747     case LABEL_DECL:
748       OB_PUTID (DECL_NAME (t));
749       break;
750
751     case CONST_DECL:
752       if ((TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == ENUMERAL_TYPE)
753           || TREE_CODE (DECL_INITIAL (t)) == TEMPLATE_CONST_PARM)
754         goto general;
755       else
756         dump_expr (DECL_INITIAL (t), 0);
757       break;
758
759     case USING_DECL:
760       OB_PUTS ("using ");
761       dump_type (DECL_INITIAL (t), 0);
762       OB_PUTS ("::");
763       OB_PUTID (DECL_NAME (t));
764       break;
765
766     default:
767       sorry ("`%s' not supported by dump_decl",
768              tree_code_name[(int) TREE_CODE (t)]);
769     }
770 }
771
772 /* Pretty printing for announce_function.  T is the declaration of the
773    function we are interested in seeing.  V is non-zero if we should print
774    the type that this function returns.  */
775
776 static void
777 dump_function_decl (t, v)
778      tree t;
779      int v;
780 {
781   tree name = DECL_ASSEMBLER_NAME (t);
782   tree fntype = TREE_TYPE (t);
783   tree parmtypes = TYPE_ARG_TYPES (fntype);
784   tree cname = NULL_TREE;
785
786   /* Friends have DECL_CLASS_CONTEXT set, but not DECL_CONTEXT.  */
787   if (DECL_CONTEXT (t))
788     cname = DECL_CLASS_CONTEXT (t);
789   /* this is for partially instantiated template methods */
790   else if (TREE_CODE (fntype) == METHOD_TYPE)
791     cname = TREE_TYPE (TREE_VALUE (parmtypes));
792
793   v = (v > 0);
794   
795   if (v)
796     {
797       if (DECL_STATIC_FUNCTION_P (t))
798         OB_PUTS ("static ");
799     
800       if (! IDENTIFIER_TYPENAME_P (name)
801           && ! DECL_CONSTRUCTOR_P (t)
802           && ! DESTRUCTOR_NAME_P (name))
803         {
804           dump_type_prefix (TREE_TYPE (fntype), 1);
805           OB_PUTC (' ');
806         }
807     }
808
809   if (cname)
810     {
811       dump_type (cname, 0);
812       OB_PUTC2 (':', ':');
813       if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
814         parmtypes = TREE_CHAIN (parmtypes);
815       if (DECL_CONSTRUCTOR_FOR_VBASE_P (t))
816         /* Skip past "in_charge" identifier.  */
817         parmtypes = TREE_CHAIN (parmtypes);
818     }
819
820   if (DESTRUCTOR_NAME_P (name) && DECL_LANGUAGE (t) == lang_cplusplus)
821     parmtypes = TREE_CHAIN (parmtypes);
822   
823   dump_function_name (t);
824   
825   OB_PUTC ('(');
826
827   if (parmtypes)
828     dump_type (parmtypes, v);
829   else
830     OB_PUTS ("...");
831
832   OB_PUTC (')');
833
834   if (v && ! IDENTIFIER_TYPENAME_P (name))
835     dump_type_suffix (TREE_TYPE (fntype), 1);
836
837   if (TREE_CODE (fntype) == METHOD_TYPE)
838     {
839       if (IS_SIGNATURE (cname))
840         /* We look at the type pointed to by the `optr' field of `this.'  */
841         dump_readonly_or_volatile
842           (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (TREE_VALUE (TYPE_ARG_TYPES (fntype))))), before);
843       else
844         dump_readonly_or_volatile
845           (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
846     }
847 }
848
849 /* Handle the function name for a FUNCTION_DECL node, grokking operators
850    and destructors properly.  */
851
852 static void
853 dump_function_name (t)
854      tree t;
855 {
856   tree name = DECL_NAME (t);
857
858   /* There ought to be a better way to find out whether or not something is
859      a destructor.  */
860   if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t))
861       && DECL_LANGUAGE (t) == lang_cplusplus)
862     {
863       OB_PUTC ('~');
864       dump_decl (name, 0);
865     }
866   else if (IDENTIFIER_TYPENAME_P (name))
867     {
868       /* This cannot use the hack that the operator's return
869          type is stashed off of its name because it may be
870          used for error reporting.  In the case of conflicting
871          declarations, both will have the same name, yet
872          the types will be different, hence the TREE_TYPE field
873          of the first name will be clobbered by the second.  */
874       OB_PUTS ("operator ");
875       dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
876     }
877   else if (IDENTIFIER_OPNAME_P (name))
878     {
879       char *name_string = operator_name_string (name);
880       OB_PUTS ("operator ");
881       OB_PUTCP (name_string);
882     }
883   else
884     dump_decl (name, 0);
885 }
886
887 static void
888 dump_char (c)
889      char c;
890 {
891   switch (c)
892     {
893     case TARGET_NEWLINE:
894       OB_PUTS ("\\n");
895       break;
896     case TARGET_TAB:
897       OB_PUTS ("\\t");
898       break;
899     case TARGET_VT:
900       OB_PUTS ("\\v");
901       break;
902     case TARGET_BS:
903       OB_PUTS ("\\b");
904       break;
905     case TARGET_CR:
906       OB_PUTS ("\\r");
907       break;
908     case TARGET_FF:
909       OB_PUTS ("\\f");
910       break;
911     case TARGET_BELL:
912       OB_PUTS ("\\a");
913       break;
914     case '\\':
915       OB_PUTS ("\\\\");
916       break;
917     case '\'':
918       OB_PUTS ("\\'");
919       break;
920     case '\"':
921       OB_PUTS ("\\\"");
922       break;
923     default:
924       if (isprint (c))
925         OB_PUTC (c);
926       else
927         {
928           sprintf (digit_buffer, "\\%03o", (int) c);
929           OB_PUTCP (digit_buffer);
930         }
931     }
932 }
933
934 /* Print out a list of initializers (subr of dump_expr) */
935
936 static void
937 dump_expr_list (l)
938      tree l;
939 {
940   while (l)
941     {
942       dump_expr (TREE_VALUE (l), 0);
943       if (TREE_CHAIN (l))
944         OB_PUTC2 (',', ' ');
945       l = TREE_CHAIN (l);
946     }
947 }
948
949 /* Print out an expression */
950
951 static void
952 dump_expr (t, nop)
953      tree t;
954      int nop;                   /* suppress parens */
955 {
956   switch (TREE_CODE (t))
957     {
958     case VAR_DECL:
959     case PARM_DECL:
960     case FIELD_DECL:
961     case CONST_DECL:
962     case FUNCTION_DECL:
963     case TEMPLATE_DECL:
964       dump_decl (t, -1);
965       break;
966
967     case INTEGER_CST:
968       {
969         tree type = TREE_TYPE (t);
970         my_friendly_assert (type != 0, 81);
971
972         /* If it's an enum, output its tag, rather than its value.  */
973         if (TREE_CODE (type) == ENUMERAL_TYPE)
974           {
975             char *p = enum_name_string (t, type);
976             OB_PUTCP (p);
977           }
978         else if (type == boolean_type_node)
979           {
980             if (t == boolean_false_node
981                 || (TREE_INT_CST_LOW (t) == 0
982                     && TREE_INT_CST_HIGH (t) == 0))
983               OB_PUTS ("false");
984             else if (t == boolean_true_node)
985               OB_PUTS ("true");
986           }
987         else if (type == char_type_node)
988           {
989             OB_PUTC ('\'');
990             dump_char (TREE_INT_CST_LOW (t));
991             OB_PUTC ('\'');
992           }
993         else if (TREE_INT_CST_HIGH (t)
994                  != (TREE_INT_CST_LOW (t) >> (HOST_BITS_PER_WIDE_INT - 1)))
995           {
996             tree val = t;
997             if (TREE_INT_CST_HIGH (val) < 0)
998               {
999                 OB_PUTC ('-');
1000                 val = build_int_2 (~TREE_INT_CST_LOW (val),
1001                                    -TREE_INT_CST_HIGH (val));
1002               }
1003             /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
1004                systems?  */
1005             {
1006               static char format[10]; /* "%x%09999x\0" */
1007               if (!format[0])
1008                 sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
1009               sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
1010                        TREE_INT_CST_LOW (val));
1011               OB_PUTCP (digit_buffer);
1012             }
1013           }
1014         else
1015           OB_PUTI (TREE_INT_CST_LOW (t));
1016       }
1017       break;
1018
1019     case REAL_CST:
1020 #ifndef REAL_IS_NOT_DOUBLE
1021       sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
1022 #else
1023       {
1024         unsigned char *p = (unsigned char *) &TREE_REAL_CST (t);
1025         int i;
1026         strcpy (digit_buffer, "0x");
1027         for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
1028           sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
1029       }
1030 #endif
1031       OB_PUTCP (digit_buffer);
1032       break;
1033
1034     case STRING_CST:
1035       {
1036         char *p = TREE_STRING_POINTER (t);
1037         int len = TREE_STRING_LENGTH (t) - 1;
1038         int i;
1039
1040         OB_PUTC ('\"');
1041         for (i = 0; i < len; i++)
1042           dump_char (p[i]);
1043         OB_PUTC ('\"');
1044       }
1045       break;
1046
1047     case COMPOUND_EXPR:
1048       dump_binary_op (",", t);
1049       break;
1050
1051     case COND_EXPR:
1052       OB_PUTC ('(');
1053       dump_expr (TREE_OPERAND (t, 0), 0);
1054       OB_PUTS (" ? ");
1055       dump_expr (TREE_OPERAND (t, 1), 0);
1056       OB_PUTS (" : ");
1057       dump_expr (TREE_OPERAND (t, 2), 0);
1058       OB_PUTC (')');
1059       break;
1060
1061     case SAVE_EXPR:
1062       if (TREE_HAS_CONSTRUCTOR (t))
1063         {
1064           OB_PUTS ("new ");
1065           dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
1066           PARM_DECL_EXPR (t) = 1;
1067         }
1068       else
1069         {
1070           dump_expr (TREE_OPERAND (t, 0), 0);
1071         }
1072       break;
1073
1074     case NEW_EXPR:
1075       OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
1076       OB_PUTC ('(');
1077       dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
1078       OB_PUTC (')');
1079       break;
1080
1081     case CALL_EXPR:
1082       {
1083         tree fn = TREE_OPERAND (t, 0);
1084         tree args = TREE_OPERAND (t, 1);
1085         
1086         if (TREE_CODE (fn) == ADDR_EXPR)
1087           fn = TREE_OPERAND (fn, 0);
1088
1089         if (TREE_TYPE (fn) != NULL_TREE && NEXT_CODE (fn) == METHOD_TYPE)
1090           {
1091             tree ob = TREE_VALUE (args);
1092             if (TREE_CODE (ob) == ADDR_EXPR)
1093               {
1094                 dump_expr (TREE_OPERAND (ob, 0), 0);
1095                 OB_PUTC ('.');
1096               }
1097             else if (TREE_CODE (ob) != PARM_DECL
1098                      || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1099               {
1100                 dump_expr (ob, 0);
1101                 OB_PUTC2 ('-', '>');
1102               }
1103             args = TREE_CHAIN (args);
1104           }
1105         dump_expr (fn, 0);
1106         OB_PUTC ('(');
1107         dump_expr_list (args);
1108         OB_PUTC (')');
1109       }
1110       break;
1111
1112     case TARGET_EXPR:
1113       /* Note that this only works for G++ target exprs.  If somebody
1114          builds a general TARGET_EXPR, there's no way to represent that
1115          it initializes anything other that the parameter slot for the
1116          default argument.  Note we may have cleared out the first
1117          operand in expand_expr, so don't go killing ourselves.  */
1118       if (TREE_OPERAND (t, 1))
1119         dump_expr (TREE_OPERAND (t, 1), 0);
1120       break;
1121
1122     case MODIFY_EXPR:
1123     case PLUS_EXPR:
1124     case MINUS_EXPR:
1125     case MULT_EXPR:
1126     case TRUNC_DIV_EXPR:
1127     case TRUNC_MOD_EXPR:
1128     case MIN_EXPR:
1129     case MAX_EXPR:
1130     case LSHIFT_EXPR:
1131     case RSHIFT_EXPR:
1132     case BIT_IOR_EXPR:
1133     case BIT_XOR_EXPR:
1134     case BIT_AND_EXPR:
1135     case BIT_ANDTC_EXPR:
1136     case TRUTH_ANDIF_EXPR:
1137     case TRUTH_ORIF_EXPR:
1138     case LT_EXPR:
1139     case LE_EXPR:
1140     case GT_EXPR:
1141     case GE_EXPR:
1142     case EQ_EXPR:
1143     case NE_EXPR:
1144       dump_binary_op (opname_tab[(int) TREE_CODE (t)], t);
1145       break;
1146
1147     case CEIL_DIV_EXPR:
1148     case FLOOR_DIV_EXPR:
1149     case ROUND_DIV_EXPR:
1150       dump_binary_op ("/", t);
1151       break;
1152
1153     case CEIL_MOD_EXPR:
1154     case FLOOR_MOD_EXPR:
1155     case ROUND_MOD_EXPR:
1156       dump_binary_op ("%", t);
1157       break;
1158
1159     case COMPONENT_REF:
1160       {
1161         tree ob = TREE_OPERAND (t, 0);
1162         if (TREE_CODE (ob) == INDIRECT_REF)
1163           {
1164             ob = TREE_OPERAND (ob, 0);
1165             if (TREE_CODE (ob) != PARM_DECL
1166                 || strcmp (IDENTIFIER_POINTER (DECL_NAME (ob)), "this"))
1167               {
1168                 dump_expr (ob, 0);
1169                 OB_PUTC2 ('-', '>');
1170               }
1171           }
1172         else
1173           {
1174             dump_expr (ob, 0);
1175             OB_PUTC ('.');
1176           }
1177         dump_expr (TREE_OPERAND (t, 1), 1);
1178       }
1179       break;
1180
1181     case ARRAY_REF:
1182       dump_expr (TREE_OPERAND (t, 0), 0);
1183       OB_PUTC ('[');
1184       dump_expr (TREE_OPERAND (t, 1), 0);
1185       OB_PUTC (']');
1186       break;
1187
1188     case CONVERT_EXPR:
1189       dump_unary_op ("+", t, nop);
1190       break;
1191
1192     case ADDR_EXPR:
1193       if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
1194           || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
1195         dump_expr (TREE_OPERAND (t, 0), 0);
1196       else
1197         dump_unary_op ("&", t, nop);
1198       break;
1199
1200     case INDIRECT_REF:
1201       if (TREE_HAS_CONSTRUCTOR (t))
1202         {
1203           t = TREE_OPERAND (t, 0);
1204           my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
1205           dump_expr (TREE_OPERAND (t, 0), 0);
1206           OB_PUTC ('(');
1207           dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
1208           OB_PUTC (')');
1209         }
1210       else
1211         {
1212           if (TREE_OPERAND (t,0) != NULL_TREE
1213               && NEXT_CODE (TREE_OPERAND (t, 0)) == REFERENCE_TYPE)
1214             dump_expr (TREE_OPERAND (t, 0), nop);
1215           else
1216             dump_unary_op ("*", t, nop);
1217         }
1218       break;
1219
1220     case NEGATE_EXPR:
1221     case BIT_NOT_EXPR:
1222     case TRUTH_NOT_EXPR:
1223     case PREDECREMENT_EXPR:
1224     case PREINCREMENT_EXPR:
1225       dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, nop);
1226       break;
1227
1228     case POSTDECREMENT_EXPR:
1229     case POSTINCREMENT_EXPR:
1230       OB_PUTC ('(');
1231       dump_expr (TREE_OPERAND (t, 0), 0);
1232       OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
1233       OB_PUTC (')');
1234       break;
1235
1236     case NON_LVALUE_EXPR:
1237       /* FIXME: This is a KLUDGE workaround for a parsing problem.  There
1238          should be another level of INDIRECT_REF so that I don't have to do
1239          this.  */
1240       if (TREE_TYPE (t) != NULL_TREE && NEXT_CODE (t) == POINTER_TYPE)
1241         {
1242           tree next = TREE_TYPE (TREE_TYPE (t));
1243
1244           while (TREE_CODE (next) == POINTER_TYPE)
1245             next = TREE_TYPE (next);
1246           
1247           if (TREE_CODE (next) == FUNCTION_TYPE)
1248             {
1249               if (!nop) OB_PUTC ('(');
1250               OB_PUTC ('*');
1251               dump_expr (TREE_OPERAND (t, 0), 1);
1252               if (!nop) OB_PUTC (')');
1253               break;
1254             }
1255           /* else FALLTHRU */
1256         }
1257       dump_expr (TREE_OPERAND (t, 0), 0);
1258       break;
1259
1260     case NOP_EXPR:
1261       dump_expr (TREE_OPERAND (t, 0), nop);
1262       break;
1263
1264     case CONSTRUCTOR:
1265       if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t)))
1266         {
1267           tree idx = build_component_ref (t, index_identifier, NULL_TREE, 0);
1268
1269           if (integer_all_onesp (idx))
1270             {
1271               tree pfn = PFN_FROM_PTRMEMFUNC (t);
1272               dump_expr (pfn);
1273               break;
1274             }
1275           if (TREE_CODE (idx) == INTEGER_CST
1276               && TREE_INT_CST_HIGH (idx) == 0)
1277             {
1278               tree virtuals;
1279               unsigned HOST_WIDE_INT n;
1280
1281               t = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t)));
1282               t = TYPE_METHOD_BASETYPE (t);
1283               virtuals = BINFO_VIRTUALS (TYPE_BINFO (TYPE_MAIN_VARIANT (t)));
1284               
1285               n = TREE_INT_CST_LOW (idx);
1286
1287               /* Map vtable index back one, to allow for the null pointer to
1288                  member.  */
1289               --n;
1290
1291               while (n > 0 && virtuals)
1292                 {
1293                   --n;
1294                   virtuals = TREE_CHAIN (virtuals);
1295                 }
1296               if (virtuals)
1297                 {
1298                   dump_expr (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)));
1299                   break;
1300                 }
1301             }
1302         }
1303       OB_PUTC ('{');
1304       dump_expr_list (CONSTRUCTOR_ELTS (t));
1305       OB_PUTC ('}');
1306       break;
1307
1308     case OFFSET_REF:
1309       {
1310         tree ob = TREE_OPERAND (t, 0);
1311         if (TREE_CODE (ob) == NOP_EXPR
1312             && TREE_OPERAND (ob, 0) == error_mark_node
1313             && TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
1314             /* A::f */
1315           dump_expr (TREE_OPERAND (t, 1), 0);
1316         else
1317           {
1318             dump_expr (TREE_OPERAND (t, 0), 0);
1319             OB_PUTS (" .* ");
1320             dump_expr (TREE_OPERAND (t, 1), 0);
1321           }
1322         break;
1323       }
1324
1325     case TEMPLATE_CONST_PARM:
1326       {
1327         tree r = TREE_VEC_ELT (TREE_VALUE (current_template_parms),
1328                                TEMPLATE_CONST_IDX (t));
1329         dump_decl (TREE_VALUE (r), -1);
1330         break;
1331       }
1332
1333     case IDENTIFIER_NODE:
1334       OB_PUTID (t);
1335       break;
1336
1337     case SCOPE_REF:
1338       dump_type (TREE_OPERAND (t, 0), 0);
1339       OB_PUTS ("::");
1340       dump_expr (TREE_OPERAND (t, 1), 0);
1341       break;
1342
1343     case CAST_EXPR:
1344       if (TREE_OPERAND (t, 0) == NULL_TREE
1345           || TREE_CHAIN (TREE_OPERAND (t, 0)))
1346         {
1347           dump_type (TREE_TYPE (t), 0);
1348           OB_PUTC ('(');
1349           dump_expr_list (TREE_OPERAND (t, 0));
1350           OB_PUTC (')');
1351         }
1352       else
1353         {
1354           OB_PUTC ('(');
1355           dump_type (TREE_TYPE (t), 0);
1356           OB_PUTC (')');
1357           OB_PUTC ('(');
1358           dump_expr_list (TREE_OPERAND (t, 0));
1359           OB_PUTC (')');
1360         }
1361       break;
1362
1363     case LOOKUP_EXPR:
1364       OB_PUTID (TREE_OPERAND (t, 0));
1365       break;
1366
1367     case SIZEOF_EXPR:
1368       OB_PUTS ("sizeof (");
1369       if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t, 0))) == 't')
1370         dump_type (TREE_OPERAND (t, 0), 0);
1371       else
1372         dump_unary_op ("*", t, 0);
1373       OB_PUTC (')');
1374       break;
1375
1376     case TREE_LIST:
1377       if (TREE_VALUE (t) && TREE_CODE (TREE_VALUE (t)) == FUNCTION_DECL)
1378         {
1379           OB_PUTID (DECL_NAME (TREE_VALUE (t)));
1380           break;
1381         }
1382       /* else fall through */   
1383
1384       /*  This list is incomplete, but should suffice for now.
1385           It is very important that `sorry' does not call
1386           `report_error_function'.  That could cause an infinite loop.  */
1387     default:
1388       sorry ("`%s' not supported by dump_expr",
1389              tree_code_name[(int) TREE_CODE (t)]);
1390
1391       /* fall through to ERROR_MARK...  */
1392     case ERROR_MARK:
1393     error:
1394       OB_PUTCP ("{error}");
1395       break;
1396     }
1397 }
1398
1399 static void
1400 dump_binary_op (opstring, t)
1401      char *opstring;
1402      tree t;
1403 {
1404   OB_PUTC ('(');
1405   dump_expr (TREE_OPERAND (t, 0), 1);
1406   OB_PUTC (' ');
1407   OB_PUTCP (opstring);
1408   OB_PUTC (' ');
1409   dump_expr (TREE_OPERAND (t, 1), 1);
1410   OB_PUTC (')');
1411 }
1412
1413 static void
1414 dump_unary_op (opstring, t, nop)
1415      char *opstring;
1416      tree t;
1417      int nop;
1418 {
1419   if (!nop) OB_PUTC ('(');
1420   OB_PUTCP (opstring);
1421   dump_expr (TREE_OPERAND (t, 0), 1);
1422   if (!nop) OB_PUTC (')');
1423 }
1424
1425 char *
1426 fndecl_as_string (fndecl, print_ret_type_p)
1427      tree fndecl;
1428      int print_ret_type_p;
1429 {
1430   return decl_as_string (fndecl, print_ret_type_p);
1431 }
1432
1433 /* Same, but handtype a _TYPE.
1434    Called from convert_to_reference, mangle_class_name_for_template,
1435    build_unary_op, and GNU_xref_decl.  */
1436
1437 char *
1438 type_as_string (typ, v)
1439      tree typ;
1440      int v;
1441 {
1442   OB_INIT ();
1443
1444   dump_type (typ, v);
1445
1446   OB_FINISH ();
1447
1448   return (char *)obstack_base (&scratch_obstack);
1449 }
1450
1451 char *
1452 expr_as_string (decl, v)
1453      tree decl;
1454      int v;
1455 {
1456   OB_INIT ();
1457
1458   dump_expr (decl, 1);
1459
1460   OB_FINISH ();
1461
1462   return (char *)obstack_base (&scratch_obstack);
1463 }
1464
1465 /* A cross between type_as_string and fndecl_as_string.
1466    Only called from substitute_nice_name.  */
1467
1468 char *
1469 decl_as_string (decl, v)
1470      tree decl;
1471      int v;
1472 {
1473   OB_INIT ();
1474
1475   dump_decl (decl, v);
1476
1477   OB_FINISH ();
1478
1479   return (char *)obstack_base (&scratch_obstack);
1480 }
1481
1482 char *
1483 cp_file_of (t)
1484      tree t;
1485 {
1486   if (TREE_CODE (t) == PARM_DECL)
1487     return DECL_SOURCE_FILE (DECL_CONTEXT (t));
1488   else if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
1489     return DECL_SOURCE_FILE (TYPE_MAIN_DECL (t));
1490   else
1491     return DECL_SOURCE_FILE (t);
1492 }
1493
1494 int
1495 cp_line_of (t)
1496      tree t;
1497 {
1498   int line = 0;
1499   if (TREE_CODE (t) == PARM_DECL)
1500     line = DECL_SOURCE_LINE (DECL_CONTEXT (t));
1501   if (TREE_CODE (t) == TYPE_DECL && DECL_ARTIFICIAL (t))
1502     t = TREE_TYPE (t);
1503
1504   if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
1505     line = DECL_SOURCE_LINE (TYPE_MAIN_DECL (t));
1506   else
1507     line = DECL_SOURCE_LINE (t);
1508
1509   if (line == 0)
1510     return lineno;
1511
1512   return line;
1513 }
1514
1515 char *
1516 code_as_string (c, v)
1517      enum tree_code c;
1518      int v;
1519 {
1520   return tree_code_name [c];
1521 }
1522
1523 char *
1524 language_as_string (c, v)
1525      enum languages c;
1526      int v;
1527 {
1528   switch (c)
1529     {
1530     case lang_c:
1531       return "C";
1532
1533     case lang_cplusplus:
1534       return "C++";
1535
1536     default:
1537       my_friendly_abort (355);
1538       return 0;
1539     }
1540 }
1541
1542 /* Return the proper printed version of a parameter to a C++ function.  */
1543
1544 char *
1545 parm_as_string (p, v)
1546      int p, v;
1547 {
1548   if (p < 0)
1549     return "`this'";
1550
1551   sprintf (digit_buffer, "%d", p+1);
1552   return digit_buffer;
1553 }
1554
1555 char *
1556 op_as_string (p, v)
1557      enum tree_code p;
1558      int v;
1559 {
1560   static char buf[] = "operator                ";
1561
1562   if (p == 0)
1563     return "{unknown}";
1564   
1565   strcpy (buf + 9, opname_tab [p]);
1566   return buf;
1567 }
1568
1569 char *
1570 assop_as_string (p, v)
1571      enum tree_code p;
1572      int v;
1573 {
1574   static char buf[] = "operator                ";
1575
1576   if (p == 0)
1577     return "{unknown}";
1578   
1579   strcpy (buf + 9, assignop_tab [p]);
1580   return buf;
1581 }
1582
1583 char *
1584 args_as_string (p, v)
1585      tree p;
1586      int v;
1587 {
1588   if (p == NULL_TREE)
1589     return "";
1590
1591   if (TREE_CODE_CLASS (TREE_CODE (TREE_VALUE (p))) == 't')
1592     return type_as_string (p, v);
1593
1594   OB_INIT ();
1595   for (; p; p = TREE_CHAIN (p))
1596     {
1597       dump_type (error_type (TREE_VALUE (p)), v);
1598       if (TREE_CHAIN (p))
1599         OB_PUTS (", ");
1600     }
1601   OB_FINISH ();
1602   return (char *)obstack_base (&scratch_obstack);
1603 }
1604
1605 char *
1606 cv_as_string (p, v)
1607      tree p;
1608      int v;
1609 {
1610   OB_INIT ();
1611
1612   dump_readonly_or_volatile (p, before);
1613
1614   OB_FINISH ();
1615
1616   return (char *)obstack_base (&scratch_obstack);
1617 }