📄 error.c
字号:
/* Call-backs for C++ error reporting. This code is non-reentrant. Copyright (C) 1993, 94-97, 1998, 1999 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 "system.h"#include "tree.h"#include "cp-tree.h"#include "obstack.h"#include "toplev.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 F fndecl_as_string#define L language_as_string#define O op_as_string#define P parm_as_string#define Q assop_as_string#define T type_as_string#define V cv_as_string#define o (cp_printer *) 0cp_printer * cp_printers[256] ={/*0 1 2 3 4 5 6 7 8 9 A B C D E F */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x00 */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x10 */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x20 */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x30 */ o, A, o, C, D, E, F, o, o, o, o, o, L, o, o, O, /* 0x40 */ P, Q, o, o, T, o, V, o, o, o, o, o, o, o, o, o, /* 0x50 */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x60 */ o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, o, /* 0x70 */};#undef C#undef D#undef E#undef F#undef L#undef O#undef P#undef Q#undef T#undef V#undef o#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, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)(CST)); \ OB_PUTCP (digit_buffer); } while (0)# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));# define OB_END_TEMPLATE_ID() \ ((obstack_next_free (&scratch_obstack) != obstack_base (&scratch_obstack) \ && obstack_next_free (&scratch_obstack)[-1] == '>') \ ? OB_PUTC2 (' ', '>') : OB_PUTC ('>'))# define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))enum pad { none, before, after };static void dump_type PROTO((tree, int));static void dump_type_real PROTO((tree, int, int));static void dump_simple_decl PROTO((tree, tree, int));static void dump_decl PROTO((tree, int));static void dump_function_decl PROTO((tree, int));static void dump_expr PROTO((tree, int));static void dump_unary_op PROTO((char *, tree, int));static void dump_binary_op PROTO((char *, tree));static void dump_aggr_type PROTO((tree, int, int));static void dump_type_prefix PROTO((tree, int, int));static void dump_type_suffix PROTO((tree, int, int));static void dump_function_name PROTO((tree));static void dump_expr_list PROTO((tree));static void dump_global_iord PROTO((tree));static void dump_qualifiers PROTO((tree, enum pad));static void dump_char PROTO((int));static void dump_parameters PROTO((tree, int, int));static void dump_exception_spec PROTO((tree, int));static char *aggr_variety PROTO((tree));static tree ident_fndecl PROTO((tree));static int interesting_scope_p PROTO((tree));voidinit_error (){ gcc_obstack_init (&scratch_obstack); scratch_firstobj = (char *)obstack_alloc (&scratch_obstack, 0);}/* Returns nonzero if SCOPE is something we want to print for random decls. */static intinteresting_scope_p (scope) tree scope;{ if (scope == NULL_TREE || scope == global_namespace) return 0; return (TREE_CODE (scope) == NAMESPACE_DECL || AGGREGATE_TYPE_P (scope));}static voiddump_qualifiers (t, p) tree t; enum pad p;{ if (TYPE_QUALS (t)) { if (p == before) OB_PUTC (' '); switch (TYPE_QUALS (t)) { case TYPE_QUAL_CONST: OB_PUTS ("const"); break; case TYPE_QUAL_VOLATILE: OB_PUTS ("volatile"); break; case TYPE_QUAL_RESTRICT: OB_PUTS ("__restrict"); break; case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE: OB_PUTS ("const volatile"); break; case TYPE_QUAL_CONST | TYPE_QUAL_RESTRICT: OB_PUTS ("const __restrict"); break; case TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: OB_PUTS ("volatile __restrict"); break; case TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE | TYPE_QUAL_RESTRICT: OB_PUTS ("const volatile __restrict"); break; default: my_friendly_abort (0); } 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_real (t, v, canonical_name) tree t; int v; /* verbose? */ int canonical_name;{ 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: /* A list of function parms. */ dump_parameters (t, 0, canonical_name); break; case IDENTIFIER_NODE: OB_PUTID (t); break; case TREE_VEC: dump_type_real (BINFO_TYPE (t), v, canonical_name); break; case RECORD_TYPE: case UNION_TYPE: case ENUMERAL_TYPE: if (TYPE_LANG_SPECIFIC (t) && (IS_SIGNATURE_POINTER (t) || IS_SIGNATURE_REFERENCE (t))) { dump_qualifiers (t, after); dump_type_real (SIGNATURE_TYPE (t), v, canonical_name); if (IS_SIGNATURE_POINTER (t)) OB_PUTC ('*'); else OB_PUTC ('&'); } else dump_aggr_type (t, v, canonical_name); break; case TYPE_DECL: case TEMPLATE_DECL: case NAMESPACE_DECL: dump_decl (t, v); break; case COMPLEX_TYPE: OB_PUTS ("complex "); dump_type_real (TREE_TYPE (t), v, canonical_name); 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: { tree type; dump_qualifiers (t, after); type = canonical_name ? TYPE_MAIN_VARIANT (t) : t; if (TYPE_NAME (type) && TYPE_IDENTIFIER (type)) OB_PUTID (TYPE_IDENTIFIER (type)); else /* Types like intQI_type_node and friends have no names. These don't come up in user error messages, but it's nice to be able to print them from the debugger. */ OB_PUTS ("{anonymous}"); } break; case TEMPLATE_TEMPLATE_PARM: if (!TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t)) { /* For parameters inside template signature. */ if (TYPE_IDENTIFIER (t)) OB_PUTID (TYPE_IDENTIFIER (t)); else OB_PUTS ("{anonymous template template parm}"); } else { int i; tree args = TYPE_TI_ARGS (t); OB_PUTID (TYPE_IDENTIFIER (t)); OB_PUTC ('<'); for (i = 0; i < TREE_VEC_LENGTH (args); i++) { tree arg = TREE_VEC_ELT (args, i); if (TREE_CODE_CLASS (TREE_CODE (arg)) == 't' || TREE_CODE (arg) == TEMPLATE_DECL) dump_type_real (arg, 0, canonical_name); else dump_expr (arg, 0); if (i < TREE_VEC_LENGTH (args)-1) OB_PUTC2 (',', ' '); } OB_END_TEMPLATE_ID (); } break; case TEMPLATE_TYPE_PARM: dump_qualifiers (t, after); if (TYPE_IDENTIFIER (t)) OB_PUTID (TYPE_IDENTIFIER (t)); else OB_PUTS ("{anonymous template type parm}"); 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, canonical_name); dump_type_suffix (t, v, canonical_name); break; case TYPENAME_TYPE: OB_PUTS ("typename "); dump_type_real (TYPE_CONTEXT (t), 0, canonical_name); OB_PUTS ("::"); dump_decl (TYPENAME_TYPE_FULLNAME (t), v); break; case TYPEOF_TYPE: OB_PUTS ("__typeof ("); dump_expr (TYPE_FIELDS (t), 1); OB_PUTC (')'); 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";}static voiddump_type (t, v) tree t; int v; /* verbose? */{ dump_type_real (t, v, 0);}/* Print out a class declaration, in the form `class foo'. */static voiddump_aggr_type (t, v, canonical_name) tree t; int v; /* verbose? */ int canonical_name;{ tree name; char *variety = aggr_variety (t); dump_qualifiers (t, after); if (v > 0) { OB_PUTCP (variety); OB_PUTC (' '); } name = TYPE_NAME (canonical_name ? TYPE_MAIN_VARIANT (t) : t); if (name && CP_DECL_CONTEXT (name) != global_namespace) { /* 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, canonical_name) tree t; int v; /* verbosity */ int canonical_name;{ if (TYPE_PTRMEMFUNC_P (t)) { t = TYPE_PTRMEMFUNC_FN_TYPE (t); goto offset_type; } switch (TREE_CODE (t)) { case POINTER_TYPE: case REFERENCE_TYPE: { tree sub = TREE_TYPE (t); dump_type_prefix (sub, v, canonical_name); /* A tree for a member pointer looks like pointer to offset, so let the OFFSET_TYPE case handle it. */ if (!TYPE_PTRMEM_P (t)) { 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_QUALS (sub) == TYPE_UNQUALIFIED) break; /* But we do want "char *const *" */ default: OB_PUTC (' '); } if (TREE_CODE (t) == POINTER_TYPE) OB_PUTC ('*'); else OB_PUTC ('&'); dump_qualifiers (t, none); } } break; case OFFSET_TYPE: offset_type: dump_type_prefix (TREE_TYPE (t), v, canonical_name); if (TREE_CODE (t) == OFFSET_TYPE) /* pmfs deal with this in d_t_p */ { OB_PUTC (' '); dump_type_real (TYPE_OFFSET_BASETYPE (t), 0, canonical_name); OB_PUTC2 (':', ':'); } OB_PUTC ('*'); dump_qualifiers (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, canonical_name); OB_PUTC2 (' ', '('); break; case METHOD_TYPE: dump_type_prefix (TREE_TYPE (t), v, canonical_name); OB_PUTC2 (' ', '('); dump_aggr_type (TYPE_METHOD_BASETYPE (t), 0, canonical_name); OB_PUTC2 (':', ':'); break; case ARRAY_TYPE: dump_type_prefix (TREE_TYPE (t), v, canonical_name); 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 TEMPLATE_TEMPLATE_PARM: case TREE_LIST: case TYPE_DECL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -