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

📄 cp-except.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
  finish_struct (t, list_of_fieldlists, 0, 0);  if (current_function_decl)    error ("cannot define exception inside function scope");  else    {      enum debug_info_type old_write_symbols = write_symbols;      write_symbols = NO_DEBUG;      /* Now build the constructor for this exception.  */      parmdecls = DECL_ARGUMENTS (ctor);      start_function (NULL_TREE, ctor, 0, 1);      store_parm_decls ();      pushlevel (0);      clear_last_expr ();      push_momentary ();      expand_start_bindings (0);      /* Move all the parameters to the fields, skipping `this'.  */      parmdecls = TREE_CHAIN (parmdecls);      /* Install `name' of this exception handler.  */      DECL_INITIAL (fields) = build_unary_op (ADDR_EXPR, edecl, 0);      fields = TREE_CHAIN (fields);      /* Install all the values.  */      while (fields)	{	  /* Set up the initialization for this field.  */	  DECL_INITIAL (fields) = parmdecls;	  fields = TREE_CHAIN (fields);	  parmdecls = TREE_CHAIN (parmdecls);	}      emit_base_init (t, 0);      finish_function (DECL_SOURCE_LINE (ctor), 1);      write_symbols = old_write_symbols;    }}voidend_exception_decls (){  last_exception_field_types = NULL_TREE;  last_exception_fields = NULL_TREE;}/* Statement-level exception semantics.  */voidcplus_expand_start_try (implicit)     int implicit;{  tree call_to_setjmp;  tree handler, ref;  /* Start a new block enclosing the whole handler.  */  if (implicit)    {      pushlevel_temporary (1);    }  else    {      pushlevel (0);      clear_last_expr ();      push_momentary ();      /* Encompass whole exception handler in one big binding contour.	 If RAISE should throw out of the whole TRY/EXCEPT block, call	 `expand_start_bindings' with argument of 1.  */      expand_start_bindings (0);    }  /* Allocate handler in that block.  It's real name will come later.     Note that it will be the first name in this binding contour.  */  handler = get_temp_name (EHS_type, 0);  DECL_INITIAL (handler) = error_mark_node;  finish_decl (handler, NULL_TREE, 0, 0);  /* Must come after call to `finish_decl', else the cleanup for the temp     for the handler will cause the contour we just created to be popped.  */  if (implicit)    declare_implicit_exception ();  /* Catch via `setjmp'.  */  ref = build_component_ref (handler, get_identifier ("handler"), NULL_TREE, 0);  call_to_setjmp = build_function_call (BISJ, build_tree_list (NULL_TREE, ref));  /* RAISE throws to EXCEPT part.  */  expand_start_try (build_binary_op (EQ_EXPR, call_to_setjmp, integer_zero_node), 0, 1);}/* If KEEP is 1, then declarations in the TRY statement are worth keeping.   If KEEP is 2, then the TRY statement was generated by the compiler.   If KEEP is 0, the declarations in the TRY statement contain errors.  */treecplus_expand_end_try (keep)     int keep;{  tree decls, decl, block;  if (keep < 2)    pop_implicit_try_blocks (NULL_TREE);  decls = getdecls ();  /* Emit code to avoid falling through into a default     handler that might come later.  */  expand_end_try ();  /* Pops binding contour local to TRY, and get the exception handler     object built by `...start_try'.  */  switch (keep)    {    case 0:      expand_end_bindings (decls, 0, 1);      block = poplevel (0, 0, 0);      pop_momentary ();       decl = getdecls ();      break;    case 1:      expand_end_bindings (decls, 1, 1);      block = poplevel (1, 1, 0);      pop_momentary ();      decl = getdecls ();      break;    default:      decl = tree_last (decls);      block = NULL_TREE;      break;    }  my_friendly_assert (TREE_CODE (decl) == VAR_DECL		      && TREE_TYPE (decl) == EHS_type, 203);  if (block)    {      BLOCK_HANDLER_BLOCK (block) = 1;      TREE_USED (block) = 1;    }  /* Pass it back so that its rtl can be bound to its name     (or vice versa).  */  return decl;}voidcplus_expand_start_except (name, decl)     tree name, decl;{  int yes;  tree tmp, init;  expand_start_except (0, 1);  /* This is internal `eh'.  */  current_exception_decl = decl;  current_exception_name_as_rtx    = expand_expr (build (COMPONENT_REF, ptr_type_node,			  current_exception_decl, TREE_OPERAND (EHS_name, 1)),		   0, 0, 0);  init = build (COMPONENT_REF, ptr_type_node, decl, TREE_OPERAND (EHS_parms, 1));  current_exception_parms_as_rtx = expand_expr (init, 0, 0, 0);  if (name)    {      /* Get the exception object into scope (user declared `ex').  */      tmp = pushdecl (build_decl (VAR_DECL, name, ptr_type_node));      DECL_INITIAL (tmp) = error_mark_node;      finish_decl (tmp, init, 0, 0);    }  current_exception_type = NULL_TREE;  yes = suspend_momentary ();  if (name)    {      /* From now on, send the user to our faked-up object.  */      current_exception_object = build1 (INDIRECT_REF, void_type_node, tmp);      IDENTIFIER_LOCAL_VALUE (name) = current_exception_object;    }  resume_momentary (yes);  /* Pop exception handler stack.  */  expand_assignment (EHS_decl, EHS_prev, 0, 0);}/* Generate the call to `unhandled_exception' that is appropriate   for this particular unhandled exception.  */static treecall_to_unhandled_exception (){  extern int lineno;  tree parms = tree_cons (NULL_TREE,			  combine_strings (build_string (strlen (input_filename + 1), input_filename)),			  build_tree_list (NULL_TREE, build_int_2 (lineno, 0)));  return build_function_call (BIUE, parms);}/* Note that this must be mirror image of `...start_try'.   DFAULT is the default clause, if there was one.   DFAULT is ERROR_MARK_NODE when this ends an implicit handler.  */voidcplus_expand_end_except (dfault)     tree dfault;{  extern tree expand_end_except (); /* stmt.c.  */  tree decls, raised;  if (dfault == NULL_TREE)    {      /* Uncaught exception at outermost level.  If raised locally,	 reraise the exception.  Otherwise, generate code to call `abort'.  */      if (in_try_block (1) == 0)	{	  expand_start_cond (build (EQ_EXPR, integer_type_node,				    exception_throw_decl, integer_zero_node), 0);	  expand_expr (call_to_unhandled_exception (), 0, VOIDmode, 0);	  expand_end_cond ();	}      /* Try the next handler.  */      if (! expand_escape_except ())	compiler_error ("except nesting botch");    }  raised = expand_end_except ();  decls = getdecls ();  expand_end_bindings (decls, decls != 0, 1);  poplevel (decls != 0, 1, 0);  /* Implicit handlers do not use the momentary obstack.  */  if (dfault != error_mark_node)    pop_momentary ();  if (! in_try_block (1))    {      /* Check that this function is not raising exceptions	 it is not supposed to.  */      while (raised)	{	  error_with_decl (TREE_VALUE (raised), "exception `%s' raised but not declared raisable");	  raised = TREE_CHAIN (raised);	}    }  else if (dfault == NULL_TREE || dfault == error_mark_node)    {      expand_start_cond (build (NE_EXPR, integer_type_node,				exception_throw_decl,				integer_zero_node), 0);      /* We fell off the end of this try block.  Try going to the next.	 The escape_label will be the beginning of the next try block.  */      if (! expand_escape_except ())	compiler_error ("except nesting botch");      expand_end_cond ();    }}/* Generate code to raise exception RAISE_ID.   If EXP is NULL_TREE, then PARMS is the list of parameters to use   for constructing this exception.   If EXP is non-NULL, then it is an already constructed object   of the kind that we want.   FOR_RERAISE is non-zero if this raise is called by reraise.  In   this case we do not need to emit extra gotos to avoid warning messages;   the caller will do that once after all the exceptions it reraises   are handled and raised.  */voidcplus_expand_raise (raise_id, parms, exp, for_reraise)     tree raise_id;     tree parms;     tree exp;     int for_reraise;{  /* Allocate new exception of appropriate type, passing     PARMS to its constructor.  */  tree cname, name;  tree decl;  tree xexp = exp;  cname = lookup_exception_cname (current_class_type, current_class_name, raise_id);  if (cname == error_mark_node)    return;  name = TREE_VALUE (raise_id);  decl = lookup_exception_object (cname, name, 1);  if (decl == NULL_TREE)    return;  if (exp == NULL_TREE)    {      exp = build_method_call (NULL_TREE, name, parms, NULL_TREE, LOOKUP_COMPLAIN);      if (exp == error_mark_node)	return;    }  if (in_try_block (1))    {      expand_raise (decl);    }  else if (! current_function_decl)    {      if (xexp == NULL_TREE)	error_with_decl (decl, "invalid raise of `%s' outside of functions");      else	error_with_decl (decl, "invalid reraise of `%s' outside of functions");    }  else    {      /* Test this raise against what this function permits.  */      tree names = TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl));      while (names)	{	  if (decl == TREE_TYPE (names))	    break;	  names = TREE_CHAIN (names);	}      if (names == NULL_TREE)	{	  error ("current function not declared to raise exception `%s'",		 IDENTIFIER_POINTER (name));	  return;	}    }  store_expr (exp, EHS_parms_as_rtx, 0);  /* Set the global exception handler stack's NAME field     to the `name' of this exception.  The global exception     handler stack is the container for the exception object     we just built.     We go through a function call to make life easier when debugging.  */#if 0  expand_assignment (EHS_name, build_unary_op (ADDR_EXPR, decl, 0), 0, 0);#else  parms = tree_cons (NULL_TREE, build_unary_op (ADDR_EXPR, EHS_name, 0),		     build_tree_list (NULL_TREE,				      build_unary_op (ADDR_EXPR, decl, 0)));  expand_expr (build_function_call (BIR, parms), 0, 0, 0);#endif  /* Activate thrower.  If we are inside a TRY statement,     we can cheat and not do this, saving a longjmp.  */  if (in_try_block (1) == 0)    {      sets_exception_throw_decl = 1;      emit_move_insn (DECL_RTL (exception_throw_decl), const1_rtx);    }  if (xexp == NULL_TREE)    {          /* Invoke destructors for current procedure or handler.  */      if (! expand_escape_except ())	compiler_error ("except nesting botch");      /* Throw via `longjmp'... Done as side-effect of goto.  */    }  /* To avoid spurious warning messages, we add a goto to the end     of the function.  This code is dead, and the compiler should     know how to delete it, but for now, we are stuck with it.  */  if (! for_reraise      && TREE_TYPE (DECL_RESULT (current_function_decl)) != void_type_node)    expand_null_return ();}extern tree cplus_exception_name ();treeansi_exception_object_lookup (type)     tree type;{  tree raise_id = cplus_exception_name (type);  tree decl;  decl = IDENTIFIER_GLOBAL_VALUE (raise_id);  if (decl == NULL_TREE || TREE_CODE (decl) != VAR_DECL)    {      push_obstacks_nochange ();      end_temporary_allocation ();      decl = build_decl (VAR_DECL, raise_id, ptr_type_node);      TREE_PUBLIC (decl) = 1;      TREE_STATIC (decl) = 1;      pushdecl_top_level (decl);      make_decl_rtl (decl, (char*)0, 1);      pop_obstacks ();    }  return decl;}/* Generate code to throw an exception using EXP.   Usng ANSI syntax and semantics.   If EXP is NULL_TREE< re-raise instead. */voidcplus_expand_throw (exp)     tree exp;{  tree parms;  int for_reraise;  /* Allocate new exception of appropriate type, passing     PARMS to its constructor.  */  tree decl = ansi_exception_object_lookup (TREE_TYPE (exp));  tree xexp = exp;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -