home *** CD-ROM | disk | FTP | other *** search
- /* Call-backs for C++ error reporting.
- This code is non-reentrant.
- Copyright (C) 1993 Free Software Foundation, Inc.
-
- This file is part of GNU CC.
-
- GNU CC is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
- any later version.
-
- GNU CC is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GNU CC; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
- #include "config.h"
- #include "tree.h"
- #include "cp-tree.h"
- #include "obstack.h"
- #include <ctype.h>
-
- typedef char* cp_printer ();
-
- #define C code_as_string
- #define D decl_as_string
- #define E expr_as_string
- #define L language_as_string
- #define T type_as_string
-
- #define _ (cp_printer *) 0
- cp_printer * cp_printers[256] =
- {
- /*0 1 2 3 4 5 6 7 8 9 A B C D E F */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */
- _, _, _, C, D, E, _, _, _, _, _, _, L, _, _, _, /* 0x40 */
- _, _, _, _, T, _, _, _, _, _, _, _, _, _, _, _, /* 0x50 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */
- _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */
- };
- #undef C
- #undef D
- #undef E
- #undef L
- #undef T
- #undef _
-
- #define obstack_chunk_alloc xmalloc
- #define obstack_chunk_free free
-
- /* Obstack where we build text strings for overloading, etc. */
- static struct obstack scratch_obstack;
- static char *scratch_firstobj;
-
- # define OB_INIT() (scratch_firstobj ? (obstack_free (&scratch_obstack, scratch_firstobj), 0) : 0)
- # define OB_PUTC(C) (obstack_1grow (&scratch_obstack, (C)))
- # define OB_PUTC2(C1,C2) \
- (obstack_1grow (&scratch_obstack, (C1)), obstack_1grow (&scratch_obstack, (C2)))
- # define OB_PUTS(S) (obstack_grow (&scratch_obstack, (S), sizeof (S) - 1))
- # define OB_PUTID(ID) \
- (obstack_grow (&scratch_obstack, IDENTIFIER_POINTER (ID), \
- IDENTIFIER_LENGTH (ID)))
- # define OB_PUTCP(S) (obstack_grow (&scratch_obstack, (S), strlen (S)))
- # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
- # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
- OB_PUTCP (digit_buffer); } while (0)
-
- # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
-
- static void dump_type (), dump_decl (), dump_function_decl ();
- static void dump_expr (), dump_unary_op (), dump_binary_op ();
- static void dump_aggr_type (), dump_type_prefix (), dump_type_suffix ();
- static void dump_function_name ();
-
- void
- init_error ()
- {
- gcc_obstack_init (&scratch_obstack);
- scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);
- }
-
- /* Counter to help build parameter names in case they were omitted. */
- static int dummy_name;
-
- enum pad { none, before, after };
-
- static void
- dump_readonly_or_volatile (t, p)
- tree t;
- enum pad p;
- {
- if (TYPE_READONLY (t) || TYPE_VOLATILE (t))
- {
- if (p == before) OB_PUTC (' ');
- if (TYPE_READONLY (t))
- OB_PUTS ("const");
- if (TYPE_VOLATILE (t))
- OB_PUTS ("volatile");
- if (p == after) OB_PUTC (' ');
- }
- }
-
- /* This must be large enough to hold any printed integer or floating-point
- value. */
- static char digit_buffer[128];
-
- /* Dump into the obstack a human-readable equivalent of TYPE. */
- static void
- dump_type (t, v)
- tree t;
- int v; /* verbose? */
- {
- if (t == NULL_TREE)
- return;
-
- if (TYPE_PTRMEMFUNC_P (t))
- goto offset_type;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- OB_PUTS ("<error>");
- break;
-
- case UNKNOWN_TYPE:
- OB_PUTS ("<unknown type>");
- break;
-
- case TREE_LIST:
- /* i.e. function taking no arguments */
- if (t != void_list_node)
- {
- dump_type (TREE_VALUE (t), v);
- /* Can this happen other than for default arguments? */
- if (TREE_PURPOSE (t) && v)
- {
- OB_PUTS (" = ");
- dump_expr (TREE_PURPOSE (t));
- }
- if (TREE_CHAIN (t))
- {
- if (TREE_CHAIN (t) != void_list_node)
- {
- OB_PUTC2 (',', ' ');
- dump_type (TREE_CHAIN (t), v);
- }
- }
- else OB_PUTS (" ...");
- }
- break;
-
- case IDENTIFIER_NODE:
- OB_PUTID (t);
- break;
-
- case TREE_VEC:
- dump_type (BINFO_TYPE (t), v);
- break;
-
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- dump_aggr_type (t, v);
- break;
-
- case TYPE_DECL:
- dump_readonly_or_volatile (t, after);
- OB_PUTID (DECL_NAME (t));
- break;
-
- case INTEGER_TYPE:
- if (!TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && TREE_UNSIGNED (t))
- OB_PUTS ("unsigned ");
- else if (TREE_UNSIGNED (TYPE_MAIN_VARIANT (t)) && !TREE_UNSIGNED (t))
- OB_PUTS ("signed ");
-
- /* fall through. */
- case REAL_TYPE:
- case VOID_TYPE:
- dump_readonly_or_volatile (t, after);
- OB_PUTID (TYPE_IDENTIFIER (t));
- break;
-
- case TEMPLATE_TYPE_PARM:
- OB_PUTS ("<template type parm ");
- OB_PUTID (TYPE_IDENTIFIER (t));
- OB_PUTC ('>');
- break;
-
- case UNINSTANTIATED_P_TYPE:
- OB_PUTID (DECL_NAME (UPT_TEMPLATE (t)));
- OB_PUTS ("<...>");
- break;
-
- /* This is not always necessary for pointers and such, but doing this
- reduces code size. */
- case ARRAY_TYPE:
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- case OFFSET_TYPE:
- offset_type:
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- dump_type_prefix (t, v);
- dump_type_suffix (t, v);
- break;
-
- default:
- my_friendly_abort (68);
-
- }
- }
-
- /* Print out a class declaration, in the form `class foo'. */
- static void
- dump_aggr_type (t, v)
- tree t;
- int v; /* verbose? */
- {
- tree name;
- char *variety;
-
- if (TREE_CODE (t) == ENUMERAL_TYPE)
- variety = "enum";
- else if (TREE_CODE (t) == UNION_TYPE)
- variety = "union";
- else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
- variety = "class";
- else
- variety = "struct";
-
- dump_readonly_or_volatile (t, after);
-
- if (v)
- {
- OB_PUTCP (variety);
- OB_PUTC (' ');
- }
-
- name = TYPE_NAME (t);
-
- if (DECL_CONTEXT (name))
- {
- /* FUNCTION_DECL or RECORD_TYPE */
- dump_decl (DECL_CONTEXT (name), 0);
- OB_PUTC2 (':', ':');
- }
-
- /* kludge around wierd behavior on g++.brendan/line1.C */
- if (TREE_CODE (name) != IDENTIFIER_NODE)
- name = DECL_NAME (name);
-
- if (ANON_AGGRNAME_P (name))
- {
- OB_PUTS ("<anonymous");
- if (!v)
- {
- OB_PUTC (' ');
- OB_PUTCP (variety);
- }
- OB_PUTC ('>');
- }
- else
- OB_PUTID (name);
- }
-
- /* Dump into the obstack the initial part of the output for a given type.
- This is necessary when dealing with things like functions returning
- functions. Examples:
-
- return type of `int (* fee ())()': pointer -> function -> int. Both
- pointer (and reference and offset) and function (and member) types must
- deal with prefix and suffix.
-
- Arrays must also do this for DECL nodes, like int a[], and for things like
- int *[]&. */
-
- static void
- dump_type_prefix (t, v)
- tree t;
- int v; /* verbosity */
- {
- if (TYPE_PTRMEMFUNC_P (t))
- {
- t = TYPE_PTRMEMFUNC_FN_TYPE (t);
- goto offset_type;
- }
-
- switch (TREE_CODE (t))
- {
- case POINTER_TYPE:
- {
- tree sub = TREE_TYPE (t);
-
- dump_type_prefix (sub, v);
- /* A tree for a member pointer looks like pointer to offset,
- so let the OFFSET_TYPE case handle it. */
- if (TREE_CODE (sub) != OFFSET_TYPE)
- {
- switch (TREE_CODE (sub))
- {
- /* We don't want int ( *)() */
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- break;
-
- case POINTER_TYPE:
- /* We don't want "char * *" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
- break;
- /* But we do want "char *const *" */
-
- default:
- OB_PUTC (' ');
- }
- OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
- }
- }
- break;
-
- case REFERENCE_TYPE:
- {
- tree sub = TREE_TYPE (t);
- dump_type_prefix (sub, v);
-
- switch (TREE_CODE (sub))
- {
- case POINTER_TYPE:
- /* We don't want "char * &" */
- if (! (TYPE_READONLY (sub) || TYPE_VOLATILE (sub)))
- break;
- /* But we do want "char *const &" */
-
- default:
- OB_PUTC (' ');
- }
- }
- OB_PUTC ('&');
- dump_readonly_or_volatile (t, none);
- break;
-
- case OFFSET_TYPE:
- offset_type:
- dump_type_prefix (TREE_TYPE (t), v);
- if (NEXT_CODE (t) != FUNCTION_TYPE && NEXT_CODE (t) != METHOD_TYPE)
- OB_PUTC (' ');
- if (TREE_CODE (t) == OFFSET_TYPE)
- dump_type (TYPE_OFFSET_BASETYPE (t), 0);
- else /* pointer to member function */
- dump_type (TYPE_METHOD_BASETYPE (TREE_TYPE (t)), 0);
- OB_PUTC2 (':', ':');
- OB_PUTC ('*');
- dump_readonly_or_volatile (t, none);
- break;
-
- /* Can only be reached through function pointer -- this would not be
- correct if FUNCTION_DECLs used it. */
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- dump_type_prefix (TREE_TYPE (t), v);
- OB_PUTC2 (' ', '(');
- break;
-
- case ARRAY_TYPE:
- dump_type_prefix (TREE_TYPE (t), v);
- break;
-
- case ENUMERAL_TYPE:
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case INTEGER_TYPE:
- case REAL_TYPE:
- case RECORD_TYPE:
- case TEMPLATE_TYPE_PARM:
- case TREE_LIST:
- case TYPE_DECL:
- case TREE_VEC:
- case UNINSTANTIATED_P_TYPE:
- case UNION_TYPE:
- case UNKNOWN_TYPE:
- case VOID_TYPE:
- dump_type (t, v);
- break;
-
- default:
- my_friendly_abort (65);
- }
- }
-
- static void
- dump_type_suffix (t, v)
- tree t;
- int v; /* verbose? */
- {
- if (TYPE_PTRMEMFUNC_P (t))
- t = TYPE_PTRMEMFUNC_FN_TYPE (t);
-
- switch (TREE_CODE (t))
- {
- case POINTER_TYPE:
- case REFERENCE_TYPE:
- case OFFSET_TYPE:
- dump_type_suffix (TREE_TYPE (t), v);
- break;
-
- /* Can only be reached through function pointer */
- case FUNCTION_TYPE:
- case METHOD_TYPE:
- {
- tree arg;
- OB_PUTC2 (')', '(');
- arg = TYPE_ARG_TYPES (t);
- if (TREE_CODE (t) == METHOD_TYPE)
- arg = TREE_CHAIN (arg);
-
- if (arg)
- dump_type (arg, v);
- else
- OB_PUTS ("...");
- OB_PUTC (')');
- if (TREE_CODE (t) == METHOD_TYPE)
- dump_readonly_or_volatile
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), before);
- dump_type_suffix (TREE_TYPE (t), v);
- break;
- }
-
- case ARRAY_TYPE:
- OB_PUTC ('[');
- if (TYPE_DOMAIN (t))
- OB_PUTI (TREE_INT_CST_LOW (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) + 1);
- OB_PUTC (']');
- dump_type_suffix (TREE_TYPE (t), v);
- break;
-
- case ENUMERAL_TYPE:
- case ERROR_MARK:
- case IDENTIFIER_NODE:
- case INTEGER_TYPE:
- case REAL_TYPE:
- case RECORD_TYPE:
- case TEMPLATE_TYPE_PARM:
- case TREE_LIST:
- case TYPE_DECL:
- case TREE_VEC:
- case UNINSTANTIATED_P_TYPE:
- case UNION_TYPE:
- case UNKNOWN_TYPE:
- case VOID_TYPE:
- break;
-
- default:
- my_friendly_abort (67);
- }
- }
-
- /* Return a function declaration which corresponds to the IDENTIFIER_NODE
- argument. */
- tree
- ident_fndecl (t)
- tree t;
- {
- tree n = IDENTIFIER_GLOBAL_VALUE (t);
-
- if (TREE_CODE (n) == FUNCTION_DECL)
- return n;
- else if (TREE_CODE (n) == TREE_LIST
- && TREE_CODE (TREE_VALUE (n)) == FUNCTION_DECL)
- return TREE_VALUE (n);
- else
- my_friendly_abort (66);
- }
-
- #ifndef NO_DOLLAR_IN_LABEL
- # define GLOBAL_THING "_GLOBAL_$"
- #else
- # ifndef NO_DOT_IN_LABEL
- # define GLOBAL_THING "_GLOBAL_."
- # else
- # define GLOBAL_THING "_GLOBAL__"
- # endif
- #endif
-
- #define GLOBAL_IORD_P(NODE) \
- !strncmp(IDENTIFIER_POINTER(NODE),GLOBAL_THING,sizeof(GLOBAL_THING)-1)
-
- void
- dump_global_iord (t)
- tree t;
- {
- char *name = IDENTIFIER_POINTER (t);
-
- OB_PUTS ("(static ");
- if (name [sizeof (GLOBAL_THING) - 1] == 'I')
- OB_PUTS ("initializers");
- else if (name [sizeof (GLOBAL_THING) - 1] == 'D')
- OB_PUTS ("destructors");
- else
- my_friendly_abort (352);
-
- OB_PUTS (" for ");
- OB_PUTCP (input_filename);
- OB_PUTC (')');
- }
-
- static void
- dump_decl (t, v)
- tree t;
- int v; /* verbosity */
- {
- if (t == NULL_TREE)
- return;
-
- switch (TREE_CODE (t))
- {
- case ERROR_MARK:
- OB_PUTS (" /* decl error */ ");
- break;
-
- case VAR_DECL:
- if (VTABLE_NAME_P (DECL_NAME (t)))
- {
- OB_PUTS ("vtable for ");
- dump_type (DECL_CONTEXT (t), v);
- break;
- }
- /* else fall through */
- case FIELD_DECL:
- case PARM_DECL:
- if (v)
- {
- dump_type_prefix (TREE_TYPE (t), v);
- OB_PUTC(' ');
- }
- /* DECL_CLASS_CONTEXT isn't being set in some cases. Hmm... */
- if (TREE_CODE (t) == FIELD_DECL
- || (TREE_CODE (t) == VAR_DECL && DECL_CONTEXT (t)
- && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't'))
- {
- dump_type (DECL_CONTEXT (t), 0);
- OB_PUTC2(':', ':');
- }
- if (DECL_NAME (t))
- dump_decl (DECL_NAME (t), v);
- else
- OB_PUTS ("<anon>");
- if (v) dump_type_suffix (TREE_TYPE (t), v);
- break;
-
- case ARRAY_REF:
- dump_decl (TREE_OPERAND (t, 0), v);
- OB_PUTC ('[');
- dump_decl (TREE_OPERAND (t, 1), v);
- OB_PUTC (']');
- break;
-
- /* So that we can do dump_decl in dump_aggr_type and have it work for
- both class and function scope. */
- case RECORD_TYPE:
- case UNION_TYPE:
- case ENUMERAL_TYPE:
- dump_type (t, v);
- break;
-
- case TYPE_DECL:
- dump_type (TREE_TYPE (t), v);
- break;
-
- case TYPE_EXPR:
- my_friendly_abort (69);
- break;
-
- /* These special cases are duplicated here so that other functions
- can feed identifiers to cp_error and get them demangled properly. */
- case IDENTIFIER_NODE:
- if (DESTRUCTOR_NAME_P (t))
- {
- OB_PUTC ('~');
- dump_decl (DECL_NAME (ident_fndecl (t)), 0);
- }
- else if (IDENTIFIER_TYPENAME_P (t))
- {
- OB_PUTS ("operator ");
- /* Not exactly IDENTIFIER_TYPE_VALUE. */
- dump_type (TREE_TYPE (t), 0);
- break;
- }
- else if (IDENTIFIER_OPNAME_P (t))
- {
- char *name_string = operator_name_string (t);
- OB_PUTS ("operator ");
- OB_PUTCP (name_string);
- }
- else
- OB_PUTID (t);
- break;
-
- case FUNCTION_DECL:
- if (GLOBAL_IORD_P (DECL_ASSEMBLER_NAME (t)))
- dump_global_iord (DECL_ASSEMBLER_NAME (t));
- else
- dump_function_decl (t, v);
- break;
-
- case TEMPLATE_DECL:
- switch (NEXT_CODE (t))
- {
- case METHOD_TYPE:
- case FUNCTION_TYPE:
- dump_function_decl (t, v);
- break;
-
- default:
- my_friendly_abort (353);
- }
- break;
-
- case LABEL_DECL:
- OB_PUTID (DECL_NAME (t));
- break;
-
- case CONST_DECL:
- if (NEXT_CODE (t) == ENUMERAL_TYPE)
- {
- if (DECL_CONTEXT (t))
- {
- dump_decl (DECL_CONTEXT (t), 0);
- OB_PUTC2 (':', ':');
- }
- OB_PUTID (DECL_NAME (t));
- }
- else
- dump_expr (DECL_INITIAL (t), 0);
- break;
-
- default:
- my_friendly_abort (70);
- }
- }
-
- /* Pretty printing for announce_function. T is the declaration of the
- function we are interested in seeing. V is non-zero if we should print
- the type that this function returns. */
-
- static void
- dump_function_decl (t, v)
- tree t;
- int v;
- {
- tree name = DECL_ASSEMBLER_NAME (t);
- tree fntype = TREE_TYPE (t);
- tree parmtypes = TYPE_ARG_TYPES (fntype);
- tree cname = NULL_TREE;
- int spaces = 0;
-
- if (DECL_CLASS_CONTEXT (t))
- cname = DECL_CLASS_CONTEXT (t);
- /* this is for partially instantiated template methods */
- else if (TREE_CODE (fntype) == METHOD_TYPE)
- cname = TREE_TYPE (TREE_VALUE (parmtypes));
-
- if (v)
- {
- if (DECL_STATIC_FUNCTION_P (t))
- OB_PUTS ("static ");
-
- if (! IDENTIFIER_TYPENAME_P (name))
- {
- dump_type_prefix (TREE_TYPE (fntype), 1);
- OB_PUTC (' ');
- }
- }
-
- if (cname)
- {
- dump_type (cname, 0);
- OB_PUTC2 (':', ':');
- if (TREE_CODE (fntype) == METHOD_TYPE && parmtypes)
- parmtypes = TREE_CHAIN (parmtypes);
- if (DECL_CONSTRUCTOR_FOR_VBASE_P (t))
- /* Skip past "in_charge" identifier. */
- parmtypes = TREE_CHAIN (parmtypes);
- }
-
- if (DESTRUCTOR_NAME_P (name))
- parmtypes = TREE_CHAIN (parmtypes);
-
- dump_function_name (t);
-
- OB_PUTC ('(');
-
- if (parmtypes)
- dump_type (parmtypes, v);
- else
- OB_PUTS ("...");
-
- OB_PUTC (')');
-
- if (v && ! IDENTIFIER_TYPENAME_P (name))
- dump_type_suffix (TREE_TYPE (fntype), 1);
-
- if (TREE_CODE (fntype) == METHOD_TYPE)
- dump_readonly_or_volatile
- (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype))), before);
- }
-
- /* Handle the function name for a FUNCTION_DECL node, grokking operators
- and destructors properly. */
- static void
- dump_function_name (t)
- tree t;
- {
- tree name = DECL_NAME (t);
-
- /* There ought to be a better way to find out whether or not something is
- a destructor. */
- if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (t)))
- {
- OB_PUTC ('~');
- dump_decl (name, 0);
- }
- else if (IDENTIFIER_TYPENAME_P (name))
- {
- /* This cannot use the hack that the operator's return
- type is stashed off of its name because it may be
- used for error reporting. In the case of conflicting
- declarations, both will have the same name, yet
- the types will be different, hence the TREE_TYPE field
- of the first name will be clobbered by the second. */
- OB_PUTS ("operator ");
- dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
- }
- else if (IDENTIFIER_OPNAME_P (name))
- {
- char *name_string = operator_name_string (name);
- OB_PUTS ("operator ");
- OB_PUTCP (name_string);
- }
- else
- dump_decl (name, 0);
- }
-
- static void
- dump_char (c)
- char c;
- {
- switch (c)
- {
- case '\n':
- OB_PUTS ("\\n");
- break;
- case '\t':
- OB_PUTS ("\\t");
- break;
- case '\v':
- OB_PUTS ("\\v");
- break;
- case '\b':
- OB_PUTS ("\\b");
- break;
- case '\r':
- OB_PUTS ("\\r");
- break;
- case '\f':
- OB_PUTS ("\\f");
- break;
- case '\a':
- OB_PUTS ("\\a");
- break;
- case '\\':
- OB_PUTS ("\\\\");
- break;
- case '\'':
- OB_PUTS ("\\'");
- break;
- case '\"':
- OB_PUTS ("\\\"");
- break;
- default:
- if (isprint (c))
- OB_PUTC (c);
- else
- {
- sprintf (digit_buffer, "\\%03o", (int) c);
- OB_PUTCP (digit_buffer);
- }
- }
- }
-
- /* Print out a list of initializers (subr of dump_expr) */
- static void
- dump_expr_list (l)
- tree l;
- {
- while (l)
- {
- dump_expr (TREE_VALUE (l), 0);
- if (TREE_CHAIN (l))
- OB_PUTC2 (',', ' ');
- l = TREE_CHAIN (l);
- }
- }
-
- /* Print out an expression */
- static void
- dump_expr (t, nop)
- tree t;
- int nop; /* suppress parens */
- {
- switch (TREE_CODE (t))
- {
- case VAR_DECL:
- case PARM_DECL:
- case FIELD_DECL:
- case CONST_DECL:
- case FUNCTION_DECL:
- dump_decl (t, 0);
- break;
-
- case INTEGER_CST:
- {
- tree type = TREE_TYPE (t);
- my_friendly_assert (type != 0, 81);
-
- /* If it's an enum, output its tag, rather than its value. */
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- {
- char *p = enum_name_string (t, type);
- OB_PUTCP (p);
- }
- else if (type == char_type_node
- || type == signed_char_type_node
- || type == unsigned_char_type_node)
- {
- OB_PUTC ('\'');
- dump_char (TREE_INT_CST_LOW (t));
- OB_PUTC ('\'');
- }
- else if (TREE_INT_CST_HIGH (t)
- != (TREE_INT_CST_LOW (t) >> (HOST_BITS_PER_WIDE_INT - 1)))
- {
- tree val = t;
- if (TREE_INT_CST_HIGH (val) < 0)
- {
- OB_PUTC ('-');
- val = build_int_2 (~TREE_INT_CST_LOW (val),
- -TREE_INT_CST_HIGH (val));
- }
- /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
- systems? */
- {
- static char format[10]; /* "%x%09999x\0" */
- if (!format[0])
- sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4);
- sprintf (digit_buffer, format, TREE_INT_CST_HIGH (val),
- TREE_INT_CST_LOW (val));
- OB_PUTCP (digit_buffer);
- }
- }
- else
- OB_PUTI (TREE_INT_CST_LOW (t));
- }
- break;
-
- case REAL_CST:
- #ifndef REAL_IS_NOT_DOUBLE
- sprintf (digit_buffer, "%g", TREE_REAL_CST (t));
- #else
- {
- int i;
- char *p = (char *) &TREE_REAL_CST (t);
- sprintf (digit_buffer, "0x");
- for (i = 0; i < sizeof TREE_REAL_CST (t); i++)
- sprintf (digit_buffer + 2 + 2*i, "%02x", *p++);
- }
- #endif
- OB_PUTCP (digit_buffer);
- break;
-
- case STRING_CST:
- {
- char *p = TREE_STRING_POINTER (t);
- int len = TREE_STRING_LENGTH (t) - 1;
- int i;
-
- OB_PUTC ('\"');
- for (i = 0; i < len; i++)
- dump_char (p[i]);
- OB_PUTC ('\"');
- }
- break;
-
- case COMPOUND_EXPR:
- dump_binary_op (",", t);
- break;
-
- case COND_EXPR:
- OB_PUTC ('(');
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTS (" ? ");
- dump_expr (TREE_OPERAND (t, 1), 0);
- OB_PUTS (" : ");
- dump_expr (TREE_OPERAND (t, 2), 0);
- OB_PUTC (')');
- break;
-
- case SAVE_EXPR:
- if (TREE_HAS_CONSTRUCTOR (t))
- {
- OB_PUTS ("new ");
- dump_type (TREE_TYPE (TREE_TYPE (t)), 0);
- PARM_DECL_EXPR (t) = 1;
- }
- else
- {
- sorry ("operand of SAVE_EXPR not understood");
- goto error;
- }
- break;
-
- case NEW_EXPR:
- OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
- OB_PUTC ('(');
- dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
- OB_PUTC (')');
- break;
-
- case CALL_EXPR:
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTC2 (' ', '(');
- dump_expr_list (TREE_OPERAND (t, 1));
- OB_PUTC (')');
- break;
-
- case WITH_CLEANUP_EXPR:
- /* Note that this only works for G++ cleanups. If somebody
- builds a general cleanup, there's no way to represent it. */
- dump_expr (TREE_OPERAND (t, 0), 0);
- break;
-
- case TARGET_EXPR:
- /* Note that this only works for G++ target exprs. If somebody
- builds a general TARGET_EXPR, there's no way to represent that
- it initializes anything other that the parameter slot for the
- default argument. Note we may have cleared out the first
- operand in expand_expr, so don't go killing ourselves. */
- if (TREE_OPERAND (t, 1))
- dump_expr (TREE_OPERAND (t, 1), 0);
- break;
-
- case MODIFY_EXPR:
- case PLUS_EXPR:
- case MINUS_EXPR:
- case MULT_EXPR:
- case TRUNC_DIV_EXPR:
- case TRUNC_MOD_EXPR:
- case MIN_EXPR:
- case MAX_EXPR:
- case LSHIFT_EXPR:
- case RSHIFT_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- case BIT_AND_EXPR:
- case BIT_ANDTC_EXPR:
- case TRUTH_ANDIF_EXPR:
- case TRUTH_ORIF_EXPR:
- case LT_EXPR:
- case LE_EXPR:
- case GT_EXPR:
- case GE_EXPR:
- case EQ_EXPR:
- case NE_EXPR:
- dump_binary_op (opname_tab[(int) TREE_CODE (t)], t);
- break;
-
- case CEIL_DIV_EXPR:
- case FLOOR_DIV_EXPR:
- case ROUND_DIV_EXPR:
- dump_binary_op ("/", t);
- break;
-
- case CEIL_MOD_EXPR:
- case FLOOR_MOD_EXPR:
- case ROUND_MOD_EXPR:
- dump_binary_op ("%", t);
- break;
-
- case COMPONENT_REF:
- dump_binary_op (".", t);
- break;
-
- case CONVERT_EXPR:
- dump_unary_op ("+", t, nop);
- break;
-
- case ADDR_EXPR:
- if (TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL
- || TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST)
- dump_expr (TREE_OPERAND (t, 0), 0);
- else
- dump_unary_op ("&", t, nop);
- break;
-
- case INDIRECT_REF:
- if (TREE_HAS_CONSTRUCTOR (t))
- {
- t = TREE_OPERAND (t, 0);
- my_friendly_assert (TREE_CODE (t) == CALL_EXPR, 237);
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTC ('(');
- dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
- OB_PUTC (')');
- }
- else
- dump_unary_op ("*", t, nop);
- break;
-
- case NEGATE_EXPR:
- case BIT_NOT_EXPR:
- case TRUTH_NOT_EXPR:
- case PREDECREMENT_EXPR:
- case PREINCREMENT_EXPR:
- dump_unary_op (opname_tab [(int)TREE_CODE (t)], t, nop);
- break;
-
- case POSTDECREMENT_EXPR:
- case POSTINCREMENT_EXPR:
- OB_PUTC ('(');
- dump_expr (TREE_OPERAND (t, 0), 0);
- OB_PUTCP (opname_tab[(int)TREE_CODE (t)]);
- OB_PUTC (')');
- break;
-
- case NON_LVALUE_EXPR:
- /* FIXME: This is a KLUDGE workaround for a parsing problem. There
- should be another level of INDIRECT_REF so that I don't have to do
- this. */
- if (NEXT_CODE (t) == POINTER_TYPE)
- {
- tree next = TREE_TYPE (TREE_TYPE (t));
-
- while (TREE_CODE (next) == POINTER_TYPE)
- next = TREE_TYPE (next);
-
- if (TREE_CODE (next) == FUNCTION_TYPE)
- {
- if (!nop) OB_PUTC ('(');
- OB_PUTC ('*');
- dump_expr (TREE_OPERAND (t, 0), 1);
- if (!nop) OB_PUTC (')');
- break;
- }
- /* else FALLTHRU */
- }
- dump_expr (TREE_OPERAND (t, 0), 0);
- break;
-
- case NOP_EXPR:
- dump_expr (TREE_OPERAND (t, 0), nop);
- break;
-
- case CONSTRUCTOR:
- OB_PUTC ('{');
- dump_expr_list (CONSTRUCTOR_ELTS (t), 0);
- OB_PUTC ('}');
- break;
-
- /* This list is incomplete, but should suffice for now.
- It is very important that `sorry' does not call
- `report_error_function'. That could cause an infinite loop. */
- default:
- sorry ("`%s' not supported by dump_expr",
- tree_code_name[(int) TREE_CODE (t)]);
-
- /* fall through to ERROR_MARK... */
- case ERROR_MARK:
- error:
- OB_PUTCP ("/* error */");
- break;
- }
- }
-
- static void
- dump_binary_op (opstring, t)
- char *opstring;
- tree t;
- {
- OB_PUTC ('(');
- dump_expr (TREE_OPERAND (t, 0), 1);
- OB_PUTC (' ');
- OB_PUTCP (opstring);
- OB_PUTC (' ');
- dump_expr (TREE_OPERAND (t, 1), 1);
- OB_PUTC (')');
- }
-
- static void
- dump_unary_op (opstring, t, nop)
- char *opstring;
- tree t;
- int nop;
- {
- if (!nop) OB_PUTC ('(');
- OB_PUTCP (opstring);
- dump_expr (TREE_OPERAND (t, 0), 1);
- if (!nop) OB_PUTC (')');
- }
-
- char *
- fndecl_as_string (cname, fndecl, print_ret_type_p)
- tree cname, fndecl;
- int print_ret_type_p;
- {
- return decl_as_string (fndecl, print_ret_type_p);
- }
-
- /* Same, but handtype a _TYPE.
- Called from convert_to_reference, mangle_class_name_for_template,
- build_unary_op, and GNU_xref_decl. */
- char *
- type_as_string (typ, v)
- tree typ;
- int v;
- {
- OB_INIT ();
-
- dump_type (typ, v);
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
- }
-
- char *
- expr_as_string (decl, v)
- tree decl;
- int v;
- {
- OB_INIT ();
-
- dump_expr (decl, 1);
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
- }
-
- /* A cross between type_as_string and fndecl_as_string.
- Only called from substitute_nice_name. */
- char *
- decl_as_string (decl, v)
- tree decl;
- int v;
- {
- OB_INIT ();
-
- dump_decl (decl, v);
-
- OB_FINISH ();
-
- return (char *)obstack_base (&scratch_obstack);
- }
-
- char *
- cp_file_of (t)
- tree t;
- {
- if (TREE_CODE (t) == PARM_DECL)
- return DECL_SOURCE_FILE (DECL_CONTEXT (t));
- else
- return DECL_SOURCE_FILE (t);
- }
-
- int
- cp_line_of (t)
- tree t;
- {
- if (TREE_CODE (t) == PARM_DECL)
- return DECL_SOURCE_LINE (DECL_CONTEXT (t));
- else
- return DECL_SOURCE_LINE (t);
- }
-
- char *
- code_as_string (c, v)
- enum tree_code c;
- int v;
- {
- return tree_code_name [c];
- }
-
- char *
- language_as_string (c, v)
- enum languages c;
- int v;
- {
- switch (c)
- {
- case lang_c:
- return "C";
-
- case lang_cplusplus:
- return "C++";
-
- default:
- my_friendly_abort (355);
- }
- }
-