|
|
1.1 root 1: /* Call-backs for C++ error reporting.
2: This code is non-reentrant.
3: Copyright (C) 1993 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, 675 Mass Ave, Cambridge, MA 02139, USA. */
20:
21: #include "config.h"
22: #include "tree.h"
23: #include "cp-tree.h"
24: #include "obstack.h"
25: #include <ctype.h>
26: #ifdef OBJCPLUS
27: #include "objc-act.h"
28: #endif
29:
30: typedef char* cp_printer ();
31:
32: #define C code_as_string
33: #define D decl_as_string
34: #define E expr_as_string
35: #define L language_as_string
36: #define T type_as_string
37:
38: #define _ (cp_printer *) 0
39: cp_printer * cp_printers[256] =
40: {
41: /*0 1 2 3 4 5 6 7 8 9 A B C D E F */
42: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */
43: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */
44: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
45: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
46: _, _, _, C, D, E, _, _, _, _, _, _, L, _, _, _, /* 0x40 */
47: _, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */
48: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
49: _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
50: };
51: #undef C
52: #undef D
53: #undef E
54: #undef L
55: #undef T
56: #undef _
57:
58: #define obstack_chunk_alloc xmalloc
59: #define obstack_chunk_free free
60:
61: /* Obstack where we build text strings for overloading, etc. */
62: static struct obstack scratch_obstack;
63: static char *scratch_firstobj;
64:
65: # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
66: # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
67: # define OB_PUTC2(C1,C2) \
68: (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
69: # define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
70: # define OB_PUTID(ID) \
71: (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \
72: IDENTIFIER_LENGTH (ID)))
73: # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
74: # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
75: # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
76: OB_PUTCP (digit_buffer); } while (0)
77:
78: # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
79:
80: static void dump_type (), dump_decl (), dump_function_decl ();
81: static void dump_expr (), dump_unary_op (), dump_binary_op ();
82: static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix ();
83: static void dump_function_name ();
84:
85: void
86: init_error ()
87: {
88: gcc_obstack_init (&scratch_obstack);
89: scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
90: }
91:
92: /* Counter to help build parameter names in case they were omitted. */
93: static int dummy_name;
94:
95: enum pad { none, before, after };
96:
97: static void
98: dump_readonly_or_volatile (t, p)
99: tree t;
100: enum pad p;
101: {
102: if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
103: {
104: if (p == before) OB_PUTC (' ');
105: if (TYPE_READONLY (t))
106: OB_PUTS ("const");
107: if (TYPE_VOLATILE (t))
108: OB_PUTS ("volatile");
109: if (p == after) OB_PUTC (' ');
110: }
111: }
112:
113: /* This must be large enough to hold any printed integer or floating-point
114: value. */
115: static char digit_buffer[128];
116:
117: /* Dump into the obstack a human-readable equivalent of TYPE. */
118: static void
119: dump_type (t, v)
120: tree t;
121: int v; /* verbose? */
122: {
123: if (t == NULL_TREE)
124: return;
125:
126: if (TYPE_PTRMEMFUNC_P (t))
127: goto offset_type;
128:
129: switch (TREE_CODE (t))
130: {
131: case ERROR_MARK:
132: OB_PUTS ("<error>");
133: break;
134:
135: case UNKNOWN_TYPE:
136: OB_PUTS ("<unknown type>");
137: break;
138:
139: case TREE_LIST:
140: /* i.e. function taking no arguments */
141: if (t != void_list_node)
142: {
143: dump_type (TREE_VALUE (t), v);
144: /* Can this happen other than for default arguments? */
145: if (TREE_PURPOSE (t) && v)
146: {
147: OB_PUTS (" = ");
148: dump_expr (TREE_PURPOSE (t));
149: }
150: if (TREE_CHAIN (t))
151: {
152: if (TREE_CHAIN (t) != void_list_node)
153: {
154: OB_PUTC2 (',', ' ');
155: dump_type (TREE_CHAIN (t), v);
156: }
157: }
158: else OB_PUTS (" ...");
159: }
160: break;
161:
162: case IDENTIFIER_NODE:
163: OB_PUTID (t);
164: break;
165:
166: case TREE_VEC:
167: dump_type (BINFO_TYPE (t), v);
168: break;
169:
170: case RECORD_TYPE:
171: case UNION_TYPE:
172: case ENUMERAL_TYPE:
173: dump_aggr_type (t, v);
174: break;
175:
176: case TYPE_DECL:
177: dump_readonly_or_volatile (t, after);
178: OB_PUTID (DECL_NAME (t));
179: break;
180:
181: case INTEGER_TYPE:
182: if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
183: OB_PUTS ("unsigned ");
184: else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t))
185: OB_PUTS ("signed ");
186:
187: /* fall through. */
188: case REAL_TYPE:
189: case VOID_TYPE:
190: dump_readonly_or_volatile (t, after);
191: OB_PUTID (TYPE_IDENTIFIER (t));
192: break;
193:
194: case TEMPLATE_TYPE_PARM:
195: OB_PUTS ("<template type parm ");
196: OB_PUTID (TYPE_IDENTIFIER (t));
197: OB_PUTC ('>');
198: break;
199:
200: case UNINSTANTIATED_P_TYPE:
201: OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
202: OB_PUTS ("<...>");
203: break;
204:
205: /* This is not always necessary for pointers and such, but doing this
206: reduces code size. */
207: case POINTER_TYPE:
208: case ARRAY_TYPE:
209: case REFERENCE_TYPE:
210: case OFFSET_TYPE:
211: offset_type:
212: case FUNCTION_TYPE:
213: case METHOD_TYPE:
214: dump_type_prefix (t, v);
215: dump_type_suffix (t, v);
216: break;
217:
218: default:
219: my_friendly_abort (68);
220:
221: }
222: }
223:
224: /* Print out a class declaration, in the form `class foo'. */
225: static void
226: dump_aggr_type (t, v)
227: tree t;
228: int v; /* verbose? */
229: {
230: tree name;
231: char *variety;
232:
233: if (TREE_CODE (t) == ENUMERAL_TYPE)
234: variety = "enum";
235: else if (TREE_CODE (t) == UNION_TYPE)
236: variety = "union";
237: else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
238: variety = "class";
239: else
240: variety = "struct";
241:
242: dump_readonly_or_volatile (t, after);
243:
244: if (v)
245: {
246: OB_PUTCP (variety);
247: OB_PUTC (' ');
248: }
249:
250: name = TYPE_NAME (t);
251:
252: if (DECL_CONTEXT (name))
253: {
254: /* FUNCTION_DECL or RECORD_TYPE */
255: dump_decl (DECL_CONTEXT (name), 0);
256: OB_PUTC2 (':', ':');
257: }
258:
259: /* kludge around wierd behavior on g++.brendan/line1.C */
260: if (TREE_CODE (name) != IDENTIFIER_NODE)
261: name = DECL_NAME (name);
262:
263: if (ANON_AGGRNAME_P (name))
264: {
265: OB_PUTS ("<anonymous");
266: if (!v)
267: {
268: OB_PUTC (' ');
269: OB_PUTCP (variety);
270: }
271: OB_PUTC ('>');
272: }
273: else
274: OB_PUTID (name);
275: }
276:
277: /* Dump into the obstack the initial part of the output for a given type.
278: This is necessary when dealing with things like functions returning
279: functions. Examples:
280:
281: return type of `int (* fee ())()': pointer -> function -> int. Both
282: pointer (and reference and offset) and function (and member) types must
283: deal with prefix and suffix.
284:
285: Arrays must also do this for DECL nodes, like int a[], and for things like
286: int *[]&. */
287:
288: static void
289: dump_type_prefix (t, v)
290: tree t;
291: int v; /* verbosity */
292: {
293: if (TYPE_PTRMEMFUNC_P (t))
294: {
295: t = TYPE_PTRMEMFUNC_FN_TYPE (t);
296: goto offset_type;
297: }
298:
299: switch (TREE_CODE (t))
300: {
301: case POINTER_TYPE:
302: {
303: tree sub = TREE_TYPE (t);
304:
305: #if 0
306: if (doing_objc_thang)
307: {
308: static tree id_type = 0, sel_type;
309:
310: /* initialize id_type and sel_type */
311: if (!id_type)
312: {
313: tree id, ref;
314:
315: id = get_identifier ("objc_object");
316: ref = xref_tag (RECORD_TYPE, id);
317: id_type = build_pointer_type (ref);
318:
319: id = get_identifier ("objc_selector");
320: ref = xref_tag (RECORD_TYPE, id);
321: sel_type = build_pointer_type (ref);
322: }
323:
324: if (TYPE_MAIN_VARIANT (t) == TYPE_MAIN_VARIANT (id_type))
325: {
326: OB_PUTS ("id ");
327: dump_readonly_or_volatile (t, none);
328: return;
329: }
330: else if (TYPE_MAIN_VARIANT (t) == TYPE_MAIN_VARIANT (sel_type))
331: {
332: OB_PUTS ("SEL ");
333: dump_readonly_or_volatile (t, none);
334: return;
335: }
336: }
337: #endif
338:
339: dump_type_prefix (sub, v);
340: /* A tree for a member pointer looks like pointer to offset,
341: so let the OFFSET_TYPE case handle it. */
342: if (TREE_CODE (sub) != OFFSET_TYPE)
343: {
344: switch (TREE_CODE (sub))
345: {
346: /* We don't want int ( *)() */
347: case FUNCTION_TYPE:
348: case METHOD_TYPE:
349: break;
350:
351: case POINTER_TYPE:
352: /* We don't want "char * *" */
353: if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
354: break;
355: /* But we do want "char *const *" */
356:
357: default:
358: OB_PUTC (' ');
359: }
360: OB_PUTC ('*');
361: dump_readonly_or_volatile (t, none);
362: }
363: }
364: break;
365:
366: case REFERENCE_TYPE:
367: {
368: tree sub = TREE_TYPE (t);
369: dump_type_prefix (sub, v);
370:
371: switch (TREE_CODE (sub))
372: {
373: case POINTER_TYPE:
374: /* We don't want "char * &" */
375: if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
376: break;
377: /* But we do want "char *const &" */
378:
379: default:
380: OB_PUTC (' ');
381: }
382: }
383: OB_PUTC ('&');
384: dump_readonly_or_volatile (t, none);
385: break;
386:
387: case OFFSET_TYPE:
388: offset_type:
389: dump_type_prefix (TREE_TYPE (t), v);
390: if (NEXT_CODE (t) != FUNCTION_TYPE && NEXT_CODE (t) != METHOD_TYPE)
391: OB_PUTC (' ');
392: if (TREE_CODE (t) == OFFSET_TYPE)
393: dump_type (TYPE_OFFSET_BASETYPE (t), 0);
394: else /* pointer to member function */
395: dump_type (TYPE_METHOD_BASETYPE (TREE_TYPE (t)), 0);
396: OB_PUTC2 (':', ':');
397: OB_PUTC ('*');
398: dump_readonly_or_volatile (t, none);
399: break;
400:
401: /* Can only be reached through function pointer -- this would not be
402: correct if FUNCTION_DECLs used it. */
403: case FUNCTION_TYPE:
404: case METHOD_TYPE:
405: dump_type_prefix (TREE_TYPE (t), v);
406: OB_PUTC2 (' ', '(');
407: break;
408:
409: case ARRAY_TYPE:
410: dump_type_prefix (TREE_TYPE (t), v);
411: break;
412:
413: case ENUMERAL_TYPE:
414: case ERROR_MARK:
415: case IDENTIFIER_NODE:
416: case INTEGER_TYPE:
417: case REAL_TYPE:
418: case RECORD_TYPE:
419: case TEMPLATE_TYPE_PARM:
420: case TREE_LIST:
421: case TYPE_DECL:
422: case TREE_VEC:
423: case UNINSTANTIATED_P_TYPE:
424: case UNION_TYPE:
425: case UNKNOWN_TYPE:
426: case VOID_TYPE:
427: dump_type (t, v);
428: break;
429:
430: default:
431: my_friendly_abort (65);
432: }
433: }
434:
435: static void
436: dump_type_suffix (t, v)
437: tree t;
438: int v; /* verbose? */
439: {
440: if (TYPE_PTRMEMFUNC_P (t))
441: t = TYPE_PTRMEMFUNC_FN_TYPE (t);
442:
443: switch (TREE_CODE (t))
444: {
445: case POINTER_TYPE:
446: case REFERENCE_TYPE:
447: case OFFSET_TYPE:
448: dump_type_suffix (TREE_TYPE (t), v);
449: break;
450:
451: /* Can only be reached through function pointer */
452: case FUNCTION_TYPE:
453: case METHOD_TYPE:
454: {
455: tree arg;
456: OB_PUTC2 (')', '(');
457: arg = TYPE_ARG_TYPES (t);
458: if (TREE_CODE (t) == METHOD_TYPE)
459: arg = TREE_CHAIN (arg);
460:
461: if (arg)
462: dump_type (arg, v);
463: else
464: OB_PUTS ("...");
465: OB_PUTC (')');
466: if (TREE_CODE (t) == METHOD_TYPE)
467: dump_readonly_or_volatile
468: (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
469: dump_type_suffix (TREE_TYPE (t), v);
470: break;
471: }
472:
473: case ARRAY_TYPE:
474: OB_PUTC ('[');
475: if (TYPE_DOMAIN (t))
476: OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
477: OB_PUTC (']');
478: dump_type_suffix (TREE_TYPE (t), v);
479: break;
480:
481: case ENUMERAL_TYPE:
482: case ERROR_MARK:
483: case IDENTIFIER_NODE:
484: case INTEGER_TYPE:
485: case REAL_TYPE:
486: case RECORD_TYPE:
487: case TEMPLATE_TYPE_PARM:
488: case TREE_LIST:
489: case TYPE_DECL:
490: case TREE_VEC:
491: case UNINSTANTIATED_P_TYPE:
492: case UNION_TYPE:
493: case UNKNOWN_TYPE:
494: case VOID_TYPE:
495: break;
496:
497: default:
498: my_friendly_abort (67);
499: }
500: }
501:
502: /* Return a function declaration which corresponds to the IDENTIFIER_NODE
503: argument. */
504: tree
505: ident_fndecl (t)
506: tree t;
507: {
508: tree n = IDENTIFIER_GLOBAL_VALUE (t);
509:
510: if (TREE_CODE (n) == FUNCTION_DECL)
511: return n;
512: else if (TREE_CODE (n) == TREE_LIST
513: && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
514: return TREE_VALUE (n);
515: else
516: my_friendly_abort (66);
517: }
518:
519: #ifndef NO_DOLLAR_IN_LABEL
520: # define GLOBAL_THING "_GLOBAL_$"
521: #else
522: # ifndef NO_DOT_IN_LABEL
523: # define GLOBAL_THING "_GLOBAL_."
524: # else
525: # define GLOBAL_THING "_GLOBAL__"
526: # endif
527: #endif
528:
529: #define GLOBAL_IORD_P(NODE) \
530: !strncmp(IDENTIFIER_POINTER(NODE),GLOBAL_THING,sizeof(GLOBAL_THING)-1)
531:
532: void
533: dump_global_iord (t)
534: tree t;
535: {
536: char *name = IDENTIFIER_POINTER (t);
537:
538: OB_PUTS ("(static ");
539: if (name [sizeof (GLOBAL_THING) - 1] == 'I')
540: OB_PUTS ("initializers");
541: else if (name [sizeof (GLOBAL_THING) - 1] == 'D')
542: OB_PUTS ("destructors");
543: else
544: my_friendly_abort (352);
545:
546: OB_PUTS (" for ");
547: OB_PUTCP (input_filename);
548: OB_PUTC (')');
549: }
550:
551: static void
552: dump_decl (t, v)
553: tree t;
554: int v; /* verbosity */
555: {
556: if (t == NULL_TREE)
557: return;
558:
559: switch (TREE_CODE (t))
560: {
561: case ERROR_MARK:
562: OB_PUTS (" /* decl error */ ");
563: break;
564:
565: case VAR_DECL:
566: if (VTABLE_NAME_P (DECL_NAME (t)))
567: {
568: OB_PUTS ("vtable for ");
569: dump_type (DECL_CONTEXT (t), v);
570: break;
571: }
572: /* else fall through */
573: case FIELD_DECL:
574: case PARM_DECL:
575: if (v)
576: {
577: dump_type_prefix (TREE_TYPE (t), v);
578: OB_PUTC(' ');
579: }
580: /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
581: if (TREE_CODE (t) == FIELD_DECL
582: || (TREE_CODE (t) == VAR_DECL && DECL_CONTEXT (t)
583: && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
584: {
585: dump_type (DECL_CONTEXT (t), 0);
586: OB_PUTC2(':', ':');
587: }
588: if (DECL_NAME (t))
589: dump_decl (DECL_NAME (t), v);
590: else
591: OB_PUTS ("<anon>");
592: if (v) dump_type_suffix (TREE_TYPE (t), v);
593: break;
594:
595: case ARRAY_REF:
596: dump_decl (TREE_OPERAND (t, 0), v);
597: OB_PUTC ('[');
598: dump_decl (TREE_OPERAND (t, 1), v);
599: OB_PUTC (']');
600: break;
601:
602: /* So that we can do dump_decl in dump_aggr_type and have it work for
603: both class and function scope. */
604: case RECORD_TYPE:
605: case UNION_TYPE:
606: case ENUMERAL_TYPE:
607: dump_type (t, v);
608: break;
609:
610: case TYPE_DECL:
611: dump_type (TREE_TYPE (t), v);
612: break;
613:
614: case TYPE_EXPR:
615: my_friendly_abort (69);
616: break;
617:
618: /* These special cases are duplicated here so that other functions
619: can feed identifiers to cp_error and get them demangled properly. */
620: case IDENTIFIER_NODE:
621: if (DESTRUCTOR_NAME_P (t))
622: {
623: OB_PUTC ('~');
624: dump_decl (DECL_NAME (ident_fndecl (t)), 0);
625: }
626: else if (IDENTIFIER_TYPENAME_P (t))
627: {
628: OB_PUTS ("operator ");
629: /* Not exactly IDENTIFIER_TYPE_VALUE. */
630: dump_type (TREE_TYPE (t), 0);
631: break;
632: }
633: else if (IDENTIFIER_OPNAME_P (t))
634: {
635: char *name_string = operator_name_string (t);
636: OB_PUTS ("operator ");
637: OB_PUTCP (name_string);
638: }
639: else
640: OB_PUTID (t);
641: break;
642:
643: case FUNCTION_DECL:
644: if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
645: dump_global_iord (DECL_ASSEMBLER_NAME (t));
646: else
647: dump_function_decl (t, v);
648: break;
649:
650: case TEMPLATE_DECL:
651: switch (NEXT_CODE (t))
652: {
653: case METHOD_TYPE:
654: case FUNCTION_TYPE:
655: dump_function_decl (t, v);
656: break;
657:
658: default:
659: my_friendly_abort (353);
660: }
661: break;
662:
663: case LABEL_DECL:
664: OB_PUTID (DECL_NAME (t));
665: break;
666:
667: case CONST_DECL:
668: if (NEXT_CODE (t) == ENUMERAL_TYPE)
669: {
670: if (DECL_CONTEXT (t))
671: {
672: dump_decl (DECL_CONTEXT (t), 0);
673: OB_PUTC2 (':', ':');
674: }
675: OB_PUTID (DECL_NAME (t));
676: }
677: else
678: dump_expr (DECL_INITIAL (t), 0);
679: break;
680:
681: #ifdef OBJCPLUS
682: case INSTANCE_METHOD_DECL:
683: case CLASS_METHOD_DECL:
684: dump_decl (METHOD_DEFINITION (t), v);
685: break;
686: #endif
687:
688: default:
689: my_friendly_abort (70);
690: }
691: }
692:
693: /* Pretty printing for announce_function. T is the declaration of the
694: function we are interested in seeing. V is non-zero if we should print
695: the type that this function returns. */
696:
697: static void
698: dump_function_decl (t, v)
699: tree t;
700: int v;
701: {
702: tree name = DECL_ASSEMBLER_NAME (t);
703: tree fntype = TREE_TYPE (t);
704: tree parmtypes = TYPE_ARG_TYPES (fntype);
705: tree cname = NULL_TREE;
706: int spaces = 0;
707:
708: if (DECL_CLASS_CONTEXT (t))
709: cname = DECL_CLASS_CONTEXT (t);
710: /* this is for partially instantiated template methods */
711: else if (TREE_CODE (fntype) == METHOD_TYPE)
712: cname = TREE_TYPE (TREE_VALUE (parmtypes));
713:
714: if (v)
715: {
716: if (DECL_STATIC_FUNCTION_P (t))
717: OB_PUTS ("static ");
718:
719: if (! IDENTIFIER_TYPENAME_P (name))
720: {
721: dump_type_prefix (TREE_TYPE (fntype), 1);
722: OB_PUTC (' ');
723: }
724: }
725:
726: if (cname)
727: {
728: dump_type (cname, 0);
729: OB_PUTC2 (':', ':');
730: if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
731: parmtypes = TREE_CHAIN (parmtypes);
732: if (DECL_CONSTRUCTOR_FOR_VBASE_P (t))
733: /* Skip past "in_charge" identifier. */
734: parmtypes = TREE_CHAIN (parmtypes);
735: }
736:
737: if (DESTRUCTOR_NAME_P (name))
738: parmtypes = TREE_CHAIN (parmtypes);
739:
740: dump_function_name (t);
741:
742: OB_PUTC ('(');
743:
744: if (parmtypes)
745: dump_type (parmtypes, v);
746: else
747: OB_PUTS ("...");
748:
749: OB_PUTC (')');
750:
751: if (v && ! IDENTIFIER_TYPENAME_P (name))
752: dump_type_suffix (TREE_TYPE (fntype), 1);
753:
754: if (TREE_CODE (fntype) == METHOD_TYPE)
755: dump_readonly_or_volatile
756: (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
757: }
758:
759: /* Handle the function name for a FUNCTION_DECL node, grokking operators
760: and destructors properly. */
761: static void
762: dump_function_name (t)
763: tree t;
764: {
765: tree name = DECL_NAME (t);
766:
767: /* There ought to be a better way to find out whether or not something is
768: a destructor. */
769: if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
770: {
771: OB_PUTC ('~');
772: dump_decl (name, 0);
773: }
774: else if (IDENTIFIER_TYPENAME_P (name))
775: {
776: /* This cannot use the hack that the operator's return
777: type is stashed off of its name because it may be
778: used for error reporting. In the case of conflicting
779: declarations, both will have the same name, yet
780: the types will be different, hence the TREE_TYPE field
781: of the first name will be clobbered by the second. */
782: OB_PUTS ("operator ");
783: dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
784: }
785: else if (IDENTIFIER_OPNAME_P (name))
786: {
787: char *name_string = operator_name_string (name);
788: OB_PUTS ("operator ");
789: OB_PUTCP (name_string);
790: }
791: else
792: dump_decl (name, 0);
793: }
794:
795: static void
796: dump_char (c)
797: char c;
798: {
799: switch (c)
800: {
801: case '\n':
802: OB_PUTS ("\\n");
803: break;
804: case '\t':
805: OB_PUTS ("\\t");
806: break;
807: case '\v':
808: OB_PUTS ("\\v");
809: break;
810: case '\b':
811: OB_PUTS ("\\b");
812: break;
813: case '\r':
814: OB_PUTS ("\\r");
815: break;
816: case '\f':
817: OB_PUTS ("\\f");
818: break;
819: case '\a':
820: OB_PUTS ("\\a");
821: break;
822: case '\\':
823: OB_PUTS ("\\\\");
824: break;
825: case '\'':
826: OB_PUTS ("\\'");
827: break;
828: case '\"':
829: OB_PUTS ("\\\"");
830: break;
831: default:
832: if (isprint (c))
833: OB_PUTC (c);
834: else
835: {
836: sprintf (digit_buffer, "\\%03o", (int) c);
837: OB_PUTCP (digit_buffer);
838: }
839: }
840: }
841:
842: /* Print out a list of initializers (subr of dump_expr) */
843: static void
844: dump_expr_list (l)
845: tree l;
846: {
847: while (l)
848: {
849: dump_expr (TREE_VALUE (l), 0);
850: if (TREE_CHAIN (l))
851: OB_PUTC2 (',', ' ');
852: l = TREE_CHAIN (l);
853: }
854: }
855:
856: /* Print out an expression */
857: static void
858: dump_expr (t, nop)
859: tree t;
860: int nop; /* suppress parens */
861: {
862: switch (TREE_CODE (t))
863: {
864: case VAR_DECL:
865: case PARM_DECL:
866: case FIELD_DECL:
867: case CONST_DECL:
868: case FUNCTION_DECL:
869: dump_decl (t, 0);
870: break;
871:
872: case INTEGER_CST:
873: {
874: tree type = TREE_TYPE (t);
875: my_friendly_assert (type != 0, 81);
876:
877: /* If it's an enum, output its tag, rather than its value. */
878: if (TREE_CODE (type) == ENUMERAL_TYPE)
879: {
880: char *p = enum_name_string (t, type);
881: OB_PUTCP (p);
882: }
883: else if (type == char_type_node
884: || type == signed_char_type_node
885: || type == unsigned_char_type_node)
886: {
887: OB_PUTC ('\'');
888: dump_char (TREE_INT_CST_LOW (t));
889: OB_PUTC ('\'');
890: }
891: else if (TREE_INT_CST_HIGH (t)
892: != (TREE_INT_CST_LOW (t) >> (HOST_BITS_PER_WIDE_INT - 1)))
893: {
894: tree val = t;
895: if (TREE_INT_CST_HIGH (val) < 0)
896: {
897: OB_PUTC ('-');
898: val = build_int_2 (~TREE_INT_CST_LOW (val),
899: -TREE_INT_CST_HIGH (val));
900: }
901: /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
902: systems? */
903: {
904: static char format[10]; /* "%x%09999x\0" */
905: if (!format[0])
906: sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
907: sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
908: TREE_INT_CST_LOW (val));
909: OB_PUTCP (digit_buffer);
910: }
911: }
912: else
913: OB_PUTI (TREE_INT_CST_LOW (t));
914: }
915: break;
916:
917: case REAL_CST:
918: #ifndef REAL_IS_NOT_DOUBLE
919: sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
920: #else
921: {
922: int i;
923: char *p = (char *) &TREE_REAL_CST (t);
924: sprintf (digit_buffer, "0x");
925: for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
926: sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
927: }
928: #endif
929: OB_PUTCP (digit_buffer);
930: break;
931:
932: case STRING_CST:
933: {
934: char *p = TREE_STRING_POINTER (t);
935: int len = TREE_STRING_LENGTH (t) - 1;
936: int i;
937:
938: OB_PUTC ('\"');
939: for (i = 0; i < len; i++)
940: dump_char (p[i]);
941: OB_PUTC ('\"');
942: }
943: break;
944:
945: case COMPOUND_EXPR:
946: dump_binary_op (",", t);
947: break;
948:
949: case COND_EXPR:
950: OB_PUTC ('(');
951: dump_expr (TREE_OPERAND (t, 0), 0);
952: OB_PUTS (" ? ");
953: dump_expr (TREE_OPERAND (t, 1), 0);
954: OB_PUTS (" : ");
955: dump_expr (TREE_OPERAND (t, 2), 0);
956: OB_PUTC (')');
957: break;
958:
959: case SAVE_EXPR:
960: if (TREE_HAS_CONSTRUCTOR (t))
961: {
962: OB_PUTS ("new ");
963: dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
964: PARM_DECL_EXPR (t) = 1;
965: }
966: else
967: {
968: sorry ("operand of SAVE_EXPR not understood");
969: goto error;
970: }
971: break;
972:
973: case NEW_EXPR:
974: OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
975: OB_PUTC ('(');
976: dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
977: OB_PUTC (')');
978: break;
979:
980: case CALL_EXPR:
981: dump_expr (TREE_OPERAND (t, 0), 0);
982: OB_PUTC2 (' ', '(');
983: dump_expr_list (TREE_OPERAND (t, 1));
984: OB_PUTC (')');
985: break;
986:
987: case WITH_CLEANUP_EXPR:
988: /* Note that this only works for G++ cleanups. If somebody
989: builds a general cleanup, there's no way to represent it. */
990: dump_expr (TREE_OPERAND (t, 0), 0);
991: break;
992:
993: case TARGET_EXPR:
994: /* Note that this only works for G++ target exprs. If somebody
995: builds a general TARGET_EXPR, there's no way to represent that
996: it initializes anything other that the parameter slot for the
997: default argument. Note we may have cleared out the first
998: operand in expand_expr, so don't go killing ourselves. */
999: if (TREE_OPERAND (t, 1))
1000: dump_expr (TREE_OPERAND (t, 1), 0);
1001: break;
1002:
1003: case MODIFY_EXPR:
1004: case PLUS_EXPR:
1005: case MINUS_EXPR:
1006: case MULT_EXPR:
1007: case TRUNC_DIV_EXPR:
1008: case TRUNC_MOD_EXPR:
1009: case MIN_EXPR:
1010: case MAX_EXPR:
1011: case LSHIFT_EXPR:
1012: case RSHIFT_EXPR:
1013: case BIT_IOR_EXPR:
1014: case BIT_XOR_EXPR:
1015: case BIT_AND_EXPR:
1016: case BIT_ANDTC_EXPR:
1017: case TRUTH_ANDIF_EXPR:
1018: case TRUTH_ORIF_EXPR:
1019: case LT_EXPR:
1020: case LE_EXPR:
1021: case GT_EXPR:
1022: case GE_EXPR:
1023: case EQ_EXPR:
1024: case NE_EXPR:
1025: dump_binary_op (opname_tab[(int) TREE_CODE (t)], t);
1026: break;
1027:
1028: case CEIL_DIV_EXPR:
1029: case FLOOR_DIV_EXPR:
1030: case ROUND_DIV_EXPR:
1031: dump_binary_op ("/", t);
1032: break;
1033:
1034: case CEIL_MOD_EXPR:
1035: case FLOOR_MOD_EXPR:
1036: case ROUND_MOD_EXPR:
1037: dump_binary_op ("%", t);
1038: break;
1039:
1040: case COMPONENT_REF:
1041: dump_binary_op (".", t);
1042: break;
1043:
1044: case CONVERT_EXPR:
1045: dump_unary_op ("+", t, nop);
1046: break;
1047:
1048: case ADDR_EXPR:
1049: if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
1050: || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
1051: dump_expr (TREE_OPERAND (t, 0), 0);
1052: else
1053: dump_unary_op ("&", t, nop);
1054: break;
1055:
1056: case INDIRECT_REF:
1057: if (TREE_HAS_CONSTRUCTOR (t))
1058: {
1059: t = TREE_OPERAND (t, 0);
1060: my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
1061: dump_expr (TREE_OPERAND (t, 0), 0);
1062: OB_PUTC ('(');
1063: dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
1064: OB_PUTC (')');
1065: }
1066: else
1067: dump_unary_op ("*", t, nop);
1068: break;
1069:
1070: case NEGATE_EXPR:
1071: case BIT_NOT_EXPR:
1072: case TRUTH_NOT_EXPR:
1073: case PREDECREMENT_EXPR:
1074: case PREINCREMENT_EXPR:
1075: dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, nop);
1076: break;
1077:
1078: case POSTDECREMENT_EXPR:
1079: case POSTINCREMENT_EXPR:
1080: OB_PUTC ('(');
1081: dump_expr (TREE_OPERAND (t, 0), 0);
1082: OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
1083: OB_PUTC (')');
1084: break;
1085:
1086: case NON_LVALUE_EXPR:
1087: /* FIXME: This is a KLUDGE workaround for a parsing problem. There
1088: should be another level of INDIRECT_REF so that I don't have to do
1089: this. */
1090: if (NEXT_CODE (t) == POINTER_TYPE)
1091: {
1092: tree next = TREE_TYPE (TREE_TYPE (t));
1093:
1094: while (TREE_CODE (next) == POINTER_TYPE)
1095: next = TREE_TYPE (next);
1096:
1097: if (TREE_CODE (next) == FUNCTION_TYPE)
1098: {
1099: if (!nop) OB_PUTC ('(');
1100: OB_PUTC ('*');
1101: dump_expr (TREE_OPERAND (t, 0), 1);
1102: if (!nop) OB_PUTC (')');
1103: break;
1104: }
1105: /* else FALLTHRU */
1106: }
1107: dump_expr (TREE_OPERAND (t, 0), 0);
1108: break;
1109:
1110: case NOP_EXPR:
1111: dump_expr (TREE_OPERAND (t, 0), nop);
1112: break;
1113:
1114: case CONSTRUCTOR:
1115: OB_PUTC ('{');
1116: dump_expr_list (CONSTRUCTOR_ELTS (t), 0);
1117: OB_PUTC ('}');
1118: break;
1119:
1120: /* This list is incomplete, but should suffice for now.
1121: It is very important that `sorry' does not call
1122: `report_error_function'. That could cause an infinite loop. */
1123: default:
1124: sorry ("`%s' not supported by dump_expr",
1125: tree_code_name[(int) TREE_CODE (t)]);
1126:
1127: /* fall through to ERROR_MARK... */
1128: case ERROR_MARK:
1129: error:
1130: OB_PUTCP ("/* error */");
1131: break;
1132: }
1133: }
1134:
1135: static void
1136: dump_binary_op (opstring, t)
1137: char *opstring;
1138: tree t;
1139: {
1140: OB_PUTC ('(');
1141: dump_expr (TREE_OPERAND (t, 0), 1);
1142: OB_PUTC (' ');
1143: OB_PUTCP (opstring);
1144: OB_PUTC (' ');
1145: dump_expr (TREE_OPERAND (t, 1), 1);
1146: OB_PUTC (')');
1147: }
1148:
1149: static void
1150: dump_unary_op (opstring, t, nop)
1151: char *opstring;
1152: tree t;
1153: int nop;
1154: {
1155: if (!nop) OB_PUTC ('(');
1156: OB_PUTCP (opstring);
1157: dump_expr (TREE_OPERAND (t, 0), 1);
1158: if (!nop) OB_PUTC (')');
1159: }
1160:
1161: char *
1162: fndecl_as_string (cname, fndecl, print_ret_type_p)
1163: tree cname, fndecl;
1164: int print_ret_type_p;
1165: {
1166: return decl_as_string (fndecl, print_ret_type_p);
1167: }
1168:
1169: /* Same, but handtype a _TYPE.
1170: Called from convert_to_reference, mangle_class_name_for_template,
1171: build_unary_op, and GNU_xref_decl. */
1172: char *
1173: type_as_string (typ, v)
1174: tree typ;
1175: int v;
1176: {
1177: OB_INIT ();
1178:
1179: dump_type (typ, v);
1180:
1181: OB_FINISH ();
1182:
1183: return (char *)obstack_base (&scratch_obstack);
1184: }
1185:
1186: char *
1187: expr_as_string (decl, v)
1188: tree decl;
1189: int v;
1190: {
1191: OB_INIT ();
1192:
1193: dump_expr (decl, 1);
1194:
1195: OB_FINISH ();
1196:
1197: return (char *)obstack_base (&scratch_obstack);
1198: }
1199:
1200: /* A cross between type_as_string and fndecl_as_string.
1201: Only called from substitute_nice_name. */
1202: char *
1203: decl_as_string (decl, v)
1204: tree decl;
1205: int v;
1206: {
1207: OB_INIT ();
1208:
1209: dump_decl (decl, v);
1210:
1211: OB_FINISH ();
1212:
1213: return (char *)obstack_base (&scratch_obstack);
1214: }
1215:
1216: char *
1217: cp_file_of (t)
1218: tree t;
1219: {
1220: if (TREE_CODE (t) == PARM_DECL)
1221: return DECL_SOURCE_FILE (DECL_CONTEXT (t));
1222: else
1223: return DECL_SOURCE_FILE (t);
1224: }
1225:
1226: int
1227: cp_line_of (t)
1228: tree t;
1229: {
1230: if (TREE_CODE (t) == PARM_DECL)
1231: return DECL_SOURCE_LINE (DECL_CONTEXT (t));
1232: else
1233: return DECL_SOURCE_LINE (t);
1234: }
1235:
1236: char *
1237: code_as_string (c, v)
1238: enum tree_code c;
1239: int v;
1240: {
1241: return tree_code_name [c];
1242: }
1243:
1244: char *
1245: language_as_string (c, v)
1246: enum languages c;
1247: int v;
1248: {
1249: switch (c)
1250: {
1251: case lang_c:
1252: return "C";
1253:
1254: case lang_cplusplus:
1255: return "C++";
1256:
1257: default:
1258: my_friendly_abort (355);
1259: }
1260: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.