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

📄 rtti.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
  TREE_TYPE (name) = copy_to_permanent (type);  pushdecl_top_level (d);  make_function_rtl (d);  mark_inline_for_output (d);  pop_obstacks ();  return d;}/* Likewise, but also mark it used.  Called by various EH and RTTI code.  */treeget_tinfo_fn (type)     tree type;{  tree d = get_tinfo_fn_unused (type);  mark_used (d);  return d;}treeget_typeid_1 (type)     tree type;{  tree t;  t = build_call    (get_tinfo_fn (type), TREE_TYPE (tinfo_fn_type), NULL_TREE);  return convert_from_reference (t);}  /* Return the type_info object for TYPE, creating it if necessary.  */treeget_typeid (type)     tree type;{  if (type == error_mark_node)    return error_mark_node;  if (TYPE_SIZE (type_info_type_node) == NULL_TREE)    {      error ("must #include <typeinfo> before using typeid");      return error_mark_node;    }    if (! flag_rtti)    error ("requesting typeid with -fno-rtti");  if (processing_template_decl)    return build_min_nt (TYPEID_EXPR, type);  /* If the type of the type-id is a reference type, the result of the     typeid expression refers to a type_info object representing the     referenced type.  */  if (TREE_CODE (type) == REFERENCE_TYPE)    type = TREE_TYPE (type);  /* The top-level cv-qualifiers of the lvalue expression or the type-id     that is the operand of typeid are always ignored.  */  type = TYPE_MAIN_VARIANT (type);  if (TYPE_SIZE (complete_type (type)) == NULL_TREE)    {      cp_error ("taking typeid of incomplete type `%T'", type);      return error_mark_node;    }  return get_typeid_1 (type);}/* Check whether TEST is null before returning RESULT.  If TEST is used in   RESULT, it must have previously had a save_expr applied to it.  */static treeifnonnull (test, result)     tree test, result;{  return build (COND_EXPR, TREE_TYPE (result),		build (EQ_EXPR, boolean_type_node, test, integer_zero_node),		cp_convert (TREE_TYPE (result), integer_zero_node),		result);}/* Execute a dynamic cast, as described in section 5.2.6 of the 9/93 working   paper.  */static treebuild_dynamic_cast_1 (type, expr)     tree type, expr;{  enum tree_code tc = TREE_CODE (type);  tree exprtype;  enum tree_code ec;  tree dcast_fn;  tree old_expr = expr;  if (TREE_CODE (expr) == OFFSET_REF)    expr = resolve_offset_ref (expr);    exprtype = TREE_TYPE (expr);  assert (exprtype != NULL_TREE);  ec = TREE_CODE (exprtype);  switch (tc)    {    case POINTER_TYPE:      if (ec == REFERENCE_TYPE)	{	  expr = convert_from_reference (expr);	  exprtype = TREE_TYPE (expr);	  ec = TREE_CODE (exprtype);	}      if (ec != POINTER_TYPE)	goto fail;      if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)	goto fail;      if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)	goto fail;      if (!at_least_as_qualified_p (TREE_TYPE (type),				    TREE_TYPE (exprtype)))	goto fail;      if (TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)	break;      /* else fall through */    case REFERENCE_TYPE:      if (TREE_CODE (TREE_TYPE (type)) != RECORD_TYPE)	goto fail;      if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)	goto fail;      break;      /* else fall through */    default:      goto fail;    }  /* Apply trivial conversion T -> T& for dereferenced ptrs.  */  if (ec == RECORD_TYPE)    {      exprtype = build_reference_type (exprtype);      expr = convert_to_reference (exprtype, expr, CONV_IMPLICIT,				   LOOKUP_NORMAL, NULL_TREE);      ec = REFERENCE_TYPE;    }  if (tc == REFERENCE_TYPE)    {      if (ec != REFERENCE_TYPE)	goto fail;      if (TREE_CODE (TREE_TYPE (exprtype)) != RECORD_TYPE)	goto fail;      if (TYPE_SIZE (complete_type (TREE_TYPE (exprtype))) == NULL_TREE)	goto fail;      if (!at_least_as_qualified_p (TREE_TYPE (type),				    TREE_TYPE (exprtype)))	goto fail;    }  /* If *type is an unambiguous accessible base class of *exprtype,     convert statically.  */  {    int distance;    tree path;    distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,				  &path);    if (distance == -2)      {	cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",		  TREE_TYPE (exprtype), TREE_TYPE (type));	return error_mark_node;      }    if (distance == -3)      {	cp_error ("dynamic_cast from `%T' to private base class `%T'",		  TREE_TYPE (exprtype), TREE_TYPE (type));	return error_mark_node;      }    if (distance >= 0)      return build_vbase_path (PLUS_EXPR, type, expr, path, 0);  }  /* Otherwise *exprtype must be a polymorphic class (have a vtbl).  */  if (TYPE_VIRTUAL_P (TREE_TYPE (exprtype)))    {      tree expr1;      /* if TYPE is `void *', return pointer to complete object.  */      if (tc == POINTER_TYPE	  && TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)	{	  /* if b is an object, dynamic_cast<void *>(&b) == (void *)&b.  */	  if (TREE_CODE (expr) == ADDR_EXPR	      && TREE_CODE (TREE_OPERAND (expr, 0)) == VAR_DECL	      && TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == RECORD_TYPE)	    return build1 (NOP_EXPR, type, expr);	  /* Since expr is used twice below, save it.  */	  expr = save_expr (expr);	  expr1 = build_headof (expr);	  if (TREE_TYPE (expr1) != type)	    expr1 = build1 (NOP_EXPR, type, expr1);	  return ifnonnull (expr, expr1);	}      else	{	  tree retval;          tree result, td1, td2, td3, elems, expr2; 	  /* If we got here, we can't convert statically.  Therefore,	     dynamic_cast<D&>(b) (b an object) cannot succeed.  */	  if (ec == REFERENCE_TYPE)	    {	      if (TREE_CODE (old_expr) == VAR_DECL		  && TREE_CODE (TREE_TYPE (old_expr)) == RECORD_TYPE)		{		  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",			      old_expr, type);		  return throw_bad_cast ();		}	    }	  /* Ditto for dynamic_cast<D*>(&b).  */	  else if (TREE_CODE (expr) == ADDR_EXPR)	    {	      tree op = TREE_OPERAND (expr, 0);	      if (TREE_CODE (op) == VAR_DECL		  && TREE_CODE (TREE_TYPE (op)) == RECORD_TYPE)		{		  cp_warning ("dynamic_cast of `%#D' to `%#T' can never succeed",			      op, type);		  retval = build_int_2 (0, 0); 		  TREE_TYPE (retval) = type; 		  return retval;		}	    }	  /* Since expr is used twice below, save it.  */	  expr = save_expr (expr);	  expr1 = expr;	  if (tc == REFERENCE_TYPE)	    expr1 = build_unary_op (ADDR_EXPR, expr1, 0);	  /* Build run-time conversion.  */	  expr2 = build_headof (expr1);	  if (ec == POINTER_TYPE)	    td1 = get_tinfo_fn_dynamic (build_indirect_ref (expr, NULL_PTR));	  else	    td1 = get_tinfo_fn_dynamic (expr);	  td1 = decay_conversion (td1);	  	  td2 = decay_conversion	    (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (type))));	  td3 = decay_conversion	    (get_tinfo_fn (TYPE_MAIN_VARIANT (TREE_TYPE (exprtype))));          elems = tree_cons	    (NULL_TREE, td1, tree_cons	     (NULL_TREE, td2, tree_cons	      (NULL_TREE, build_int_2 (1, 0), tree_cons	       (NULL_TREE, expr2, tree_cons		(NULL_TREE, td3, tree_cons		 (NULL_TREE, expr1, NULL_TREE))))));	  dcast_fn = get_identifier ("__dynamic_cast");	  if (IDENTIFIER_GLOBAL_VALUE (dcast_fn))	    dcast_fn = IDENTIFIER_GLOBAL_VALUE (dcast_fn);	  else	    {	      tree tmp;	      push_obstacks (&permanent_obstack, &permanent_obstack);	      tmp = tree_cons		(NULL_TREE, TREE_TYPE (td1), tree_cons		 (NULL_TREE, TREE_TYPE (td1), tree_cons		  (NULL_TREE, integer_type_node, tree_cons		   (NULL_TREE, ptr_type_node, tree_cons		    (NULL_TREE, TREE_TYPE (td1), tree_cons		     (NULL_TREE, ptr_type_node, void_list_node))))));	      tmp = build_function_type (ptr_type_node, tmp);	      dcast_fn = build_lang_decl (FUNCTION_DECL, dcast_fn, tmp);	      DECL_EXTERNAL (dcast_fn) = 1;	      TREE_PUBLIC (dcast_fn) = 1;	      DECL_ARTIFICIAL (dcast_fn) = 1;	      pushdecl_top_level (dcast_fn);	      make_function_rtl (dcast_fn);	      pop_obstacks ();	    }	  	  mark_used (dcast_fn);          result = build_call	    (dcast_fn, TREE_TYPE (TREE_TYPE (dcast_fn)), elems);	  if (tc == REFERENCE_TYPE)	    {	      expr1 = throw_bad_cast ();	      expr1 = build_compound_expr		(expr_tree_cons (NULL_TREE, expr1,			    build_expr_list (NULL_TREE, cp_convert (type, integer_zero_node))));	      TREE_TYPE (expr1) = type;	      result = save_expr (result);	      return build (COND_EXPR, type, result, result, expr1);	    }	  /* Now back to the type we want from a void*.  */	  result = cp_convert (type, result);          return ifnonnull (expr, result);	}    } fail:  cp_error ("cannot dynamic_cast `%E' (of type `%#T') to type `%#T'",	    expr, exprtype, type);  return error_mark_node;}treebuild_dynamic_cast (type, expr)     tree type, expr;{  if (type == error_mark_node || expr == error_mark_node)    return error_mark_node;    if (processing_template_decl)    return build_min (DYNAMIC_CAST_EXPR, copy_to_permanent (type), expr);  return convert_from_reference (build_dynamic_cast_1 (type, expr));}/* Build and initialize various sorts of descriptors.  Every descriptor   node has a name associated with it (the name created by mangling).   For this reason, we use the identifier as our access to the __*_desc   nodes, instead of sticking them directly in the types.  Otherwise we   would burden all built-in types (and pointer types) with slots that   we don't necessarily want to use.   For each descriptor we build, we build a variable that contains   the descriptor's information.  When we need this info at runtime,   all we need is access to these variables.   Note: these constructors always return the address of the descriptor   info, since that is simplest for their mutual interaction.  */extern tree const_string_type_node;/* Build an initializer for a __si_type_info node.  */static voidexpand_si_desc (tdecl, type)     tree tdecl;     tree type;{  tree t, elems, fn;  const char *name = build_overload_name (type, 1, 1);  tree name_string = combine_strings (build_string (strlen (name)+1, name));  type = BINFO_TYPE (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0));  expand_expr_stmt (get_typeid_1 (type));  t = decay_conversion (get_tinfo_var (type));  elems = tree_cons    (NULL_TREE, decay_conversion (tdecl), tree_cons     (NULL_TREE, decay_conversion (name_string), tree_cons      (NULL_TREE, t, NULL_TREE)));  fn = get_identifier ("__rtti_si");  if (IDENTIFIER_GLOBAL_VALUE (fn))    fn = IDENTIFIER_GLOBAL_VALUE (fn);  else    {      tree tmp;      push_obstacks (&permanent_obstack, &permanent_obstack);      tmp = tree_cons	(NULL_TREE, ptr_type_node, tree_cons	 (NULL_TREE, const_string_type_node, tree_cons	  (NULL_TREE, build_pointer_type (type_info_type_node),	   void_list_node)));      tmp = build_function_type	(void_type_node, tmp);        fn = build_lang_decl (FUNCTION_DECL, fn, tmp);      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);  fn = build_call (fn, TREE_TYPE (TREE_TYPE (fn)), elems);  expand_expr_stmt (fn);}/* Build an initializer for a __class_type_info node.  */static voidexpand_class_desc (tdecl, type)     tree tdecl;     tree type;

⌨️ 快捷键说明

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