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

📄 class.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
      /* 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 index;	/* We skip a slot for the offset/tdesc entry.  */	int i = ++(*has_virtual);	if (i >= 256 || index_table[i] == 0)	  {	    index = build_int_2 (i, 0);	    if (i < 256)	      index_table[i] = index;	  }	else	  index = index_table[i];	/* Now assign virtual dispatch information. */	DECL_VINDEX (fndecl) = index;	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))	{	  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 ((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)		    cp_error_at ("duplicate nested type `%D'", x);		  else if (TREE_CODE (field) == TYPE_DECL			   || TREE_CODE (x) == TYPE_DECL)		    cp_error_at ("duplicate field `%D' (as type and non-type)",				x);		  else		    cp_error_at ("duplicate member `%D'", x);		  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, TREE_CHAIN (x));}/* Change the access of FDECL to ACCESS in T.   Return 1 if change was legit, otherwise return 0.  */static intalter_access (t, fdecl, access)     tree t;     tree fdecl;     enum access_type access;{  tree elem = purpose_member (t, DECL_ACCESS (fdecl));  if (elem && TREE_VALUE (elem) != (tree)access)    {      if (TREE_CODE (TREE_TYPE (fdecl)) == FUNCTION_DECL)	{	  cp_error_at ("conflicting access specifications for method `%D', ignored", TREE_TYPE (fdecl));	}      else	error ("conflicting access specifications for field `%s', ignored",	       IDENTIFIER_POINTER (DECL_NAME (fdecl)));    }  else if (TREE_PRIVATE (fdecl))    {      if (access != access_private)	cp_error_at ("cannot make private `%D' non-private", fdecl);      goto alter;    }  else if (TREE_PROTECTED (fdecl))    {      if (access != access_protected)	cp_error_at ("cannot make protected `%D' non-protected", fdecl);      goto alter;    }  /* ARM 11.3: an access declaration may not be used to restrict access     to a member that is accessible in the base class.  */  else if (access != access_public)    cp_error_at ("cannot reduce access of public member `%D'", fdecl);  else if (elem == NULL_TREE)    {    alter:      DECL_ACCESS (fdecl) = tree_cons (t, (tree)access,					   DECL_ACCESS (fdecl));      return 1;    }  return 0;}/* Return the offset to the main vtable for a given base BINFO.  */treeget_vfield_offset (binfo)     tree binfo;{  return size_binop (PLUS_EXPR,		     size_binop (FLOOR_DIV_EXPR,				 DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),				 size_int (BITS_PER_UNIT)),		     BINFO_OFFSET (binfo));}/* Get the offset to the start of the original binfo that we derived   this binfo from.  If we find TYPE first, return the offset only   that far.  The shortened search is useful because the this pointer   on method calling is expected to point to a DECL_CONTEXT (fndecl)   object, and not a baseclass of it.  */static treeget_derived_offset (binfo, type)     tree binfo, type;{  tree offset1 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));  tree offset2;  int i;  while (BINFO_BASETYPES (binfo)	 && (i=CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo))) != -1)    {      tree binfos = BINFO_BASETYPES (binfo);      if (BINFO_TYPE (binfo) == type)	break;      binfo = TREE_VEC_ELT (binfos, i);    }  offset2 = get_vfield_offset (TYPE_BINFO (BINFO_TYPE (binfo)));  return size_binop (MINUS_EXPR, offset1, offset2);}/* If FOR_TYPE needs to reinitialize virtual function table pointers   for TYPE's sub-objects, add such reinitializations to BASE_INIT_LIST.   Returns BASE_INIT_LIST appropriately modified.  */static treemaybe_fixup_vptrs (for_type, binfo, base_init_list)     tree for_type, binfo, base_init_list;{  /* Now reinitialize any slots that don't fall under our virtual     function table pointer.  */  tree vfields = CLASSTYPE_VFIELDS (BINFO_TYPE (binfo));  while (vfields)    {      tree basetype = VF_NORMAL_VALUE (vfields)	? TYPE_MAIN_VARIANT (VF_NORMAL_VALUE (vfields))	  : VF_BASETYPE_VALUE (vfields);      tree base_binfo = get_binfo (basetype, for_type, 0);      /* Punt until this is implemented. */      if (1 /* BINFO_MODIFIED (base_binfo) */)	{	  tree base_offset = get_vfield_offset (base_binfo);	  if (! tree_int_cst_equal (base_offset, get_vfield_offset (TYPE_BINFO (for_type)))	      && ! tree_int_cst_equal (base_offset, get_vfield_offset (binfo)))	    base_init_list = tree_cons (error_mark_node, base_binfo,					base_init_list);	}      vfields = TREE_CHAIN (vfields);    }  return base_init_list;}/* If TYPE does not have a constructor, then the compiler must   manually deal with all of the initialization this type requires.   If a base initializer exists only to fill in the virtual function   table pointer, then we mark that fact with the TREE_VIRTUAL bit.   This way, we avoid multiple initializations of the same field by   each virtual function table up the class hierarchy.   Virtual base class pointers are not initialized here.  They are   initialized only at the "top level" of object creation.  If we   initialized them here, we would have to skip a lot of work.  */static voidbuild_class_init_list (type)     tree type;{  tree base_init_list = NULL_TREE;  tree member_init_list = NULL_TREE;  /* Since we build member_init_list and base_init_list using     tree_cons, backwards fields the all through work.  */  tree x;  tree binfos = BINFO_BASETYPES (TYPE_BINFO (type));  int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;  for (x = TYPE_FIELDS (type); x; x = TREE_CHAIN (x))    {      if (TREE_CODE (x) != FIELD_DECL)	continue;      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (x))	  || DECL_INITIAL (x) != NULL_TREE)	member_init_list = tree_cons (x, type, member_init_list);    }  member_init_list = nreverse (member_init_list);  /* We will end up doing this last.  Need special marker     to avoid infinite regress.  */  if (TYPE_VIRTUAL_P (type))    {      base_init_list = build_tree_list (error_mark_node, TYPE_BINFO (type));      if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (type) == 0)	TREE_VALUE (base_init_list) = NULL_TREE;      TREE_ADDRESSABLE (base_init_list) = 1;    }

⌨️ 快捷键说明

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