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

📄 class.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Remember which class this vtable is really for.  */  DECL_CONTEXT (new_decl) = for_type;  DECL_ARTIFICIAL (new_decl) = 1;  TREE_STATIC (new_decl) = 1;  BINFO_VTABLE (binfo) = pushdecl_top_level (new_decl);  DECL_VIRTUAL_P (new_decl) = 1;#ifndef WRITABLE_VTABLES  /* Make them READONLY by default. (mrs) */  TREE_READONLY (new_decl) = 1;#endif  DECL_ALIGN (new_decl) = DECL_ALIGN (orig_decl);  /* Make fresh virtual list, so we can smash it later.  */  BINFO_VIRTUALS (binfo) = copy_list (BINFO_VIRTUALS (binfo));  if (TREE_VIA_VIRTUAL (binfo))    {      tree binfo1 = binfo_member (BINFO_TYPE (binfo), 				  CLASSTYPE_VBASECLASSES (for_type));      /* XXX - This should never happen, if it does, the caller should	 ensure that the binfo is from for_type's binfos, not from any	 base type's.  We can remove all this code after a while.  */      if (binfo1 != binfo)	warning ("internal inconsistency: binfo offset error for rtti");      offset = BINFO_OFFSET (binfo1);    }  else    offset = BINFO_OFFSET (binfo);  set_rtti_entry (BINFO_VIRTUALS (binfo),		  size_binop (MINUS_EXPR, signed_size_zero_node, offset),		  for_type);#ifdef GATHER_STATISTICS  n_vtables += 1;  n_vtable_elems += list_length (BINFO_VIRTUALS (binfo));#endif  /* Set TREE_PUBLIC and TREE_EXTERN as appropriate.  */  import_export_vtable (new_decl, for_type, 0);  if (TREE_VIA_VIRTUAL (binfo))    my_friendly_assert (binfo == binfo_member (BINFO_TYPE (binfo),				   CLASSTYPE_VBASECLASSES (current_class_type)),			170);  SET_BINFO_NEW_VTABLE_MARKED (binfo);}#if 0/* Access the virtual function table entry that logically   contains BASE_FNDECL.  VIRTUALS is the virtual function table's   initializer.  We can run off the end, when dealing with virtual   destructors in MI situations, return NULL_TREE in that case.  */static treeget_vtable_entry (virtuals, base_fndecl)     tree virtuals, base_fndecl;{  unsigned HOST_WIDE_INT n = (HOST_BITS_PER_WIDE_INT >= BITS_PER_WORD	   ? (TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl))	      & (((unsigned HOST_WIDE_INT)1<<(BITS_PER_WORD-1))-1))	   : TREE_INT_CST_LOW (DECL_VINDEX (base_fndecl)));#ifdef GATHER_STATISTICS  n_vtable_searches += n;#endif  while (n > 0 && virtuals)    {      --n;      virtuals = TREE_CHAIN (virtuals);    }  return virtuals;}#endif/* Put new entry ENTRY into virtual function table initializer   VIRTUALS.   Also update DECL_VINDEX (FNDECL).  */static voidmodify_vtable_entry (old_entry_in_list, new_entry, fndecl)     tree old_entry_in_list, new_entry, fndecl;{  tree base_fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (old_entry_in_list)), 0);#ifdef NOTQUITE  cp_warning ("replaced %D with %D", DECL_ASSEMBLER_NAME (base_fndecl),	      DECL_ASSEMBLER_NAME (fndecl));#endif  TREE_VALUE (old_entry_in_list) = new_entry;  /* Now assign virtual dispatch information, if unset.  */  /* We can dispatch this, through any overridden base function.  */  if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)    {      DECL_VINDEX (fndecl) = DECL_VINDEX (base_fndecl);      DECL_CONTEXT (fndecl) = DECL_CONTEXT (base_fndecl);    }}/* Access the virtual function table entry N.  VIRTUALS is the virtual   function table's initializer.  */static treeget_vtable_entry_n (virtuals, n)     tree virtuals;     unsigned HOST_WIDE_INT n;{  while (n > 0)    {      --n;      virtuals = TREE_CHAIN (virtuals);    }  return virtuals;}/* Add a virtual function to all the appropriate vtables for the class   T.  DECL_VINDEX(X) should be error_mark_node, if we want to   allocate a new slot in our table.  If it is error_mark_node, we   know that no other function from another vtable is overridden by X.   HAS_VIRTUAL keeps track of how many virtuals there are in our main   vtable for the type, and we build upon the PENDING_VIRTUALS list   and return it.  */static treeadd_virtual_function (pending_virtuals, has_virtual, fndecl, t)     tree pending_virtuals;     int *has_virtual;     tree fndecl;     tree t; /* Structure type.  */{  /* FUNCTION_TYPEs and OFFSET_TYPEs no longer freely     convert to void *.  Make such a conversion here.  */  tree vfn = build1 (ADDR_EXPR, vfunc_ptr_type_node, fndecl);  TREE_CONSTANT (vfn) = 1;#ifndef DUMB_USER  if (current_class_type == 0)    cp_warning ("internal problem, current_class_type is zero when adding `%D', please report",		fndecl);  if (current_class_type && t != current_class_type)    cp_warning ("internal problem, current_class_type differs when adding `%D', please report",		fndecl);#endif  /* 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 (fndecl) == error_mark_node)    {      tree entry;      /* We remember that this was the base sub-object for rtti.  */      CLASSTYPE_RTTI (t) = t;      /* If we are using thunks, use two slots at the front, one	 for the offset pointer, one for the tdesc pointer.  */      if (*has_virtual == 0 && flag_vtable_thunks)	{	  *has_virtual = 1;	}      /* Build a new INT_CST for this DECL_VINDEX.  */      {	static tree index_table[256];	tree idx;	/* We skip a slot for the offset/tdesc entry.  */	int i = ++(*has_virtual);	if (i >= 256 || index_table[i] == 0)	  {	    idx = build_int_2 (i, 0);	    if (i < 256)	      index_table[i] = idx;	  }	else	  idx = index_table[i];	/* Now assign virtual dispatch information.  */	DECL_VINDEX (fndecl) = idx;	DECL_CONTEXT (fndecl) = t;      }      entry = build_vtable_entry (integer_zero_node, vfn);      pending_virtuals = tree_cons (DECL_VINDEX (fndecl), entry, pending_virtuals);    }  /* Might already be INTEGER_CST if declared twice in class.  We will     give error later or we've already given it.  */  else if (TREE_CODE (DECL_VINDEX (fndecl)) != INTEGER_CST)    {      /* 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 (fndecl, vfn, pending_hard_virtuals);    }  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))	{	  /* ??? 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 *));	  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)))	    TREE_VEC_ELT (method_vec, 1) = decl;	  else	    TREE_VEC_ELT (method_vec, 0) = decl;	  TREE_VEC_LENGTH (method_vec) = 2;	}      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) + 2*sizeof (tree *));	  TREE_VEC_ELT (method_vec, 2) = decl;	  TREE_VEC_LENGTH (method_vec) = 3;	  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))	{	  int idx = !!DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl));	  /* TREE_VEC_ELT (method_vec, idx) = decl; */	  if (decl != TREE_VEC_ELT (method_vec, idx))	    {	      DECL_CHAIN (decl) = TREE_VEC_ELT (method_vec, idx);	      TREE_VEC_ELT (method_vec, idx) = 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 ((char *) method_vec, (char *) 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, fields)     tree field, fields;{  tree x;  tree prev = 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, 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, 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)		    cp_error_at ("duplicate enum value `%D'", x);		  else if (TREE_CODE (field) == CONST_DECL			   || TREE_CODE (x) == CONST_DECL)		    cp_error_at ("duplicate field `%D' (as enum and non-enum)",				x);		  else if (TREE_CODE (field) == TYPE_DECL			   && TREE_CODE (x) == TYPE_DECL)		    {		      if (TREE_TYPE (field) == TREE_TYPE (x))			continue;		      cp_error_at ("duplicate nested type `%D'", x);		    }		  else if (TREE_CODE (field) == TYPE_DECL

⌨️ 快捷键说明

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