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

📄 rtti.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 3 页
字号:
/* RunTime Type Identification   Copyright (C) 1995, 96-97, 1998, 1999 Free Software Foundation, Inc.   Mostly written by Jason Merrill (jason@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, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  */#include "config.h"#include "system.h"#include "tree.h"#include "cp-tree.h"#include "flags.h"#include "output.h"#include "assert.h"#include "toplev.h"#ifndef INT_TYPE_SIZE#define INT_TYPE_SIZE BITS_PER_WORD#endifextern struct obstack permanent_obstack;static tree call_void_fn PROTO((const char *));static tree build_headof_sub PROTO((tree));static tree build_headof PROTO((tree));static tree get_tinfo_var PROTO((tree));static tree ifnonnull PROTO((tree, tree));static tree build_dynamic_cast_1 PROTO((tree, tree));static void expand_si_desc PROTO((tree, tree));static void expand_class_desc PROTO((tree, tree));static void expand_attr_desc PROTO((tree, tree));static void expand_ptr_desc PROTO((tree, tree));static void expand_generic_desc PROTO((tree, tree, const char *));static tree throw_bad_cast PROTO((void));static tree throw_bad_typeid PROTO((void));tree type_info_type_node;tree tinfo_fn_id;tree tinfo_fn_type;voidinit_rtti_processing (){  if (flag_honor_std)    push_namespace (get_identifier ("std"));  type_info_type_node = xref_tag    (class_type_node, get_identifier ("type_info"), 1);  if (flag_honor_std)    pop_namespace ();  tinfo_fn_id = get_identifier ("__tf");  tinfo_fn_type = build_function_type    (build_reference_type (build_qualified_type (type_info_type_node, 						 TYPE_QUAL_CONST)),     void_list_node);}/* Given a pointer to an object with at least one virtual table   pointer somewhere, return a pointer to a possible sub-object that   has a virtual table pointer in it that is the vtable parent for   that sub-object.  */static treebuild_headof_sub (exp)     tree exp;{  tree type = TREE_TYPE (TREE_TYPE (exp));  tree basetype = CLASSTYPE_RTTI (type);  tree binfo = get_binfo (basetype, type, 0);  exp = convert_pointer_to_real (binfo, exp);  return exp;}/* Given the expression EXP of type `class *', return the head of the   object pointed to by EXP with type cv void*, if the class has any   virtual functions (TYPE_VIRTUAL_P), else just return the   expression.  */static treebuild_headof (exp)     tree exp;{  tree type = TREE_TYPE (exp);  tree aref;  tree offset;  if (TREE_CODE (type) != POINTER_TYPE)    {      error ("`headof' applied to non-pointer type");      return error_mark_node;    }  type = TREE_TYPE (type);  if (!TYPE_VIRTUAL_P (type))    return exp;  if (CLASSTYPE_COM_INTERFACE (type))    {      cp_error ("RTTI not supported for COM interface type `%T'", type);      return error_mark_node;    }  /* If we don't have rtti stuff, get to a sub-object that does.  */  if (!CLASSTYPE_VFIELDS (TREE_TYPE (TREE_TYPE (exp))))    exp = build_headof_sub (exp);  /* We use this a couple of times below, protect it.  */  exp = save_expr (exp);  aref = build_vtbl_ref (build_indirect_ref (exp, NULL_PTR), integer_zero_node);  if (flag_vtable_thunks)    offset = aref;  else    offset = build_component_ref (aref, delta_identifier, NULL_TREE, 0);  type = build_qualified_type (ptr_type_node, 			       CP_TYPE_QUALS (TREE_TYPE (exp)));  return build (PLUS_EXPR, type, exp,		cp_convert (ptrdiff_type_node, offset));}/* Build a call to a generic entry point taking and returning void.  */static treecall_void_fn (name)     const char *name;{  tree d = get_identifier (name);  tree type;    if (IDENTIFIER_GLOBAL_VALUE (d))    d = IDENTIFIER_GLOBAL_VALUE (d);  else    {      push_obstacks (&permanent_obstack, &permanent_obstack);      type = build_function_type (void_type_node, void_list_node);      d = build_lang_decl (FUNCTION_DECL, d, type);      DECL_EXTERNAL (d) = 1;      TREE_PUBLIC (d) = 1;      DECL_ARTIFICIAL (d) = 1;      pushdecl_top_level (d);      make_function_rtl (d);      pop_obstacks ();    }  mark_used (d);  return build_call (d, void_type_node, NULL_TREE);}/* Get a bad_cast node for the program to throw...   See libstdc++/exception.cc for __throw_bad_cast */static treethrow_bad_cast (){  return call_void_fn ("__throw_bad_cast");}static treethrow_bad_typeid (){  return call_void_fn ("__throw_bad_typeid");}/* Return the type_info function associated with the expression EXP.  If   EXP is a reference to a polymorphic class, return the dynamic type;   otherwise return the static type of the expression.  */treeget_tinfo_fn_dynamic (exp)     tree exp;{  tree type;  if (exp == error_mark_node)    return error_mark_node;  if (type_unknown_p (exp))    {      error ("typeid of overloaded function");      return error_mark_node;    }  type = TREE_TYPE (exp);  /* 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 (TYPE_SIZE (complete_type (type)) == NULL_TREE)    {      cp_error ("taking typeid of incomplete type `%T'", type);      return error_mark_node;    }  /* If exp is a reference to polymorphic type, get the real type_info.  */  if (TYPE_VIRTUAL_P (type) && ! resolves_to_fixed_type_p (exp, 0))    {      /* build reference to type_info from vtable.  */      tree t;      if (! flag_rtti)	error ("taking dynamic typeid of object with -fno-rtti");      if (CLASSTYPE_COM_INTERFACE (type))	{	  cp_error ("RTTI not supported for COM interface type `%T'", type);	  return error_mark_node;	}      /* If we don't have rtti stuff, get to a sub-object that does.  */      if (! CLASSTYPE_VFIELDS (type))	{	  exp = build_unary_op (ADDR_EXPR, exp, 0);	  exp = build_headof_sub (exp);	  exp = build_indirect_ref (exp, NULL_PTR);	}      if (flag_vtable_thunks)	t = build_vfn_ref ((tree *) 0, exp, integer_one_node);      else	t = build_vfn_ref ((tree *) 0, exp, integer_zero_node);      TREE_TYPE (t) = build_pointer_type (tinfo_fn_type);      return t;    }  /* otherwise return the type_info for the static type of the expr.  */  return get_tinfo_fn (TYPE_MAIN_VARIANT (type));}treebuild_typeid (exp)     tree exp;{  exp = get_tinfo_fn_dynamic (exp);  exp = build_call (exp, TREE_TYPE (tinfo_fn_type), NULL_TREE);  return convert_from_reference (exp);}  treebuild_x_typeid (exp)     tree exp;{  tree cond = NULL_TREE;  tree type;  int nonnull;  if (! flag_rtti)    {      error ("cannot use typeid with -fno-rtti");      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 (processing_template_decl)    return build_min_nt (TYPEID_EXPR, exp);  if (TREE_CODE (exp) == INDIRECT_REF      && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE      && TYPE_VIRTUAL_P (TREE_TYPE (exp))      && ! resolves_to_fixed_type_p (exp, &nonnull)      && ! nonnull)    {      exp = stabilize_reference (exp);      cond = cp_convert (boolean_type_node, TREE_OPERAND (exp, 0));    }  exp = get_tinfo_fn_dynamic (exp);  if (exp == error_mark_node)    return error_mark_node;  type = TREE_TYPE (tinfo_fn_type);  exp = build_call (exp, type, NULL_TREE);  if (cond)    {      tree bad = throw_bad_typeid ();      bad = build_compound_expr	(expr_tree_cons (NULL_TREE, bad, build_expr_list		    (NULL_TREE, cp_convert (type, integer_zero_node))));      exp = build (COND_EXPR, type, cond, exp, bad);    }  return convert_from_reference (exp);}static treeget_tinfo_var (type)     tree type;{  tree tname = build_overload_with_type (get_identifier ("__ti"), type);  tree tdecl, arrtype;  int size;  if (IDENTIFIER_GLOBAL_VALUE (tname))    return IDENTIFIER_GLOBAL_VALUE (tname);      /* Figure out how much space we need to allocate for the type_info object.     If our struct layout or the type_info classes are changed, this will     need to be modified.  */  if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)    size = 3 * POINTER_SIZE + INT_TYPE_SIZE;  else if (TREE_CODE (type) == POINTER_TYPE	   && ! (TREE_CODE (TREE_TYPE (type)) == OFFSET_TYPE		 || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE))    size = 3 * POINTER_SIZE;  else if (IS_AGGR_TYPE (type))    {      if (CLASSTYPE_N_BASECLASSES (type) == 0)	size = 2 * POINTER_SIZE;      else if (! TYPE_USES_COMPLEX_INHERITANCE (type)	       && (TREE_VIA_PUBLIC		   (TREE_VEC_ELT (TYPE_BINFO_BASETYPES (type), 0))))	size = 3 * POINTER_SIZE;      else	size = 3 * POINTER_SIZE + TYPE_PRECISION (sizetype);    }  else    size = 2 * POINTER_SIZE;  push_obstacks (&permanent_obstack, &permanent_obstack);  /* The type for a character array of the appropriate size.  */  arrtype = build_cplus_array_type    (unsigned_char_type_node,     build_index_type (size_int (size / BITS_PER_UNIT - 1)));  tdecl = build_decl (VAR_DECL, tname, arrtype);  TREE_PUBLIC (tdecl) = 1;  DECL_EXTERNAL (tdecl) = 1;  DECL_ARTIFICIAL (tdecl) = 1;  pushdecl_top_level (tdecl);  cp_finish_decl (tdecl, NULL_TREE, NULL_TREE, 0, 0);  pop_obstacks ();  return tdecl;}/* Returns the decl for a function which will return a type_info node for   TYPE.  This version does not mark the function used, for use in   set_rtti_entry; for the vtable case, we'll get marked in   finish_vtable_vardecl, when we know that we want to be emitted.   We do this to avoid emitting the tinfo node itself, since we don't   currently support DECL_DEFER_OUTPUT for variables.  Also, we don't   associate constant pools with their functions properly, so we would   emit string constants and such even though we don't emit the actual   function.  When those bugs are fixed, this function should go away.  */treeget_tinfo_fn_unused (type)     tree type;{  tree name;  tree d;  if (TREE_CODE (type) == OFFSET_TYPE)    type = TREE_TYPE (type);  if (TREE_CODE (type) == METHOD_TYPE)    type = build_function_type (TREE_TYPE (type),				TREE_CHAIN (TYPE_ARG_TYPES (type)));  name = build_overload_with_type (tinfo_fn_id, type);  if (IDENTIFIER_GLOBAL_VALUE (name))    return IDENTIFIER_GLOBAL_VALUE (name);  push_obstacks (&permanent_obstack, &permanent_obstack);  d = build_lang_decl (FUNCTION_DECL, name, tinfo_fn_type);  DECL_EXTERNAL (d) = 1;  TREE_PUBLIC (d) = 1;  DECL_ARTIFICIAL (d) = 1;  DECL_NOT_REALLY_EXTERN (d) = 1;  SET_DECL_TINFO_FN_P (d);

⌨️ 快捷键说明

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