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

📄 except.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
{  return build_component_ref (get_eh_info (), get_identifier ("handlers"),			      NULL_TREE, 0);}#endif/* Build a type value for use at runtime for a type that is matched   against by the exception handling system.  */static treebuild_eh_type_type (type)     tree type;{  const char *typestring;  tree exp;  if (type == error_mark_node)    return error_mark_node;  /* peel back references, so they match.  */  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* Peel off cv qualifiers.  */  type = TYPE_MAIN_VARIANT (type);  if (flag_rtti)    return build1 (ADDR_EXPR, ptr_type_node, get_typeid_1 (type));  typestring = build_overload_name (type, 1, 1);  exp = combine_strings (build_string (strlen (typestring)+1, typestring));  return build1 (ADDR_EXPR, ptr_type_node, exp);}/* Build the address of a runtime type for use in the runtime matching   field of the new exception model */static treebuild_eh_type_type_ref (type)     tree type;{  const char *typestring;  tree exp;  if (type == error_mark_node)    return error_mark_node;  /* peel back references, so they match.  */  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* Peel off cv qualifiers.  */  type = TYPE_MAIN_VARIANT (type);  push_obstacks_nochange ();  end_temporary_allocation ();  if (flag_rtti)    {      exp = get_tinfo_fn (type);      TREE_USED (exp) = 1;      mark_inline_for_output (exp);      exp = build1 (ADDR_EXPR, ptr_type_node, exp);    }  else    {      typestring = build_overload_name (type, 1, 1);      exp = combine_strings (build_string (strlen (typestring)+1, typestring));      exp = build1 (ADDR_EXPR, ptr_type_node, exp);    }  pop_obstacks ();  return (exp);}/* Build a type value for use at runtime for a exp that is thrown or   matched against by the exception handling system.  */static treebuild_eh_type (exp)     tree exp;{  if (flag_rtti)    {      exp = build_typeid (exp);      return build1 (ADDR_EXPR, ptr_type_node, exp);    }  return build_eh_type_type (TREE_TYPE (exp));}/* This routine is called to mark all the symbols representing runtime   type functions in the exception table as haveing been referenced.   This will make sure code is emitted for them. Called from finish_file. */void mark_all_runtime_matches () {  int x,num;  void **ptr;  tree exp;    num = find_all_handler_type_matches (&ptr);  if (num == 0 || ptr == NULL)    return;    for (x=0; x <num; x++)    {      exp = (tree) ptr[x];      if (TREE_CODE (exp) == ADDR_EXPR)        {          exp = TREE_OPERAND (exp, 0);          if (TREE_CODE (exp) == FUNCTION_DECL)            TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (exp)) = 1;        }    }    free (ptr);}/* Build up a call to __cp_pop_exception, to destroy the exception object   for the current catch block.  HANDLER is either true or false, telling   the library whether or not it is being called from an exception handler;   if it is, it avoids destroying the object on rethrow.  */static treedo_pop_exception (){  tree fn, cleanup;  fn = get_identifier ("__cp_pop_exception");  if (IDENTIFIER_GLOBAL_VALUE (fn))    fn = IDENTIFIER_GLOBAL_VALUE (fn);  else    {      /* Declare void __cp_pop_exception (void *),	 as defined in exception.cc. */      push_obstacks_nochange ();      end_temporary_allocation ();      fn = build_lang_decl	(FUNCTION_DECL, fn,	 build_function_type (void_type_node, tree_cons			      (NULL_TREE, ptr_type_node, void_list_node)));      DECL_EXTERNAL (fn) = 1;      TREE_PUBLIC (fn) = 1;      DECL_ARTIFICIAL (fn) = 1;      pushdecl_top_level (fn);      make_function_rtl (fn);      pop_obstacks ();    }  mark_used (fn);  /* Arrange to do a dynamically scoped cleanup upon exit from this region.  */  cleanup = lookup_name (get_identifier ("__exception_info"), 0);  cleanup = build_function_call (fn, expr_tree_cons				 (NULL_TREE, cleanup, NULL_TREE));  return cleanup;}/* This routine creates the cleanup for the current exception.  */static voidpush_eh_cleanup (){  int yes;  yes = suspend_momentary ();  /* All cleanups must last longer than normal.  */  expand_decl_cleanup (NULL_TREE, do_pop_exception ());  resume_momentary (yes);}/* Build up a call to terminate on the function obstack, for use as an   exception handler.  */static treebuild_terminate_handler (){  int yes = suspend_momentary ();  tree term = build_function_call (Terminate, NULL_TREE);  resume_momentary (yes);  return term;}/* Call this to start a catch block. Typename is the typename, and identifier   is the variable to place the object in or NULL if the variable doesn't   matter.  If typename is NULL, that means its a "catch (...)" or catch   everything.  In that case we don't need to do any type checking.   (ie: it ends up as the "else" clause rather than an "else if" clause) */voidexpand_start_catch_block (declspecs, declarator)     tree declspecs, declarator;{  tree decl;  if (processing_template_decl)    {      if (declspecs)	{	  decl = grokdeclarator (declarator, declspecs, CATCHPARM,				 1, NULL_TREE);	  pushdecl (decl);	  decl = build_min_nt (DECL_STMT, copy_to_permanent (declarator),			       copy_to_permanent (declspecs),			       NULL_TREE);	  add_tree (decl);	}      return;    }  if (! doing_eh (1))    return;  process_start_catch_block (declspecs, declarator);}/* This function performs the expand_start_catch_block functionality for    exceptions implemented in the new style. __throw determines whether   a handler needs to be called or not, so the handler itself has to do   nothing additional. */static void process_start_catch_block (declspecs, declarator)     tree declspecs, declarator;{  tree decl = NULL_TREE;  tree init;  /* Create a binding level for the eh_info and the exception object     cleanup.  */  pushlevel (0);  expand_start_bindings (0);  if (declspecs)    {      decl = grokdeclarator (declarator, declspecs, CATCHPARM, 1, NULL_TREE);      if (decl == NULL_TREE)	error ("invalid catch parameter");    }  if (decl)    start_catch_handler (build_eh_type_type_ref (TREE_TYPE (decl)));  else    start_catch_handler (CATCH_ALL_TYPE);  emit_line_note (input_filename, lineno);  push_eh_info ();  if (decl)    {      tree exp;      tree init_type;      /* Make sure we mark the catch param as used, otherwise we'll get	 a warning about an unused ((anonymous)).  */      TREE_USED (decl) = 1;      /* Figure out the type that the initializer is.  */      init_type = TREE_TYPE (decl);      if (TREE_CODE (init_type) != REFERENCE_TYPE	  && TREE_CODE (init_type) != POINTER_TYPE)	init_type = build_reference_type (init_type);      exp = get_eh_value ();      /* Since pointers are passed by value, initialize a reference to	 pointer catch parm with the address of the value slot.  */      if (TREE_CODE (init_type) == REFERENCE_TYPE	  && TREE_CODE (TREE_TYPE (init_type)) == POINTER_TYPE)	exp = build_unary_op (ADDR_EXPR, exp, 1);      exp = ocp_convert (init_type , exp, CONV_IMPLICIT|CONV_FORCE_TEMP, 0);      push_eh_cleanup ();      /* Create a binding level for the parm.  */      pushlevel (0);      expand_start_bindings (0);      init = convert_from_reference (exp);      /* If the constructor for the catch parm exits via an exception, we         must call terminate.  See eh23.C.  */      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))	{	  /* Generate the copy constructor call directly so we can wrap it.	     See also expand_default_init.  */	  init = ocp_convert (TREE_TYPE (decl), init,			      CONV_IMPLICIT|CONV_FORCE_TEMP, 0);	  init = build (TRY_CATCH_EXPR, TREE_TYPE (init), init,			build_terminate_handler ());	}      /* Let `cp_finish_decl' know that this initializer is ok.  */      DECL_INITIAL (decl) = init;      decl = pushdecl (decl);      start_decl_1 (decl);      cp_finish_decl (decl, init, NULL_TREE, 0,		      LOOKUP_ONLYCONVERTING|DIRECT_BIND);    }  else    {      push_eh_cleanup ();      /* Create a binding level for the parm.  */      pushlevel (0);      expand_start_bindings (0);      /* Fall into the catch all section.  */    }  emit_line_note (input_filename, lineno);}/* Call this to end a catch block.  Its responsible for emitting the   code to handle jumping back to the correct place, and for emitting   the label to jump to if this catch block didn't match.  */voidexpand_end_catch_block (){  if (! doing_eh (1))    return;  /* Cleanup the EH parameter.  */  expand_end_bindings (getdecls (), kept_level_p (), 0);  poplevel (kept_level_p (), 1, 0);        /* Cleanup the EH object.  */  expand_end_bindings (getdecls (), kept_level_p (), 0);  poplevel (kept_level_p (), 1, 0);  /* Fall to outside the try statement when done executing handler and     we fall off end of handler.  This is jump Lresume in the     documentation.  */  expand_goto (top_label_entry (&caught_return_label_stack));  end_catch_handler ();}/* An exception spec is implemented more or less like:   try {     function body;   } catch (...) {     void *p[] = { typeid(raises) };     __check_eh_spec (p, count);   }   __check_eh_spec in exception.cc handles all the details.  */voidexpand_start_eh_spec (){  expand_start_try_stmts ();}static voidexpand_end_eh_spec (raises)     tree raises;{  tree tmp, fn, decl, types = NULL_TREE;  int count = 0;  expand_start_all_catch ();  expand_start_catch_block (NULL_TREE, NULL_TREE);  /* Build up an array of type_infos.  */  for (; raises && TREE_VALUE (raises); raises = TREE_CHAIN (raises))    {      types = expr_tree_cons	(NULL_TREE, build_eh_type_type (TREE_VALUE (raises)), types);      ++count;    }  types = build_nt (CONSTRUCTOR, NULL_TREE, types);  TREE_HAS_CONSTRUCTOR (types) = 1;  /* We can't pass the CONSTRUCTOR directly, so stick it in a variable.  */  tmp = build_cplus_array_type (const_ptr_type_node, NULL_TREE);  decl = build_decl (VAR_DECL, NULL_TREE, tmp);  DECL_ARTIFICIAL (decl) = 1;  DECL_INITIAL (decl) = types;  cp_finish_decl (decl, types, NULL_TREE, 0, 0);

⌨️ 快捷键说明

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