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

📄 cp-call.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	}      i = 0;      do	{	  int exact_conversions = 0;	  i -= 1;	  tta = parms;	  if (DECL_STATIC_FUNCTION_P (cp[i].function))	    tta = TREE_CHAIN (tta);	  /* special note, we don't go through len parameters, because we	     may only need len-1 parameters because of a call to a static	     member. */	  for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)), index = 0;	       tta;	       tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)	    {	      if (USER_HARSHNESS (cp[i].harshness[index]))		{		  tree this_parm = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_PURPOSE (tta), 2);		  if (basetype != NULL_TREE)		    TREE_VALUE (tta) = this_parm;		  if (this_parm)		    {		      if (TREE_CODE (this_parm) != CONVERT_EXPR			  && (TREE_CODE (this_parm) != NOP_EXPR			      || comp_target_types (TREE_TYPE (this_parm),						    TREE_TYPE (TREE_OPERAND (this_parm, 0)), 1)))			exact_conversions += 1;		    }		  else if (PROMOTES_TO_AGGR_TYPE (TREE_VALUE (ttf), REFERENCE_TYPE))		    {		      /* To get here we had to have succeeded via			 a constructor.  */		      TREE_VALUE (tta) = TREE_PURPOSE (tta);		      exact_conversions += 1;		    }		}	    }	  if (exact_conversions == cp[i].user)	    {	      if (best == 0)		{		  best = i;		  f1 = cp[best].function;		  p1 = TYPE_ARG_TYPES (TREE_TYPE (f1));		}	      else		{		  /* Don't complain if next best is from base class.  */		  tree f2 = cp[i].function;		  if (TREE_CODE (TREE_TYPE (f1)) == METHOD_TYPE		      && TREE_CODE (TREE_TYPE (f2)) == METHOD_TYPE		      && BASE_DERIVED_HARSHNESS (cp[i].harshness[0])		      && cp[best].harshness[0] < cp[i].harshness[0])		    {#if 0		      tree p2 = TYPE_ARG_TYPES (TREE_TYPE (f2));		      /* For LUCID.  */		      if (! compparms (TREE_CHAIN (p1), TREE_CHAIN (p2), 1))			goto ret0;		      else#endif			continue;		    }		  else		    {		      /* Ensure that there's nothing ambiguous about these			 two fns.  */		      int identical = 1;		      for (index = 0; index < len; index++)			{			  /* Type conversions must be piecewise equivalent.  */			  if (USER_HARSHNESS (cp[best].harshness[index])			      != USER_HARSHNESS (cp[i].harshness[index]))			    goto ret0;			  /* If there's anything we like better about the			     other function, consider it ambiguous.  */			  if (cp[i].harshness[index] < cp[best].harshness[index])			    goto ret0;			  /* If any single one it diffent, then the whole is			     not identical.  */			  if (cp[i].harshness[index] != cp[best].harshness[index])			    identical = 0;			}		      /* If we can't tell the difference between the two, it			 is ambiguous.  */		      if (identical)			goto ret0;		      /* If we made it to here, it means we're satisfied that			 BEST is still best.  */		      continue;		    }		}	    }	} while (cp + i != candidates);      if (best)	{	  int exact_conversions = cp[best].user;	  tta = parms;	  if (DECL_STATIC_FUNCTION_P (cp[best].function))	    tta = TREE_CHAIN (parms);	  for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[best].function)), index = 0;	       exact_conversions > 0;	       tta = TREE_CHAIN (tta), ttf = TREE_CHAIN (ttf), index++)	    {	      if (USER_HARSHNESS (cp[best].harshness[index]))		{		  /* We must now fill in the slot we left behind.		     @@ This could be optimized to use the value previously		     @@ computed by build_type_conversion in some cases.  */		  if (basetype != NULL_TREE)		    TREE_VALUE (tta) = convert (TREE_VALUE (ttf), TREE_PURPOSE (tta));		  exact_conversions -= 1;		}	      else TREE_VALUE (tta) = TREE_PURPOSE (tta);	    }	  return cp + best;	}      goto ret0;    }  /* If the best two candidates we find both use default parameters,     we may need to report and error.  Don't need to worry if next-best     candidate is forced to use user-defined conversion when best is not.  */  if (cp[-2].user == 0      && cp[-1].harshness[len] != 0 && cp[-2].harshness[len] != 0)    {      tree tt1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function));      tree tt2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function));      unsigned i = cp[-1].harshness[len];      if (cp[-2].harshness[len] < i)	i = cp[-2].harshness[len];      while (--i > 0)	{	  if (TYPE_MAIN_VARIANT (TREE_VALUE (tt1))	      != TYPE_MAIN_VARIANT (TREE_VALUE (tt2)))	    /* These lists are not identical, so we can choose our best candidate.  */	    return cp - 1;	  tt1 = TREE_CHAIN (tt1);	  tt2 = TREE_CHAIN (tt2);	}      /* To get here, both lists had the same parameters up to the defaults	 which were used.  This is an ambiguous request.  */      goto ret0;    }  /* Otherwise, return our best candidate.  Note that if we get candidates     from independent base classes, we have an ambiguity, even if one     argument list look a little better than another one.  */  if (cp[-1].b_or_d && basetype && TYPE_USES_MULTIPLE_INHERITANCE (basetype))    {      int i = n_candidates - 1, best = i;      tree base1 = NULL_TREE;      if (TREE_CODE (TREE_TYPE (candidates[i].function)) == FUNCTION_TYPE)	return cp - 1;      for (; i >= 0 && candidates[i].user == 0 && candidates[i].evil == 0; i--)	{	  if (TREE_CODE (TREE_TYPE (candidates[i].function)) == METHOD_TYPE)	    {	      tree newbase = DECL_CLASS_CONTEXT (candidates[i].function);	      if (base1 != NULL_TREE)		{		  /* newbase could be a base or a parent of base1 */		  if (newbase != base1 && ! UNIQUELY_DERIVED_FROM_P (newbase, base1)		      && ! UNIQUELY_DERIVED_FROM_P (base1, newbase))		    {		      error_with_aggr_type (basetype, "ambiguous request for function from distinct base classes of type `%s'");		      error ("first candidate is `%s'",			     fndecl_as_string (0, candidates[best].function, 1));		      error ("second candidate is `%s'",			     fndecl_as_string (0, candidates[i].function, 1));		      cp[-1].evil = 1;		      return cp - 1;		    }		}	      else		{		  best = i;		  base1 = newbase;		}	    }	  else return cp - 1;	}    }  /* Don't accept a candidate as being ideal if it's indistinguishable     from another candidate.  */  if (rank_for_overload (cp-1, cp-2) == 0)    {      /* If the types are distinguishably different (like	 `long' vs. `unsigned long'), that's ok.  But if they are arbitrarily	 different, such as `int (*)(void)' vs. `void (*)(int)',	 that's not ok.  */      tree p1 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function));      tree p2 = TYPE_ARG_TYPES (TREE_TYPE (cp[-2].function));      while (p1 && p2)	{	  if (TREE_CODE (TREE_VALUE (p1)) == POINTER_TYPE	      && TREE_CODE (TREE_TYPE (TREE_VALUE (p1))) == FUNCTION_TYPE	      && TREE_VALUE (p1) != TREE_VALUE (p2))	    return 0;	  p1 = TREE_CHAIN (p1);	  p2 = TREE_CHAIN (p2);	}      if (p1 || p2)	return 0;    }  return cp - 1; ret0:  /* In the case where there is no ideal candidate, restore     TREE_VALUE slots of PARMS from TREE_PURPOSE slots.  */  while (parms)    {      TREE_VALUE (parms) = TREE_PURPOSE (parms);      parms = TREE_CHAIN (parms);    }  return 0;}/* Assume that if the class referred to is not in the   current class hierarchy, that it may be remote.   PARENT is assumed to be of aggregate type here.  */static intmay_be_remote (parent)     tree parent;{  if (TYPE_OVERLOADS_METHOD_CALL_EXPR (parent) == 0)    return 0;  if (current_class_type == NULL_TREE)    return 0;  if (parent == current_class_type)    return 0;  if (UNIQUELY_DERIVED_FROM_P (parent, current_class_type))    return 0;  return 1;}#ifdef ESKIT/* Return the number of bytes that the arglist in PARMS would   occupy on the stack.  */intget_arglist_len_in_bytes (parms)     tree parms;{  register tree parm;  register int bytecount = 0;  for (parm = parms; parm; parm = TREE_CHAIN (parm))    {      register tree pval = TREE_VALUE (parm);      register int used, size;      if (TREE_CODE (pval) == ERROR_MARK)	continue;      else if (TYPE_MODE (TREE_TYPE (pval)) != BLKmode)	{	  used = size = GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (pval)));#ifdef PUSH_ROUNDING	  size = PUSH_ROUNDING (size);#endif	  used = (((size + PARM_BOUNDARY / BITS_PER_UNIT - 1)		   / (PARM_BOUNDARY / BITS_PER_UNIT))		  * (PARM_BOUNDARY / BITS_PER_UNIT));	}      else	{	  register tree size = size_in_bytes (TREE_TYPE (pval));	  register tree used_t	    = round_up (size, PARM_BOUNDARY / BITS_PER_UNIT);	  used = TREE_INT_CST_LOW (used_t);	}      bytecount += used;    }  return bytecount;}#endiftreebuild_vfield_ref (datum, type)     tree datum, type;{  tree rval;  int old_assume_nonnull_objects = flag_assume_nonnull_objects;  /* Vtable references are always made from non-null objects.  */  flag_assume_nonnull_objects = 1;  if (TREE_CODE (TREE_TYPE (datum)) == REFERENCE_TYPE)    datum = convert_from_reference (datum);  if (! TYPE_USES_COMPLEX_INHERITANCE (type))    rval = build (COMPONENT_REF, TREE_TYPE (CLASSTYPE_VFIELD (type)),		  datum, CLASSTYPE_VFIELD (type));  else    rval = build_component_ref (datum, DECL_NAME (CLASSTYPE_VFIELD (type)), 0, 0);  flag_assume_nonnull_objects = old_assume_nonnull_objects;  return rval;}/* Build a call to a member of an object.  I.e., one that overloads   operator ()(), or is a pointer-to-function or pointer-to-method.  */static treebuild_field_call (basetype_path, instance_ptr, name, parms, err_name)     tree basetype_path;     tree instance_ptr, name, parms;     char *err_name;{  tree field, instance;  if (instance_ptr == current_class_decl)    {      /* Check to see if we really have a reference to an instance variable	 with `operator()()' overloaded.  */      field = IDENTIFIER_CLASS_VALUE (name);      if (field == NULL_TREE)	{	  error ("`this' has no member named `%s'", err_name);	  return error_mark_node;	}      if (TREE_CODE (field) == FIELD_DECL)	{	  /* If it's a field, try overloading operator (),	     or calling if the field is a pointer-to-function.  */	  instance = build_component_ref_1 (C_C_D, field, 0);	  if (instance == error_mark_node)	    return error_mark_node;	  if (TYPE_LANG_SPECIFIC (TREE_TYPE (instance))	      && TYPE_OVERLOADS_CALL_EXPR (TREE_TYPE (instance)))	    return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, instance, parms);	  if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)	    if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)	      return build_function_call (instance, parms);	    else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == METHOD_TYPE)	      return build_function_call (instance, tree_cons (NULL_TREE, current_class_decl, parms));	}      return NULL_TREE;    }  /* Check to see if this is not really a reference to an instance variable     with `operator()()' overloaded.  */  field = lookup_field (basetype_path, name, 1, 0);  /* This can happen if the reference was ambiguous     or for visibility violations.  */  if (field == error_mark_node)    return error_mark_node;  if (field)    {      tree basetype;      tree ftype = TREE_TYPE (field);      if (TYPE_LANG_SPECIFIC (ftype) && TYPE_OVERLOADS_CALL_EXPR (ftype))	{	  /* Make the next search for this field very short.  */	  basetype = DECL_FIELD_CONTEXT (field);	  instance_ptr = convert_pointer_to (basetype, instance_ptr);	  instance = build_indirect_ref (instance_ptr, 0);	  return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,				 build_component_ref_1 (instance, field, 0),				 parms);	}      if (TREE_CODE (ftype) == POINTER_TYPE)	{	  if (TREE_CODE (TREE_TYPE (ftype)) == FUNCTION_TYPE	      || TREE_CODE (TREE_TYPE (ftype)) == METHOD_TYPE)	    {	      /* This is a member which is a pointer to function.  */	      tree ref = build_component_ref_1 (build_indirect_ref (instance_ptr, 0),						field, LOOKUP_COMPLAIN);	      if (ref == error_mark_node)		return error_mark_node;	      return build_function_call (ref, parms);	    }	}      else if (TREE_CODE (ftype) == METHOD_TYPE)	{	  error ("invalid call via pointer-to-member function");	  return error_mark_node;	}      else	return NULL_TREE;    }  return NULL_TREE;}treefind_scoped_type (type, inner_name, inner_types)     tree type, inner_name, inner_types;{  tree tags = CLASSTYPE_TAGS (type);  while (tags)    {      /* The TREE_PURPOSE of an enum tag (which becomes a member of the	 enclosing class) is set to the name for the enum type.  So, if	 inner_name is `bar', and we strike `baz' for `enum bar { baz }',	 then this test will be true.  */      if (TREE_PURPOSE (tags) == inner_name)	{	  if (inner_types == NULL_TREE)	    return DECL_NESTED_TYPENAME (TYPE_NAME (TREE_VALUE (tags)));	  return resolve_scope_to_name (TREE_VALUE (tags), inner_types);	}      tags = TREE_CHAIN (tags);    }  /* Look for a TYPE_DECL.  */  for (tags = TYPE_FIELDS (type); tags; tags = TREE_CHAIN (tags))    if (TREE_CODE (tags) == TYPE_DECL && DECL_NAME (tags) == inner_name)      {	/* Code by raeburn.  */	if (inner_types == NULL_TREE)	  return DECL_NESTED_TYPENAME (tags);	return resolve_scope_to_name (TREE_TYPE (tags), inner_types);      }

⌨️ 快捷键说明

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