⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-except.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 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 + -