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

📄 cp-call.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	   matter if we make life easier for the programmer	   by creating a temporary variable with which to	   hold the result.  */	if (parm && (coder == INTEGER_TYPE		     || coder == ENUMERAL_TYPE		     || coder == REAL_TYPE)	    && ! lvalue_p (parm))	  return (convert_harshness (ttl, ttr, 0)		  | INT_TO_EASY_HARSHNESS (penalty));	if (ttl == ttr)	  {	    if (penalty)	      return INT_TO_EASY_HARSHNESS (penalty);	    return INT_TO_BD_HARSHNESS (0);	  }	/* Pointers to voids always convert for pointers.  But	   make them less natural than more specific matches.  */	if (TREE_CODE (ttl) == POINTER_TYPE && TREE_CODE (ttr) == POINTER_TYPE)	  if (TREE_TYPE (ttl) == void_type_node	      || TREE_TYPE (ttr) == void_type_node)	    return INT_TO_EASY_HARSHNESS (penalty+1);	if (parm && codel != REFERENCE_TYPE)	  return (convert_harshness (ttl, ttr, 0)		  | INT_TO_EASY_HARSHNESS (penalty));	/* Here it does matter.  If this conversion is from	   derived to base, allow it.  Otherwise, types must	   be compatible in the strong sense.  */	if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)	  {	    int b_or_d = get_base_distance (ttl, ttr, 0, 0);	    if (b_or_d < 0)	      {		b_or_d = get_base_distance (ttr, ttl, 0, 0);		if (b_or_d < 0)		  return 1;		return CONTRAVARIANT_HARSHNESS (-1);	      }	    /* Say that this conversion is relatively painless.	       If it turns out that there is a user-defined X(X&)	       constructor, then that will be invoked, but that's	       preferable to dealing with other user-defined conversions	       that may produce surprising results.  */	    return INT_TO_BD_HARSHNESS (b_or_d);	  }	if (comp_target_types (ttl, intype, 1))	  return INT_TO_EASY_HARSHNESS (penalty);      }  }  if (codel == RECORD_TYPE && coder == RECORD_TYPE)    {      int b_or_d = get_base_distance (type, parmtype, 0, 0);      if (b_or_d < 0)	{	  b_or_d = get_base_distance (parmtype, type, 0, 0);	  if (b_or_d < 0)	    return 1;	  return CONTRAVARIANT_HARSHNESS (-1);	}      return INT_TO_BD_HARSHNESS (b_or_d);    }  return 1;}/* Algorithm: Start out with no strikes against.  For each argument   which requires a (subjective) hard conversion (such as between   floating point and integer), issue a strike.  If there are the same   number of formal and actual parameters in the list, there will be at   least on strike, otherwise an exact match would have been found.  If   there are not the same number of arguments in the type lists, we are   not dead yet: a `...' means that we can have more parms then were   declared, and if we wind up in the default argument section of the   list those can be used as well.  If an exact match could be found for   one of those cases, return it immediately.  Otherwise, rank the fields   so that fields with fewer strikes are tried first.   Conversions between builtin and user-defined types are allowed, but   no function involving such a conversion is preferred to one which   does not require such a conversion.  Furthermore, such conversions   must be unique.  */voidcompute_conversion_costs (function, tta_in, cp, arglen)     tree function;     tree tta_in;     struct candidate *cp;     int arglen;{  tree ttf_in = TYPE_ARG_TYPES (TREE_TYPE (function));  tree ttf = ttf_in;  tree tta = tta_in;  /* Start out with no strikes against.  */  int evil_strikes = 0;  int user_strikes = 0;  int b_or_d_strikes = 0;  int easy_strikes = 0;  int strike_index = 0, win, lose;#ifdef GATHER_STATISTICS  n_compute_conversion_costs++;#endif  cp->function = function;  cp->arg = tta ? TREE_VALUE (tta) : NULL_TREE;  cp->u.bad_arg = 0;		/* optimistic!  */  bzero (cp->harshness, (arglen+1) * sizeof (short));  while (ttf && tta)    {      int harshness;      if (ttf == void_list_node)	break;      if (type_unknown_p (TREE_VALUE (tta)))	{	  	  /* Must perform some instantiation here.  */	  tree rhs = TREE_VALUE (tta);	  tree lhstype = TREE_VALUE (ttf);	  /* Keep quiet about possible contravariance violations.  */	  int old_inhibit_warnings = inhibit_warnings;	  inhibit_warnings = 1;	  /* @@ This is to undo what `grokdeclarator' does to	     parameter types.  It really should go through	     something more general.  */	  TREE_TYPE (tta) = unknown_type_node;	  rhs = instantiate_type (lhstype, rhs, 0);	  inhibit_warnings = old_inhibit_warnings;	  if (TREE_CODE (rhs) == ERROR_MARK)	    harshness = 1;	  else	    {	      harshness = convert_harshness (lhstype, TREE_TYPE (rhs), rhs);	      /* harshness |= 2; */	    }	}      else	harshness = convert_harshness (TREE_VALUE (ttf), TREE_TYPE (TREE_VALUE (tta)), TREE_VALUE (tta));      cp->harshness[strike_index] = harshness;      if (EVIL_HARSHNESS (harshness)	  || CONTRAVARIANT_HARSHNESS (harshness))	{	  cp->u.bad_arg = strike_index;	  evil_strikes = 1;	}#if 0      /* This is never set by `convert_harshness'.  */      else if (USER_HARSHNESS (harshness))	{	  user_strikes += 1;	}#endif      else if (BASE_DERIVED_HARSHNESS (harshness))	{	  b_or_d_strikes += INT_FROM_BD_HARSHNESS (harshness);	}      else	easy_strikes += INT_FROM_EASY_HARSHNESS (harshness);      ttf = TREE_CHAIN (ttf);      tta = TREE_CHAIN (tta);      strike_index += 1;    }  if (tta)    {      /* ran out of formals, and parmlist is fixed size.  */      if (ttf /* == void_type_node */)	{	  cp->evil = 1;	  cp->u.bad_arg = -1;	  return;	}    }  else if (ttf && ttf != void_list_node)    {      /* ran out of actuals, and no defaults.  */      if (TREE_PURPOSE (ttf) == NULL_TREE)	{	  cp->evil = 1;	  cp->u.bad_arg = -2;	  return;	}      /* Store index of first default.  */      cp->harshness[arglen] = strike_index+1;    }  else cp->harshness[arglen] = 0;  /* Argument list lengths work out, so don't need to check them again.  */  if (evil_strikes)    {      /* We do not check for derived->base conversions here, since in	 no case would they give evil strike counts, unless such conversions	 are somehow ambiguous.  */      /* See if any user-defined conversions apply.         But make sure that we do not loop.  */      static int dont_convert_types = 0;      if (dont_convert_types)	{	  cp->evil = 1;	  return;	}      win = 0;			/* Only get one chance to win.  */      ttf = TYPE_ARG_TYPES (TREE_TYPE (function));      tta = tta_in;      strike_index = 0;      evil_strikes = 0;      while (ttf && tta)	{	  if (ttf == void_list_node)	    break;	  lose = cp->harshness[strike_index];	  if (EVIL_HARSHNESS (lose)	      || CONTRAVARIANT_HARSHNESS (lose))	    {	      tree actual_type = TREE_TYPE (TREE_VALUE (tta));	      tree formal_type = TREE_VALUE (ttf);	      dont_convert_types = 1;	      if (TREE_CODE (formal_type) == REFERENCE_TYPE)		formal_type = TREE_TYPE (formal_type);	      if (TREE_CODE (actual_type) == REFERENCE_TYPE)		actual_type = TREE_TYPE (actual_type);	      if (formal_type != error_mark_node		  && actual_type != error_mark_node)		{		  formal_type = TYPE_MAIN_VARIANT (formal_type);		  actual_type = TYPE_MAIN_VARIANT (actual_type);		  if (TYPE_HAS_CONSTRUCTOR (formal_type))		    {		      /* If it has a constructor for this type, try to use it.  */		      if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)			  != error_mark_node)			{			  /* @@ There is no way to save this result yet.			     @@ So success is NULL_TREE for now.  */			  win++;			}		    }		  if (TYPE_LANG_SPECIFIC (actual_type) && TYPE_HAS_CONVERSION (actual_type))		    {		      if (TREE_CODE (formal_type) == INTEGER_TYPE			  && TYPE_HAS_INT_CONVERSION (actual_type))			win++;		      else if (TREE_CODE (formal_type) == REAL_TYPE			       && TYPE_HAS_REAL_CONVERSION (actual_type))			win++;		      else			{			  tree conv = build_type_conversion (CALL_EXPR, TREE_VALUE (ttf), TREE_VALUE (tta), 0);			  if (conv)			    {			      if (conv == error_mark_node)				win += 2;			      else				win++;			    }			  else if (TREE_CODE (TREE_VALUE (ttf)) == REFERENCE_TYPE)			    {			      conv = build_type_conversion (CALL_EXPR, formal_type, TREE_VALUE (tta), 0);			      if (conv)				{				  if (conv == error_mark_node)				    win += 2;				  else				    win++;				}			    }			}		    }		}	      dont_convert_types = 0;	      if (win == 1)		{		  user_strikes += 1;		  cp->harshness[strike_index] = USER_HARSHNESS (-1);		  win = 0;		}	      else		{		  if (cp->u.bad_arg > strike_index)		    cp->u.bad_arg = strike_index;		  evil_strikes = win ? 2 : 1;		  break;		}	    }	  ttf = TREE_CHAIN (ttf);	  tta = TREE_CHAIN (tta);	  strike_index += 1;	}    }  /* Const member functions get a small penalty because defaulting     to const is less useful than defaulting to non-const. */  /* This is bogus, it does not correspond to anything in the ARM.     This code will be fixed when this entire section is rewritten     to conform to the ARM.  (mrs)  */  if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)    {      if (TYPE_READONLY (TREE_TYPE (TREE_VALUE (ttf_in))))	{	  cp->harshness[0] += INT_TO_EASY_HARSHNESS (1);	  ++easy_strikes;	}      else	{	  /* Calling a non-const member function from a const member function	     is probably invalid, but for now we let it only draw a warning.	     We indicate that such a mismatch has occurred by setting the	     harshness to a maximum value.  */	  if (TREE_CODE (TREE_TYPE (TREE_VALUE (tta_in))) == POINTER_TYPE	      && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (TREE_VALUE (tta_in))))))	    cp->harshness[0] |= CONST_HARSHNESS (-1);	}    }  cp->evil = evil_strikes;  cp->user = user_strikes;  cp->b_or_d = b_or_d_strikes;  cp->easy = easy_strikes;}/* When one of several possible overloaded functions and/or methods   can be called, choose the best candidate for overloading.   BASETYPE is the context from which we start method resolution   or NULL if we are comparing overloaded functions.   CANDIDATES is the array of candidates we have to choose from.   N_CANDIDATES is the length of CANDIDATES.   PARMS is a TREE_LIST of parameters to the function we'll ultimately   choose.  It is modified in place when resolving methods.  It is not   modified in place when resolving overloaded functions.   LEN is the length of the parameter list.  */static struct candidate *ideal_candidate (basetype, candidates, n_candidates, parms, len)     tree basetype;     struct candidate *candidates;     int n_candidates;     tree parms;     int len;{  struct candidate *cp = candidates + n_candidates;  int index, i;  tree ttf;  qsort (candidates,		/* char *base */	 n_candidates,		/* int nel */	 sizeof (struct candidate), /* int width */	 rank_for_overload);	/* int (*compar)() */  /* If the best candidate requires user-defined conversions,     and its user-defined conversions are a strict subset     of all other candidates requiring user-defined conversions,     then it is, in fact, the best.  */  for (i = -1; cp + i != candidates; i--)    if (cp[i].user == 0)      break;  if (i < -1)    {      tree ttf0;      /* Check that every other candidate requires those conversions	 as a strict subset of their conversions.  */      if (cp[i].user == cp[-1].user)	goto non_subset;      /* Look at subset relationship more closely.  */      while (i != -1)	{	  for (ttf = TYPE_ARG_TYPES (TREE_TYPE (cp[i].function)),	       ttf0 = TYPE_ARG_TYPES (TREE_TYPE (cp[-1].function)),	       index = 0;	       index < len;	       ttf = TREE_CHAIN (ttf), ttf0 = TREE_CHAIN (ttf0), index++)	    if (USER_HARSHNESS (cp[i].harshness[index]))	      {		/* If our "best" candidate also needs a conversion,		   it must be the same one.  */		if (USER_HARSHNESS (cp[-1].harshness[index])		    && TREE_VALUE (ttf) != TREE_VALUE (ttf0))		  goto non_subset;	      }	  i++;	}      /* The best was the best.  */      return cp - 1;    non_subset:      /* Use other rules for determining "bestness".  */      ;    }  /* If the best two candidates we find require user-defined     conversions, we may need to report and error message.  */  if (cp[-1].user && cp[-2].user      && (cp[-1].b_or_d || cp[-2].b_or_d == 0))    {      /* If the best two methods found involved user-defined	 type conversions, then we must see whether one	 of them is exactly what we wanted.  If not, then	 we have an ambiguity.  */      int best = 0;      tree tta = parms;      tree f1, p1;      /* Stash all of our parameters in safe places	 so that we can perform type conversions in place.  */      while (tta)	{	  TREE_PURPOSE (tta) = TREE_VALUE (tta);	  tta = TREE_CHAIN (tta);

⌨️ 快捷键说明

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