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

📄 cp-class.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	     of the immediate base class.  */	  base_context = t;	  binfo = TYPE_BINFO (t);	  if (! BINFO_NEW_VTABLE_MARKED (binfo))	    build_vtable (TYPE_BINFO (DECL_CONTEXT (vfield)), t);	}      else	{	  /* This is our very own copy of `basetype' to play with.	     Later, we will fill in all the virtual functions	     that override the virtual functions in these base classes	     which are not defined by the current type.  */	  if (! BINFO_NEW_VTABLE_MARKED (binfo))	    prepare_fresh_vtable (binfo, base, t);	}      modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl),			   build_vtable_entry (this_offset, pfn),			   fndecl, base_context);    }  for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))    {      tree this_offset;      tree base, path;      if (! BINFO_VTABLE (vbases))	/* There are only two ways that a type can fail to have	   virtual functions: neither it nor any of its base	   types define virtual functions (in which case	   no updating need be done), or virtual functions	   accessible to it come from virtual base classes	   (in which case we have or will get them modified	   in other passes of this loop).  */	continue;      base = BINFO_TYPE (vbases);      path = NULL_TREE;      if (base != base_context	  && get_base_distance (base_context, base, 0, &path) == -1)	continue;      if (path)	this_offset = size_binop (MINUS_EXPR, offset, BINFO_OFFSET (path));      else	this_offset = offset;      /* Doesn't matter if not actually from this virtual base class,         but shouldn't come from deeper virtual baseclasses.  The enclosing	 loop should take care of such baseclasses.  */      while (path)	{	  if (TREE_VIA_VIRTUAL (path))	    goto skip;	  path = BINFO_INHERITANCE_CHAIN (path);	}      base_offset = BINFO_OFFSET (vbases);      this_offset = size_binop (MINUS_EXPR, this_offset, base_offset);      /* Make sure we can modify the derived association with immunity.  */      if (TREE_USED (TYPE_BINFO (t)))	TYPE_BINFO (t) = copy_binfo (TYPE_BINFO (t));      /* This is our very own copy of `basetype' to play with.  */      if (! BINFO_NEW_VTABLE_MARKED (vbases))	{	  tree context_binfo = binfo_value (base_context, base, 0);	  prepare_fresh_vtable (vbases, context_binfo, t);	}      modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (vbases), base_fndecl),			   build_vtable_entry (this_offset, pfn),			   fndecl, base_context);    skip: {}    }}static treeadd_virtual_function (pending_virtuals, has_virtual, x, t)     tree pending_virtuals;     int *has_virtual;     tree x;     tree t; /* Structure type. */{  int debug_vbase = 1;  /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely     convert to void *.  Make such a conversion here.  */  tree vfn = build1 (ADDR_EXPR, ptr_type_node, x);  TREE_CONSTANT (vfn) = 1;  /* current_class_type may be NULL_TREE in case of error.  */  if (current_class_type)    TREE_ADDRESSABLE (x) = CLASSTYPE_VTABLE_NEEDS_WRITING (current_class_type);  /* If the virtual function is a redefinition of a prior one,     figure out in which base class the new definition goes,     and if necessary, make a fresh virtual function table     to hold that entry.  */  if (DECL_VINDEX (x) == error_mark_node)    {      tree entry = build_vtable_entry (integer_zero_node, vfn);      if (flag_dossier && *has_virtual == 0)	{	  /* CLASSTYPE_DOSSIER is only used as a Boolean (NULL or not). */	  CLASSTYPE_DOSSIER (t) = integer_one_node;	  *has_virtual = 1;        }      /* Build a new INT_CST for this DECL_VINDEX.  */#ifdef VTABLE_USES_MASK      SET_DECL_VINDEX (x, build_int_2 (++(*has_virtual), 0));#else      {	static tree index_table[256];	tree index;	int i = ++(*has_virtual);	if (i >= 256 || index_table[i] == 0)	  {	    index = build_int_2 (((unsigned HOST_WIDE_INT) 1				  << (BITS_PER_WORD - 1)) | i, ~0);	    if (i < 256)	      index_table[i] = index;	  }	else	  index = index_table[i];	DECL_VINDEX (x) = index;      }#endif      pending_virtuals = tree_cons (DECL_VINDEX (x), entry, pending_virtuals);    }  /* Happens if declared twice in class or we're not in a class definition.     We will give error later or we've already given it.  */  else if (TREE_CODE (DECL_VINDEX (x)) == INTEGER_CST	   || current_class_type == NULL_TREE)    return pending_virtuals;  else if (debug_vbase && TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))    {      /* Need an entry in some other virtual function table.         Deal with this after we have laid out our virtual base classes.  */      pending_hard_virtuals = temp_tree_cons (x, vfn, pending_hard_virtuals);    }  else    {      /* Need an entry in some other virtual function table.         We can do this now.  */      tree base_fndecl_list = DECL_VINDEX (x), base_fndecls, prev = 0;      tree vtable_context = DECL_FCONTEXT (CLASSTYPE_VFIELD (current_class_type));      tree true_base_fndecl = 0;      /* First assign DECL_VINDEX from the base vfn with which	 we share our vtable.  */      base_fndecls = base_fndecl_list;      while (base_fndecls)	{	  if (TREE_CHAIN (base_fndecls) == NULL_TREE	      || DECL_FCONTEXT (CLASSTYPE_VFIELD (DECL_CLASS_CONTEXT (TREE_VALUE (base_fndecls)))) == vtable_context)	    {	      true_base_fndecl = TREE_VALUE (base_fndecls);	      modify_vtable_entries (current_class_type, x,				     true_base_fndecl, vfn);	      if (prev)		TREE_CHAIN (prev) = TREE_CHAIN (base_fndecls);	      else		base_fndecl_list = prev;	      break;	    }	  prev = base_fndecls;	  base_fndecls = TREE_CHAIN (base_fndecls);	}      /* Now fill in the rest of the vtables.  */      base_fndecls = base_fndecl_list;      while (base_fndecls)	{	  /* If we haven't found one we like, first one wins.  */	  if (true_base_fndecl == 0)	    true_base_fndecl = TREE_VALUE (base_fndecls);	  modify_vtable_entries (current_class_type, x,				 TREE_VALUE (base_fndecls), vfn);	  base_fndecls = TREE_CHAIN (base_fndecls);	}      DECL_CONTEXT (x) = DECL_CONTEXT (true_base_fndecl);    }  return pending_virtuals;}/* Obstack on which to build the vector of class methods.  */struct obstack class_obstack;extern struct obstack *current_obstack;/* Add method METHOD to class TYPE.  This is used when a method   has been defined which did not initially appear in the class definition,   and helps cut down on spurious error messages.   FIELDS is the entry in the METHOD_VEC vector entry of the class type where   the method should be added.  */voidadd_method (type, fields, method)     tree type, *fields, method;{  /* We must make a copy of METHOD here, since we must be sure that     we have exclusive title to this method's DECL_CHAIN.  */  tree decl;  push_obstacks (&permanent_obstack, &permanent_obstack);  {    decl = copy_node (method);    if (DECL_RTL (decl) == 0        && (!processing_template_decl            || !uses_template_parms (decl)))      {	make_function_rtl (decl);	DECL_RTL (method) = DECL_RTL (decl);      }  }  if (fields && *fields)    {      /* Take care not to hide destructor.  */      DECL_CHAIN (decl) = DECL_CHAIN (*fields);      DECL_CHAIN (*fields) = decl;    }  else if (CLASSTYPE_METHOD_VEC (type) == 0)    {      tree method_vec = make_node (TREE_VEC);      if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))	{	  TREE_VEC_ELT (method_vec, 0) = decl;	  TREE_VEC_LENGTH (method_vec) = 1;	}      else	{	  /* ??? Is it possible for there to have been enough room in the	     current chunk for the tree_vec structure but not a tree_vec	     plus a tree*?  Will this work in that case?  */	  obstack_free (current_obstack, method_vec);	  obstack_blank (current_obstack, sizeof (struct tree_vec) + sizeof (tree *));	  TREE_VEC_ELT (method_vec, 1) = decl;	  TREE_VEC_LENGTH (method_vec) = 2;	  obstack_finish (current_obstack);	}      CLASSTYPE_METHOD_VEC (type) = method_vec;    }  else    {      tree method_vec = CLASSTYPE_METHOD_VEC (type);      int len = TREE_VEC_LENGTH (method_vec);      /* Adding a new ctor or dtor.  This is easy because our         METHOD_VEC always has a slot for such entries.  */      if (TYPE_IDENTIFIER (type) == DECL_NAME (decl))	{	  /* TREE_VEC_ELT (method_vec, 0) = decl; */	  if (decl != TREE_VEC_ELT (method_vec, 0))	    {	      DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, 0);	      TREE_VEC_ELT (method_vec, 0) = decl;	    }	}      else	{	  /* This is trickier.  We try to extend the TREE_VEC in-place,	     but if that does not work, we copy all its data to a new	     TREE_VEC that's large enough.  */	  struct obstack *ob = &class_obstack;	  tree *end = (tree *)obstack_next_free (ob);	  if (end != TREE_VEC_END (method_vec))	    {	      ob = current_obstack;	      TREE_VEC_LENGTH (method_vec) += 1;	      TREE_VEC_ELT (method_vec, len) = NULL_TREE;	      method_vec = copy_node (method_vec);	      TREE_VEC_LENGTH (method_vec) -= 1;	    }	  else	    {	      tree tmp_vec = (tree) obstack_base (ob);	      if (obstack_room (ob) < sizeof (tree))		{		  obstack_blank (ob, sizeof (struct tree_common)				 + tree_code_length[(int) TREE_VEC]				   * sizeof (char *)				 + len * sizeof (tree));		  tmp_vec = (tree) obstack_base (ob);		  bcopy (method_vec, tmp_vec,			 (sizeof (struct tree_common)			  + tree_code_length[(int) TREE_VEC] * sizeof (char *)			  + (len-1) * sizeof (tree)));		  method_vec = tmp_vec;		}	      else		obstack_blank (ob, sizeof (tree));	    }	  obstack_finish (ob);	  TREE_VEC_ELT (method_vec, len) = decl;	  TREE_VEC_LENGTH (method_vec) = len + 1;	  CLASSTYPE_METHOD_VEC (type) = method_vec;	  if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))	    {	      /* ??? May be better to know whether these can be extended?  */	      tree baselink_vec = CLASSTYPE_BASELINK_VEC (type);	      TREE_VEC_LENGTH (baselink_vec) += 1;	      CLASSTYPE_BASELINK_VEC (type) = copy_node (baselink_vec);	      TREE_VEC_LENGTH (baselink_vec) -= 1;	      TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), len) = 0;	    }	}    }  DECL_CONTEXT (decl) = type;  DECL_CLASS_CONTEXT (decl) = type;  pop_obstacks ();}/* Subroutines of finish_struct.  *//* Look through the list of fields for this struct, deleting   duplicates as we go.  This must be recursive to handle   anonymous unions.   FIELD is the field which may not appear anywhere in FIELDS.   FIELD_PTR, if non-null, is the starting point at which   chained deletions may take place.   The value returned is the first acceptable entry found   in FIELDS.   Note that anonymous fields which are not of UNION_TYPE are   not duplicates, they are just anonymous fields.  This happens   when we have unnamed bitfields, for example.  */static treedelete_duplicate_fields_1 (field, field_ptr, fields)     tree field, *field_ptr, fields;{  tree x;  tree prev = field_ptr ? *field_ptr : 0;  if (DECL_NAME (field) == 0)    {      if (TREE_CODE (TREE_TYPE (field)) != UNION_TYPE)	return fields;      for (x = TYPE_FIELDS (TREE_TYPE (field)); x; x = TREE_CHAIN (x))	fields = delete_duplicate_fields_1 (x, field_ptr, fields);      if (prev)	TREE_CHAIN (prev) = fields;      return fields;    }  else    {      for (x = fields; x; prev = x, x = TREE_CHAIN (x))	{	  if (DECL_NAME (x) == 0)	    {	      if (TREE_CODE (TREE_TYPE (x)) != UNION_TYPE)		continue;	      TYPE_FIELDS (TREE_TYPE (x))		= delete_duplicate_fields_1 (field, 0, TYPE_FIELDS (TREE_TYPE (x)));	      if (TYPE_FIELDS (TREE_TYPE (x)) == 0)		{		  if (prev == 0)		    fields = TREE_CHAIN (fields);		  else		    TREE_CHAIN (prev) = TREE_CHAIN (x);		}	    }	  else	    {	      if (DECL_NAME (field) == DECL_NAME (x))		{		  if (TREE_CODE (field) == CONST_DECL		      && TREE_CODE (x) == CONST_DECL)		    error_with_decl (x, "duplicate enum value `%s'");		  else if (TREE_CODE (field) == CONST_DECL			   || TREE_CODE (x) == CONST_DECL)		    error_with_decl (x, "duplicate field `%s' (as enum and non-enum)");		  else		    error_with_decl (x, "duplicate member `%s'");		  if (prev == 0)		    fields = TREE_CHAIN (fields);		  else		    TREE_CHAIN (prev) = TREE_CHAIN (x);		}	    }	}    }  return fields;}static voiddelete_duplicate_fields (fields)     tree fields;{  tree x;  for (x = fields; x && TREE_CHAIN (x); x = TREE_CHAIN (x))    TREE_CHAIN (x) = delete_duplicate_fields_1 (x, &x, TREE_CHAIN (x));}/* Change the visibility of T::FDECL to VISIBILITY.   Return 1 if change was legit, otherwise return 0.  */static int

⌨️ 快捷键说明

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