📄 error.c
字号:
/* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc. This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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 ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. */#include "config.h"#include "tree.h"#include "cp-tree.h"#include "obstack.h"#include <ctype.h>typedef char* cp_printer ();#define A args_as_string#define C code_as_string#define D decl_as_string#define E expr_as_string#define L language_as_string#define O op_as_string#define P parm_as_string#define T type_as_string#define V cv_as_string#define _ (cp_printer *) 0cp_printer * cp_printers[256] ={ /*0 1 2 3 4 5 6 7 8 9 A B C D E F */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x00 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x10 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x20 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x30 */ _, A, _, C, D, E, _, _, _, _, _, _, L, _, _, O, /* 0x40 */ P, _, _, _, T, _, V, _, _, _, _, _, _, _, _, _, /* 0x50 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x60 */ _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, _, /* 0x70 */};#undef C#undef D#undef E#undef L#undef O#undef P#undef T#undef V#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 OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));# 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 ();voidinit_error (){ gcc_obstack_init (&scratch_obstack); scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);}enum pad { none, before, after };static voiddump_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_READONLY (t) && TYPE_VOLATILE (t)) OB_PUTC (' '); 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 voiddump_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: if (TYPE_LANG_SPECIFIC (t) && (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t))) { if (TYPE_READONLY (t) | TYPE_VOLATILE (t)) dump_readonly_or_volatile (t); dump_type (SIGNATURE_TYPE (t), v); if (IS_SIGNATURE_POINTER (t)) OB_PUTC ('*'); else OB_PUTC ('&'); } else dump_aggr_type (t, v); break; case TYPE_DECL: dump_decl (t, v); 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: case BOOLEAN_TYPE: dump_readonly_or_volatile (t, after); OB_PUTID (TYPE_IDENTIFIER (t)); break; case TEMPLATE_TYPE_PARM: OB_PUTID (TYPE_IDENTIFIER (t)); 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: sorry ("`%s' not supported by dump_type", tree_code_name[(int) TREE_CODE (t)]); }}static char *aggr_variety (t) tree t;{ if (TREE_CODE (t) == ENUMERAL_TYPE) return "enum"; else if (TREE_CODE (t) == UNION_TYPE) return "union"; else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t)) return "class"; else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t)) return "signature"; else return "struct";}/* Print out a class declaration, in the form `class foo'. */static voiddump_aggr_type (t, v) tree t; int v; /* verbose? */{ tree name; char *variety = aggr_variety (t); dump_readonly_or_volatile (t, after); if (v > 0) { OB_PUTCP (variety); OB_PUTC (' '); } name = TYPE_NAME (t); if (name && DECL_CONTEXT (name)) { /* FUNCTION_DECL or RECORD_TYPE */ dump_decl (DECL_CONTEXT (name), 0); OB_PUTC2 (':', ':'); } /* kludge around weird behavior on g++.brendan/line1.C */ if (name && TREE_CODE (name) != IDENTIFIER_NODE) name = DECL_NAME (name); if (name == 0 || 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 voiddump_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 ARRAY_TYPE: OB_PUTC2 (' ', '('); 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 ARRAY_TYPE: OB_PUTC2 (' ', '('); 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 OFFSET_TYPE: offset_type: dump_type_prefix (TREE_TYPE (t), v); if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ { OB_PUTC (' '); dump_type (TYPE_OFFSET_BASETYPE (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: dump_type_prefix (TREE_TYPE (t), v); OB_PUTC2 (' ', '('); break; case METHOD_TYPE: dump_type_prefix (TREE_TYPE (t), v); OB_PUTC2 (' ', '('); dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0); 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 BOOLEAN_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: sorry ("`%s' not supported by dump_type_prefix", tree_code_name[(int) TREE_CODE (t)]); }}static voiddump_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: if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE) OB_PUTC (')'); 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 BOOLEAN_TYPE: case REAL_TYPE: case RECORD_TYPE: case TEMPLATE_TYPE_PARM: case TREE_LIST: case TYPE_DECL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -