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

📄 cp-call.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	    {	      basetype = TREE_TYPE (basetype);	      instance_ptr = instance;	    }	  if (! IS_AGGR_TYPE (basetype))	    goto non_aggr_error;	  if (! instance_ptr)	    {	      if ((lvalue_p (instance)		   && (instance_ptr = build_unary_op (ADDR_EXPR, instance, 0)))		  || (instance_ptr = unary_complex_lvalue (ADDR_EXPR, instance)))		{		  if (instance_ptr == error_mark_node)		    return error_mark_node;		}	      else if (TREE_CODE (instance) == NOP_EXPR		       || TREE_CODE (instance) == CONSTRUCTOR)		{		  /* A cast is not an lvalue.  Initialize a fresh temp		     with the value we are casting from, and proceed with		     that temporary.  We can't cast to a reference type,		     so that simplifies the initialization to something		     we can manage.  */		  tree temp = get_temp_name (TREE_TYPE (instance), 0);		  if (IS_AGGR_TYPE (TREE_TYPE (instance)))		    expand_aggr_init (temp, instance, 0);		  else		    {		      store_init_value (temp, instance);		      expand_decl_init (temp);		    }		  instance = temp;		  instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);		}	      else		{		  if (TREE_CODE (instance) != CALL_EXPR)		    my_friendly_abort (125);		  if (TYPE_NEEDS_CONSTRUCTOR (basetype))		    instance = build_cplus_new (basetype, instance, 0);		  else		    {		      instance = get_temp_name (basetype, 0);		      TREE_ADDRESSABLE (instance) = 1;		    }		  instance_ptr = build_unary_op (ADDR_EXPR, instance, 0);		}	      /* @@ Should we call comp_target_types here?  */	      inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));	      if (TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (inst_ptr_basetype))		basetype = inst_ptr_basetype;	      else		{		  instance_ptr = convert (TYPE_POINTER_TO (basetype), instance_ptr);		  if (instance_ptr == error_mark_node)		    return error_mark_node;		}	    }	  else	    inst_ptr_basetype = TREE_TYPE (TREE_TYPE (instance_ptr));	}      if (basetype_path == NULL_TREE)	basetype_path = TYPE_BINFO (inst_ptr_basetype);      result = build_field_call (basetype_path, instance_ptr, name, parms, err_name);      if (result)	return result;      if (!(flags & LOOKUP_NONVIRTUAL) && TYPE_VIRTUAL_P (basetype))	{	  if (TREE_SIDE_EFFECTS (instance_ptr))	    {	      /* This action is needed because the instance is needed		 for providing the base of the virtual function table.		 Without using a SAVE_EXPR, the function we are building		 may be called twice, or side effects on the instance		 variable (such as a post-increment), may happen twice.  */	      instance_ptr = save_expr (instance_ptr);	      instance = build_indirect_ref (instance_ptr, 0);	    }	  else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)	    {	      /* This happens when called for operator new ().  */	      instance = build_indirect_ref (instance, 0);	    }	  need_vtbl = maybe_needed;	}    }  if (TYPE_SIZE (basetype) == 0)    {      /* This is worth complaining about, I think.  */      error_with_aggr_type (basetype, "cannot lookup method in incomplete type `%s'");      return error_mark_node;    }  save_basetype = basetype;#if 0  if (all_virtual == 1      && (! strncmp (IDENTIFIER_POINTER (name), OPERATOR_METHOD_FORMAT,		     OPERATOR_METHOD_LENGTH)	  || instance_ptr == NULL_TREE	  || (TYPE_OVERLOADS_METHOD_CALL_EXPR (basetype) == 0	      /*&& TYPE_NEEDS_WRAPPER (basetype) == 0*/ )))    all_virtual = 0;#endif  last = NULL_TREE;  for (parmtypes = 0, parm = parms; parm; parm = TREE_CHAIN (parm))    {      tree t = TREE_TYPE (TREE_VALUE (parm));      if (TREE_CODE (t) == OFFSET_TYPE)	{	  /* Convert OFFSET_TYPE entities to their normal selves.  */	  TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));	  t = TREE_TYPE (TREE_VALUE (parm));	}      if (TREE_CODE (t) == ARRAY_TYPE)	{	  /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.	     This eliminates needless calls to `compute_conversion_costs'.  */	  TREE_VALUE (parm) = default_conversion (TREE_VALUE (parm));	  t = TREE_TYPE (TREE_VALUE (parm));	}      if (t == error_mark_node)	return error_mark_node;      last = build_tree_list (NULL_TREE, t);      parmtypes = chainon (parmtypes, last);    }  if (instance)    {      constp = TREE_READONLY (instance);      volatilep = TREE_THIS_VOLATILE (instance);      parms = tree_cons (NULL_TREE, instance_ptr, parms);    }  else    {      /* Raw constructors are always in charge.  */      if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)	  && ! (flags & LOOKUP_HAS_IN_CHARGE))	{	  flags |= LOOKUP_HAS_IN_CHARGE;	  parms = tree_cons (NULL_TREE, integer_one_node, parms);	  parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);	}      if (flag_this_is_variable > 0)	{	  constp = 0;	  volatilep = 0;	  parms = tree_cons (NULL_TREE, build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node), parms);	}      else	{	  constp = 0;	  volatilep = 0;	  instance_ptr = build_new (NULL_TREE, basetype, void_type_node, 0);	  if (instance_ptr == error_mark_node)	    return error_mark_node;	  instance_ptr = save_expr (instance_ptr);	  TREE_CALLS_NEW (instance_ptr) = 1;	  instance = build_indirect_ref (instance_ptr, 0);	  /* If it's a default argument initialized from a ctor, what we get	     from instance_ptr will match the arglist for the FUNCTION_DECL	     of the constructor.  */	  if (parms && TREE_CODE (TREE_VALUE (parms)) == CALL_EXPR	      && TREE_OPERAND (TREE_VALUE (parms), 1)	      && TREE_CALLS_NEW (TREE_VALUE (TREE_OPERAND (TREE_VALUE (parms), 1))))	    parms = build_tree_list (NULL_TREE, instance_ptr);	  else	    parms = tree_cons (NULL_TREE, instance_ptr, parms);	}    }  parmtypes = tree_cons (NULL_TREE,			 build_pointer_type (build_type_variant (basetype, constp, volatilep)),			 parmtypes);  if (last == NULL_TREE)    last = parmtypes;  /* Look up function name in the structure type definition.  */  if ((IDENTIFIER_HAS_TYPE_VALUE (name)       && IS_AGGR_TYPE (IDENTIFIER_TYPE_VALUE (name)))      || name == constructor_name (basetype))    {      tree tmp = NULL_TREE;      if (IDENTIFIER_TYPE_VALUE (name) == basetype	  || name == constructor_name (basetype))	tmp = TYPE_BINFO (basetype);      else	tmp = get_binfo (IDENTIFIER_TYPE_VALUE (name), basetype, 0);            if (tmp != 0)	{	  name_kind = "constructor";	  	  if (TYPE_USES_VIRTUAL_BASECLASSES (basetype)	      && ! (flags & LOOKUP_HAS_IN_CHARGE))	    {	      /* Constructors called for initialization		 only are never in charge.  */	      tree tmplist;	      	      flags |= LOOKUP_HAS_IN_CHARGE;	      tmplist = tree_cons (NULL_TREE, integer_zero_node,				   TREE_CHAIN (parms));	      TREE_CHAIN (parms) = tmplist;	      tmplist = tree_cons (NULL_TREE, integer_type_node, TREE_CHAIN (parmtypes));	      TREE_CHAIN (parmtypes) = tmplist;	    }	  #ifdef SOS	  if (TYPE_DYNAMIC (basetype) && dtbl_inserted == 0)	    {	      tree parm, parmtype;	      dtbl = get_sos_dtable (basetype);	      parm = tree_cons (NULL_TREE, dtbl, TREE_CHAIN (parms));	      parmtype = tree_cons (NULL_TREE, build_pointer_type (ptr_type_node), TREE_CHAIN (parmtypes));	      TREE_CHAIN (parms) = parm;	      TREE_CHAIN (parmtypes) = parmtype;	      dtbl_inserted = -1;	    }#endif	  /* constructors are in very specific places.  */#ifdef SOS	  if (dtbl_inserted == -1)	    {	      TREE_CHAIN (parmtypes) = TREE_CHAIN (TREE_CHAIN (parmtypes));	      TREE_CHAIN (parms) = TREE_CHAIN (TREE_CHAIN (parms));	      dtbl_inserted = 0;	    }#endif	  basetype = BINFO_TYPE (tmp);	}      else	name_kind = "method";    }  else name_kind = "method";    if (basetype_path == NULL_TREE)    basetype_path = TYPE_BINFO (basetype);  result = lookup_fnfields (basetype_path, name,			    (flags & LOOKUP_COMPLAIN));  if (result == error_mark_node)    return error_mark_node;  /* Now, go look for this method name.  We do not find destructors here.     Putting `void_list_node' on the end of the parmtypes     fakes out `build_decl_overload' into doing the right thing.  */  TREE_CHAIN (last) = void_list_node;  method_name = build_decl_overload (name, parmtypes,				     1 + (name == constructor_name (save_basetype)));  TREE_CHAIN (last) = NULL_TREE;  for (pass = 0; pass < 2; pass++)    {      struct candidate *candidates;      struct candidate *cp;      int len;      unsigned best = 2;      /* This increments every time we go up the type hierarchy.	 The idea is to prefer a function of the derived class if possible. */      int b_or_d = 0;      baselink = result;      if (pass > 0)	{	  candidates	    = (struct candidate *) alloca ((ever_seen+1)					   * sizeof (struct candidate));	  cp = candidates;	  len = list_length (parms);	  /* First see if a global function has a shot at it.  */	  if (flags & LOOKUP_GLOBAL)	    {	      tree friend_parms;	      tree parm = TREE_VALUE (parms);	      if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE)		friend_parms = parms;	      else if (TREE_CODE (TREE_TYPE (parm)) == POINTER_TYPE)		{		  tree new_type;		  parm = build_indirect_ref (parm, "friendifying parms (compiler error)");		  new_type = build_reference_type (TREE_TYPE (parm));		  /* It is possible that this should go down a layer. */		  new_type = build_type_variant (new_type,						 TREE_READONLY (parm),						 TREE_THIS_VOLATILE (parm));		  parm = convert (new_type, parm);		  friend_parms = tree_cons (NULL_TREE, parm, TREE_CHAIN (parms));		}	      else		my_friendly_assert (0, 167);	      cp->harshness		= (unsigned short *)alloca ((len+1) * sizeof (short));	      result = build_overload_call (name, friend_parms, 0, cp);	      /* If it turns out to be the one we were actually looking for		 (it was probably a friend function), the return the		 good result.  */	      if (TREE_CODE (result) == CALL_EXPR)		return result;	      while (cp->evil == 0)		{		  /* non-standard uses: set the field to 0 to indicate		     we are using a non-member function.  */		  cp->u.field = 0;		  if (cp->harshness[len] == 0		      && cp->harshness[len] == 0		      && cp->user == 0 && cp->b_or_d == 0		      && cp->easy < best)		    best = cp->easy;		  cp += 1;		}	    }	}      while (baselink)	{	  /* We have a hit (of sorts). If the parameter list is	     "error_mark_node", or some variant thereof, it won't	     match any methods.  Since we have verified that the is	     some method vaguely matching this one (in name at least),	     silently return.	     	     Don't stop for friends, however.  */	  tree basetypes = TREE_PURPOSE (baselink);	  function = TREE_VALUE (baselink);	  if (TREE_CODE (basetypes) == TREE_LIST)	    basetypes = TREE_VALUE (basetypes);	  basetype = BINFO_TYPE (basetypes);	  /* Cast the instance variable to the appropriate type.  */	  TREE_VALUE (parmtypes) = TYPE_POINTER_TO (basetype);	  if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (function)))	    function = DECL_CHAIN (function);	  for (; function; function = DECL_CHAIN (function))	    {#ifdef GATHER_STATISTICS	      n_inner_fields_searched++;#endif	      ever_seen++;	      /* Not looking for friends here.  */	      if (TREE_CODE (TREE_TYPE (function)) == FUNCTION_TYPE		  && ! DECL_STATIC_FUNCTION_P (function))		continue;	      if (pass == 0		  && DECL_ASSEMBLER_NAME (function) == method_name)		{		  if (flags & LOOKUP_PROTECT)		    {		      visibility = compute_visibility (basetypes, function);		      if (visibility == visibility_protected			  && flags & LOOKUP_PROTECTED_OK)			visibility = visibility_public;		    }		  if ((flags & LOOKUP_PROTECT) == 0		      || visibility == visibility_public)		    goto found_and_ok;		  else if (visibility == visibility_private)		    saw_private = function;		  else if (visibility == visibility_protected)		    saw_protected = function;		  /* If we fail on the exact match, we have		     an immediate failure.  */		  goto found;		}	      if (pass > 0)		{		  tree these_parms = parms;#ifdef GATHER_STATISTICS		  n_inner_fields_searched++;#endif		  cp->harshness		    = (unsigned short *)alloca ((len+1) * sizeof (short));		  if (DECL_STATIC_FUNCTION_P (function))		    these_parms = TREE_CHAIN (these_parms);		  compute_conversion_costs (function, these_parms, cp, len);		  cp->b_or_d += b_or_d;		  if (cp->evil == 0)		    {		      cp->u.field = function;		      cp->function = function;		      if (flags & LOOKUP_PROTECT)			{			  enum visibility_type this_v;			  this_v = compute_visibility (basetypes, function);			  if (this_v == visibility_protected			      && (flags & LOOKUP_PROTECTED_OK))			    this_v = visibility_public;			  if (this_v != visibility_public)			    {			      if (this_v == visibility_private)				saw_private = function;			      else				saw_protected = function;			      continue;			    }			}		      /* No "two-level" conversions.  */		      if (flags & LOOKUP_NO_CONVERSION && cp->user != 0)			continue;		      /* If we used default parameters, we must			 check to see whether anyone else might			 use them also, and report a possible			 ambiguity.  */		      if (! TYPE_USES_MULTIPLE_INHERITANCE (save_basetype)			  && cp->harshness[len] == 0			  && CONST_HARSHNESS (cp->harshness[0]) == 0		

⌨️ 快捷键说明

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