📄 cp-except.c
字号:
/* Handle exceptional things in C++. Copyright (C) 1989, 1992 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com)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, 675 Mass Ave, Cambridge, MA 02139, USA. *//* High-level class interface. */#define NULL 0/* This should be part of `ansi_opname', or at least be defined by the std. */#define EXCEPTION_NAME_PREFIX "__ex"#define EXCEPTION_NAME_LENGTH 4#include "config.h"#include "tree.h"#include "rtl.h"#include "cp-tree.h"#include "flags.h"/* On Suns this can get you to the right definition if you set the right value for TARGET. */#include <setjmp.h>#ifdef sequent/* Can you believe they forgot this? */#define _JBLEN 11#endif#ifndef _JBLEN#define _JBLEN (sizeof(jmp_buf)/sizeof(int))#endifvoid init_exception_processing ();void init_exception_processing_1 ();/* If non-zero, a VAR_DECL whose cleanup will cause a throw to the next exception handler. Its value says whether to throw or not. In the case of functions which do not issue a RAISE, it should be possible to optimize away this VAR_DECL (and overhead associated with it). */tree exception_throw_decl;/* Use this to know that we did not set `exception_throw_decl', until GCC optimizer is smart enough to figure it out for itself. */int sets_exception_throw_decl;/* The exception `type' currently in scope, or NULL_TREE if none. */tree current_exception_type;/* The exception handler object for the given scope. */tree current_exception_decl;rtx current_exception_name_as_rtx;rtx current_exception_parms_as_rtx;/* The ``object'' view of the current exception parameters. We cast up from the `parms' field to `current_exception_type'. */tree current_exception_object;/* Cache `setjmp', `longjmp', `raise_exception', and `unhandled_exception' after default conversion. Maybe later they will get built-in. */static tree BISJ, BILJ, BIR, BIUE;/* Local variables which give the appearance that exception handling is part of the language and the execution model. *//* The type of the exception handler stack. */static tree EHS_type;/* The global handler stack. */tree EHS_decl;/* Cached component refs to fields of `EHS_decl'. */static tree EHS_prev, EHS_handler, EHS_parms, EHS_name;static rtx EHS_parms_as_rtx, EHS_name_as_rtx;/* The parameter names of this exception type. */static tree last_exception_fields;static tree last_exception_field_types;/* When ID is VOID_TYPE_NODE, it means ``raise all''. Cannot be inline, since it uses `alloca', and that breaks code which pushes the result of this function on the stack. */static treeexception_object_name (prefix, id) tree prefix; tree id;{ /* First, cons up the `name' of this exception. */ char *name; int length = (id == void_type_node ? 3 : IDENTIFIER_LENGTH (id)) + EXCEPTION_NAME_LENGTH; if (prefix) length += IDENTIFIER_LENGTH (prefix) + 2; name = (char *)alloca (length); strcpy (name, EXCEPTION_NAME_PREFIX); length = EXCEPTION_NAME_LENGTH; if (prefix) { strcpy (name + length, IDENTIFIER_POINTER (prefix)); name[length + IDENTIFIER_LENGTH (prefix)] = JOINER; length += IDENTIFIER_LENGTH (prefix) + 1; } if (id == void_type_node) strcpy (name + length, "all"); else strcpy (name + length, IDENTIFIER_POINTER (id)); return get_identifier (name);}treelookup_exception_cname (ctype, cname, raise_id) tree ctype, cname; tree raise_id;{ tree this_cname = TREE_PURPOSE (raise_id); if (this_cname == NULL_TREE) { if (cname) { tree name = TREE_VALUE (raise_id); if (purpose_member (name, CLASSTYPE_TAGS (ctype))) this_cname = cname; } } else if (this_cname == void_type_node) this_cname = NULL_TREE; else if (TREE_CODE (this_cname) != IDENTIFIER_NODE) { sorry ("multiple scope refs in `cplus_expand_raise_stmt'"); this_cname = error_mark_node; } return this_cname;}treelookup_exception_tname (oname) tree oname;{ return get_identifier (IDENTIFIER_POINTER (oname) + EXCEPTION_NAME_LENGTH);}treelookup_exception_object (cname, name, complain) tree cname, name; int complain;{ tree oname; tree decl; if (cname == void_type_node) cname = NULL_TREE; else if (cname && TREE_CODE (cname) != IDENTIFIER_NODE) { sorry ("multiple scope refs in `lookup_exception_object'"); cname = NULL_TREE; } oname = exception_object_name (cname, name); decl = IDENTIFIER_GLOBAL_VALUE (oname); if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL) { if (complain) { push_obstacks_nochange (); if (cname) error ("no exception name object for name `%s::%s'", IDENTIFIER_POINTER (cname), IDENTIFIER_POINTER (name)); else error ("no exception name object for name `%s'", IDENTIFIER_POINTER (name)); end_temporary_allocation (); /* Avoid further error messages. */ pushdecl_top_level (build_lang_field_decl (VAR_DECL, exception_object_name (cname, name), error_mark_node)); pop_obstacks (); } return NULL_TREE; } return decl;}treelookup_exception_type (ctype, cname, raise_id) tree ctype, cname; tree raise_id;{ tree name = TREE_VALUE (raise_id); tree purpose = TREE_PURPOSE (raise_id); if (cname && purpose == NULL_TREE) purpose = cname; if (purpose && purpose != void_type_node) { tree link = NULL_TREE; if (TREE_CODE (purpose) != IDENTIFIER_NODE) { sorry ("multiple scope refs in `lookup_exception_type'"); TREE_PURPOSE (raise_id) = NULL_TREE; return NULL_TREE; } if (! is_aggr_typedef (purpose, 1)) return NULL_TREE; ctype = IDENTIFIER_TYPE_VALUE (purpose); link = purpose_member (name, CLASSTYPE_TAGS (ctype)); if (link) return TREE_VALUE (link); } ctype = lookup_name (name, 1); if (ctype && TREE_CODE (ctype) == TYPE_DECL) ctype = TREE_TYPE (ctype); if (ctype && TREE_CODE (ctype) == RECORD_TYPE && CLASSTYPE_DECLARED_EXCEPTION (ctype)) return ctype; return NULL_TREE;}treefinish_exception (e, list_of_fieldlists) tree e; tree list_of_fieldlists;{ tree parmtypes = NULL_TREE, name_field; tree cname = TYPE_NAME (e); if (TREE_CODE (cname) == TYPE_DECL) cname = DECL_NAME (cname); if (last_exception_fields) error ("cannot declare exceptions within exceptions"); if (list_of_fieldlists && ! ANON_AGGRNAME_P (cname)) error_with_aggr_type (e, "exception name `%s' must follow body declaration"); if (list_of_fieldlists) { tree prev, field; /* Note: no public, private, or protected allowed. */ if (TREE_CHAIN (list_of_fieldlists)) error ("visibility declarations invalid in exception declaration"); else if (TREE_PURPOSE (list_of_fieldlists) != (tree)visibility_default) error ("visibility declarations invalid in exception declaration"); TREE_PURPOSE (list_of_fieldlists) = (tree)visibility_default; /* Note also: no member function declarations allowed. */ for (prev = 0, field = TREE_VALUE (list_of_fieldlists); field; prev = field, field = TREE_CHAIN (field)) { switch (TREE_CODE (field)) { case FIELD_DECL: /* ok. */ parmtypes = tree_cons (NULL_TREE, TREE_TYPE (field), parmtypes); continue; case FUNCTION_DECL: error_with_decl (field, "declaration of function `%s' in exception invalid"); break; case VAR_DECL: if (TREE_STATIC (field)) error_with_decl (field, "declaration of static variable `%s' in exception invalid"); else error_with_decl (field, "declaration of constant field `%s' in exception invalid"); break; case CONST_DECL: error_with_decl (field, "declaration of enum value `%s' in exception invalid"); break; case SCOPE_REF: error ("use of `::' in exception context invalid"); break; } if (prev) TREE_CHAIN (prev) = TREE_CHAIN (field); else TREE_VALUE (list_of_fieldlists) = TREE_CHAIN (field); } } /* Now that we've cleaned up the fields, add a name identifier at front. */ name_field = build_lang_field_decl (FIELD_DECL, get_identifier ("__name"), ptr_type_node); if (list_of_fieldlists) { TREE_CHAIN (name_field) = TREE_VALUE (list_of_fieldlists); TREE_VALUE (list_of_fieldlists) = name_field; } else list_of_fieldlists = build_tree_list (NULL_TREE, name_field); last_exception_fields = TREE_VALUE (list_of_fieldlists); if (parmtypes) { last_exception_field_types = nreverse (parmtypes); /* Set the TREE_CHAIN of what is now at the end of the list to `void_list_node'. */ TREE_CHAIN (parmtypes) = void_list_node; } else last_exception_field_types = void_list_node; popclass (0);#if 0 /* Remove aggregate types from the list of tags, since these appear at global scope. */ while (x && IS_AGGR_TYPE (TREE_VALUE (x))) x = TREE_CHAIN (x); CLASSTYPE_TAGS (t) = x; y = x; while (x) { if (IS_AGGR_TYPE (TREE_VALUE (x))) TREE_CHAIN (y) = TREE_CHAIN (x); x = TREE_CHAIN (x); }#endif if (flag_cadillac) cadillac_finish_exception (e); return e;}voidfinish_exception_decl (cname, decl) tree cname, decl;{ /* In cp-decl.h. */ extern tree last_function_parms; /* An exception declaration. */ tree t, ctor; tree parmdecls = NULL_TREE, fields; tree list_of_fieldlists = temp_tree_cons (NULL_TREE, copy_list (last_exception_fields), NULL_TREE); tree edecl = build_lang_field_decl (VAR_DECL, exception_object_name (cname, DECL_NAME (decl)), ptr_type_node); DECL_LANGUAGE (edecl) = lang_c; TREE_STATIC (edecl) = 1; TREE_PUBLIC (edecl) = 1; finish_decl (pushdecl (edecl), 0, 0, 0); /* Now instantiate the exception decl. */ t = xref_tag (exception_type_node, DECL_NAME (decl), NULL_TREE); /* finish_struct will pop this. */ pushclass (t, 0); /* Now add a constructor which takes as parameters all the types we just defined. */ ctor = build_lang_decl (FUNCTION_DECL, DECL_NAME (decl), build_cplus_method_type (t, TYPE_POINTER_TO (t), last_exception_field_types)); /* Don't take `name'. The constructor handles that. */ fields = TREE_CHAIN (TREE_VALUE (list_of_fieldlists)); while (fields) { tree parm = build_decl (PARM_DECL, DECL_NAME (fields), TREE_TYPE (fields)); /* Since there is a prototype, args are passed in their own types. */ DECL_ARG_TYPE (parm) = TREE_TYPE (parm);#ifdef PROMOTE_PROTOTYPES if (TREE_CODE (TREE_TYPE (fields)) == INTEGER_TYPE && TYPE_PRECISION (TREE_TYPE (fields)) < TYPE_PRECISION (integer_type_node)) DECL_ARG_TYPE (parm) = integer_type_node;#endif TREE_CHAIN (parm) = parmdecls; parmdecls = parm; fields = TREE_CHAIN (fields); } fields = TREE_VALUE (list_of_fieldlists); last_function_parms = nreverse (parmdecls); DECL_CONSTRUCTOR_P (ctor) = 1; TYPE_HAS_CONSTRUCTOR (t) = 1; grokclassfn (t, DECL_NAME (decl), ctor, NO_SPECIAL, NULL_TREE); DECL_EXTERNAL (ctor) = 1; TREE_STATIC (ctor) = 1; TREE_PUBLIC (ctor) = 0; DECL_INLINE (ctor) = 1; make_decl_rtl (ctor, 0, 1); finish_decl (ctor, NULL_TREE, 0, 0); TREE_CHAIN (ctor) = TREE_VALUE (list_of_fieldlists); TREE_VALUE (list_of_fieldlists) = ctor;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -