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

📄 cp-class.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      TYPE_HAS_DESTRUCTOR (variants) = TYPE_HAS_DESTRUCTOR (t);      TYPE_NEEDS_CONSTRUCTOR (variants) = TYPE_NEEDS_CONSTRUCTOR (t);      TYPE_NEEDS_CONSTRUCTING (variants) = TYPE_NEEDS_CONSTRUCTING (t);      TYPE_NEEDS_DESTRUCTOR (variants) = TYPE_NEEDS_DESTRUCTOR (t);      TYPE_USES_COMPLEX_INHERITANCE (variants) = TYPE_USES_COMPLEX_INHERITANCE (t);      TYPE_VIRTUAL_P (variants) = TYPE_VIRTUAL_P (t);      TYPE_USES_VIRTUAL_BASECLASSES (variants) = TYPE_USES_VIRTUAL_BASECLASSES (t);      /* Copy whatever these are holding today.  */      TYPE_MIN_VALUE (variants) = TYPE_MIN_VALUE (t);      TYPE_MAX_VALUE (variants) = TYPE_MAX_VALUE (t);      variants = TYPE_NEXT_VARIANT (variants);    }  if (n_baseclasses && max_has_virtual)    {      /* Done by `finish_struct' for classes without baseclasses.  */      int has_abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (t) != 0;      tree binfos = TYPE_BINFO_BASETYPES (t);      for (i = n_baseclasses-1; i >= 0; i--)	{	  has_abstract_virtuals	    |= (CLASSTYPE_ABSTRACT_VIRTUALS (BINFO_TYPE (TREE_VEC_ELT (binfos, i))) != 0);	  if (has_abstract_virtuals)	    break;	}      if (has_abstract_virtuals)	CLASSTYPE_ABSTRACT_VIRTUALS (t) = get_abstract_virtuals (t);    }  if (n_baseclasses)    {      /* Notice whether this class has type conversion functions defined.	 Also report whether joining two types yields an ambiguity in the	 virtual function table, e.g.,	 	 struct A { virtual int f (); };	 struct B { virtual int f (); };	 struct C : A, B { / * no f (); * / };	/ / error, ambiguous	 */      tree binfo = TYPE_BINFO (t);      tree binfos = BINFO_BASETYPES (binfo);      int n_binfos = list_length (binfo);      tree vbases = CLASSTYPE_VBASECLASSES (t), basetype;      int n_vbases = list_length (vbases), j;      build_mi_virtuals (n_binfos+n_vbases*n_baseclasses, max_has_virtual);      /* Fill in virtual function table with values which do not come	 "normal"ly, i.e., those which come from virtual and/or	 non-leftmost base classes.  */      for (i = 0; binfo; binfo = TREE_CHAIN (binfo))	{	  if (TREE_VIA_VIRTUAL (binfo))	    /* Virtual functions from virtual baseclasses are done below.  */;	  else if (CLASSTYPE_VSIZE (BINFO_TYPE (binfo)))	    {	      tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (binfo));	      if (flag_dossier)		virtuals = TREE_CHAIN (virtuals);	      add_mi_virtuals (++i, virtuals);	    }	}      for (; vbases; vbases = TREE_CHAIN (vbases))	{	  basetype = BINFO_TYPE (vbases);	  if (CLASSTYPE_VSIZE (basetype))	    for (j = n_baseclasses-1; j >= 0; j--)	      {		tree this_binfo = TREE_VEC_ELT (binfos, j);		if (UNIQUELY_DERIVED_FROM_P (basetype, this_binfo))		  {		    tree virtuals = TREE_CHAIN (BINFO_VIRTUALS (vbases));		    if (flag_dossier)		      virtuals = TREE_CHAIN (virtuals);		    add_mi_virtuals (++i, virtuals);		  }	      }	}      for (i = n_baseclasses-1; i >= 0; i--)	{	  basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));	  if (TYPE_HAS_CONVERSION (basetype))	    {	      TYPE_HAS_CONVERSION (t) = 1;	      TYPE_HAS_INT_CONVERSION (t) |= TYPE_HAS_INT_CONVERSION (basetype);	      TYPE_HAS_REAL_CONVERSION (t) |= TYPE_HAS_REAL_CONVERSION (basetype);	    }	  if (CLASSTYPE_MAX_DEPTH (basetype) >= CLASSTYPE_MAX_DEPTH (t))	    CLASSTYPE_MAX_DEPTH (t) = CLASSTYPE_MAX_DEPTH (basetype) + 1;	}      report_ambiguous_mi_virtuals (n_binfos+n_vbases*n_baseclasses, t);#if 0      /* Now that we know what the virtual functiond table looks like,	 fix up offsets in the presence of virtual base classes.  */      if (n_vbases)	fixup_vbase_offsets (t);#endif    }  /* Need to test METHOD_VEC here in case all methods     (conversions and otherwise) are inherited.  */  if (TYPE_HAS_CONVERSION (t) && method_vec != NULL_TREE)    {      tree first_conversions[last_conversion_type];      tree last_conversions[last_conversion_type];      enum conversion_type conv_index;      tree *tmp;      int i;      bzero (first_conversions, sizeof (first_conversions));      bzero (last_conversions, sizeof (last_conversions));      for (tmp = &TREE_VEC_ELT (method_vec, 1);	   tmp != TREE_VEC_END (method_vec); tmp += 1)	{	  /* ??? This should compare DECL_NAME (*tmp) == ansi_opname[TYPE_EXPR].  */	  if (IDENTIFIER_TYPENAME_P (DECL_ASSEMBLER_NAME (*tmp)))	    {	      tree fntype = TREE_TYPE (*tmp);	      tree return_type = TREE_TYPE (fntype);	      my_friendly_assert (TREE_CODE (fntype) == METHOD_TYPE, 171);	      if (typecode_p (return_type, POINTER_TYPE))		{		  if (TYPE_READONLY (TREE_TYPE (return_type)))		    conv_index = constptr_conv;		  else		    conv_index = ptr_conv;		}	      else if (typecode_p (return_type, INTEGER_TYPE))		{		  TYPE_HAS_INT_CONVERSION (t) = 1;		  conv_index = int_conv;		}	      else if (typecode_p (return_type, REAL_TYPE))		{		  TYPE_HAS_REAL_CONVERSION (t) = 1;		  conv_index = real_conv;		}	      else		continue;	      if (first_conversions[(int) conv_index] == NULL_TREE)		first_conversions[(int) conv_index] = *tmp;	      last_conversions[(int) conv_index] = *tmp;	    }	}      for (i = 0; i < (int) last_conversion_type; i++)	if (first_conversions[i] != last_conversions[i])	  CLASSTYPE_CONVERSION (t, i) = error_mark_node;	else	  CLASSTYPE_CONVERSION (t, i) = first_conversions[i];    }  /* If this type has constructors, force its mode to be BLKmode,     and force its TREE_ADDRESSABLE bit to be nonzero.  */  if (TYPE_NEEDS_CONSTRUCTING (t) || TYPE_NEEDS_DESTRUCTOR (t))    {      tree variants = t;      if (TREE_CODE (TYPE_NAME (t)) == TYPE_DECL)	DECL_MODE (TYPE_NAME (t)) = BLKmode;      while (variants)	{	  TYPE_MODE (variants) = BLKmode;	  TREE_ADDRESSABLE (variants) = 1;	  variants = TYPE_NEXT_VARIANT (variants);	}    }}/* Warn about duplicate methods in fn_fields.  Also compact method   lists so that lookup can be made faster.   Algorithm: Outer loop builds lists by method name.  Inner loop   checks for redundant method names within a list.   Data Structure: List of method lists.  The outer list is a   TREE_LIST, whose TREE_PURPOSE field is the field name and the   TREE_VALUE is the TREE_CHAIN of the FUNCTION_DECLs.  Friends are   chained in the same way as member functions, but they live in the   TREE_TYPE field of the outer list.  That allows them to be quickly   deleted, and requires no extra storage.   If there are any constructors/destructors, they are moved to the   front of the list.  This makes pushclass more efficient.   We also link each field which has shares a name with its baseclass   to the head of the list of fields for that base class.  This allows   us to reduce search time in places like `build_method_call' to   consider only reasonably likely functions.  */static treefinish_struct_methods (t, fn_fields, nonprivate_method)     tree t;     tree fn_fields;     int nonprivate_method;{  tree method_vec;  tree name = constructor_name (t);  int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (t);  /* Now prepare to gather fn_fields into vector.  */  struct obstack *ambient_obstack = current_obstack;  current_obstack = &class_obstack;  method_vec = make_node (TREE_VEC);  /* Room has been saved for constructors and destructors.  */  current_obstack = ambient_obstack;  /* Now make this a live vector.  */  obstack_free (&class_obstack, method_vec);  obstack_blank (&class_obstack, sizeof (struct tree_vec));  while (fn_fields)    {      /* NEXT Pointer, TEST Pointer, and BASE Pointer.  */      tree nextp, *testp;      tree fn_name = DECL_NAME (fn_fields);      if (fn_name == NULL_TREE)	fn_name = name;      nextp = TREE_CHAIN (fn_fields);      TREE_CHAIN (fn_fields) = NULL_TREE;      /* Constructors are handled easily in search routines.	 Besides, we know we won't find any, so do not bother looking.  */      if (fn_name == name && TREE_VEC_ELT (method_vec, 0) == 0)	TREE_VEC_ELT (method_vec, 0) = fn_fields;      else	{	  testp = &TREE_VEC_ELT (method_vec, 0);	  if (*testp == NULL_TREE)	    testp++;	  while (((HOST_WIDE_INT) testp		  < (HOST_WIDE_INT) obstack_next_free (&class_obstack))		 && DECL_NAME (*testp) != fn_name)	    testp++;	  if ((HOST_WIDE_INT) testp	      < (HOST_WIDE_INT) obstack_next_free (&class_obstack))	    {	      tree x, prev_x;	      for (x = *testp; x; x = DECL_CHAIN (x))		{		  if (DECL_NAME (fn_fields) == ansi_opname[(int) DELETE_EXPR])		    {		      /* ANSI C++ June 5 1992 WP 12.5.5.1 */		      error_with_decl (fn_fields, "operator delete cannot be overloaded");		      error_with_decl (x, "previous declaration here");		    }		  if (DECL_ASSEMBLER_NAME (fn_fields) == DECL_ASSEMBLER_NAME (x))		    {		      /* We complain about multiple destructors on sight,			 so we do not repeat the warning here.  Friend-friend			 ambiguities are warned about outside this loop.  */		      if (! DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (fn_fields)))			error_with_file_and_line (DECL_SOURCE_FILE (fn_fields),						  DECL_SOURCE_LINE (fn_fields),						  "ambiguous method `%s' in structure",						  lang_printable_name (fn_fields));		      break;		    }		  prev_x = x;		}	      if (x == 0)		if (*testp)		  DECL_CHAIN (prev_x) = fn_fields;		else		  *testp = fn_fields;	    }	  else	    {	      obstack_ptr_grow (&class_obstack, fn_fields);	      method_vec = (tree)obstack_base (&class_obstack);	    }	}      fn_fields = nextp;    }  TREE_VEC_LENGTH (method_vec)    = (tree *)obstack_next_free (&class_obstack) - (&TREE_VEC_ELT (method_vec, 0));  obstack_finish (&class_obstack);  CLASSTYPE_METHOD_VEC (t) = method_vec;  if (nonprivate_method == 0      && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE      && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)    {      tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));      for (i = 0; i < n_baseclasses; i++)	if (TREE_VIA_PUBLIC (TREE_VEC_ELT (binfos, i))	    || TREE_VIA_PROTECTED (TREE_VEC_ELT (binfos, i)))	  {	    nonprivate_method = 1;	    break;	  }      if (nonprivate_method == 0)	warning ("all member functions in class `%s' are private",		 TYPE_NAME_STRING (t));    }  /* If there are constructors (and destructors), they are at the     front.  Place destructors at very front.  Also warn if all     constructors and/or destructors are private (in which case this     class is effectively unusable.  */  if (TYPE_HAS_DESTRUCTOR (t))    {      tree dtor, prev;      for (dtor = TREE_VEC_ELT (method_vec, 0); dtor; prev = dtor, dtor = DECL_CHAIN (dtor))	{	  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (dtor)))	    {	      if (TREE_PRIVATE (dtor)		  && CLASSTYPE_FRIEND_CLASSES (t) == NULL_TREE		  && DECL_FRIENDLIST (TYPE_NAME (t)) == NULL_TREE)		warning_with_decl (TYPE_NAME (t), "class `%s' only defines a private destructor and has no friends");	      break;	    }	}      /* Wild parse errors can cause this to happen.  */      if (dtor == NULL_TREE)	TYPE_HAS_DESTRUCTOR (t) = 0;      else if (dtor != TREE_VEC_ELT (method_vec, 0))	{	  DECL_CHAIN (prev) = DECL_CHAIN (dtor);	  DECL_CHAIN (dtor) = TREE_VEC_ELT (method_vec, 0);	  TREE_VEC_ELT (method_vec, 0) = dtor;	}    }  /* Now for each member function (except for constructors and     destructors), compute where member functions of the same     name reside in base classes.  */  if (n_baseclasses != 0      && TREE_VEC_LENGTH (method_vec) > 1)    {      int len = TREE_VEC_LENGTH (method_vec);      tree baselink_vec = make_tree_vec (len);      int any_links = 0;      tree baselink_binfo = build_tree_list (NULL_TREE, TYPE_BINFO (t));      for (i = 1; i < len; i++)	{	  TREE_VEC_ELT (baselink_vec, i)	    = get_baselinks (baselink_binfo, t, DECL_NAME (TREE_VEC_ELT (method_vec, i)));	  if (TREE_VEC_ELT (baselink_vec, i) != 0)	    any_links = 1;	}      if (any_links != 0)	CLASSTYPE_BASELINK_VEC (t) = baselink_vec;      else	obstack_free (current_obstack, baselink_vec);    }  /* Now add the methods to the TYPE_METHODS of T, arranged in a chain.  */  {    tree x, last_x = NULL_TREE;    int limit = TREE_VEC_LENGTH (method_vec);    for (i = 1; i < limit; i++)      {	for (x = TREE_VEC_ELT (method_vec, i); x; x = DECL_CHAIN (x))	  {	    if (last_x != NULL_TREE)	      TREE_CHAIN (last_x) = x;	    last_x = x;	  }      }    /* Put ctors and dtors at the front of the list.  */    x = TREE_VEC_ELT (method_vec, 0);    if (x)      {	while (DECL_CHAIN (x))	  {	    TREE_CHAIN (x) = DECL_CHAIN (x);	    x = DECL_CHAIN (x);	  }	if (TREE_VEC_LENGTH (method_vec) > 1)	  TREE_CHAIN (x) = TREE_VEC_ELT (method_vec, 1);	else	  TREE_CHAIN (x) = NULL_TREE;      }  }#if 0  TYPE_METHODS (t) = TREE_VEC_ELT (method_vec, 0)    ? TREE_VEC_ELT (method_vec, 0) : TREE_VEC_ELT (method_vec, 1);#else  TYPE_METHODS (t) = method_vec;#endif  return method_vec;}/* Emit error when a duplicate definition of a type is seen.  Patch up. */voidduplicate_tag_error (t)     tree t;{  char *err_name;  tree name = TYPE_NAME (t);  if (TREE_CODE (name) == TYPE_DECL)    name = DECL_NAME (name);  err_name = IDENTIFIER_POINTER (name);  if (TREE_CODE (t) == UNION_TYPE)    error ("redefinition of `union %s'", err_name);  else if (TREE_CODE (t) == RECORD_TYPE)    error ("redefinition of 

⌨️ 快捷键说明

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