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

📄 call.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
	{	  cp->h.code = EVIL_CODE;	  cp->u.bad_arg = -2;	  cp_silent = 0;	  return;	}      /* Store index of first default.  */      cp->harshness[arglen].distance = strike_index+1;    }  else    cp->harshness[arglen].distance = 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->h.code = EVIL_CODE;	  cp_silent = 0;	  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 ((lose.code & EVIL_CODE)	      || ((lose.code & STD_CODE) && lose.distance < 0))	    {	      tree actual_type = TREE_TYPE (TREE_VALUE (tta));	      tree formal_type = TREE_VALUE (ttf);	      int extra_conversions = 0;	      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.  */		      /* @@ There is no way to save this result yet, so			 success is a NULL_TREE for now.  */		      if (convert_to_aggr (formal_type, TREE_VALUE (tta), 0, 1)			  != error_mark_node)			win++;		    }		  if (TYPE_LANG_SPECIFIC (actual_type)		      && TYPE_HAS_CONVERSION (actual_type))		    {		      int extra = user_harshness (formal_type, actual_type);		      if (extra == EVIL_CODE)			win += 2;		      else if (extra >= 0)			{			  win++;			  extra_conversions = extra;			}		    }		}	      dont_convert_types = 0;	      if (win == 1)		{		  user_strikes += 1;		  cp->harshness[strike_index].code		    = USER_CODE | (extra_conversions ? STD_CODE : 0);		  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)    {      tree this_parm = TREE_VALUE (ttf_in);      if (TREE_CODE (this_parm) == RECORD_TYPE	/* Is `this' a sig ptr?  */	    ? TYPE_READONLY (TREE_TYPE (TREE_TYPE (TYPE_FIELDS (this_parm))))	    : TYPE_READONLY (TREE_TYPE (this_parm)))	{	  cp->harshness[0].code |= TRIVIAL_CODE;	  ++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].code |= CONST_CODE;	}    }  if (evil_strikes)    cp->h.code = EVIL_CODE;  if (ellipsis_strikes)    cp->h.code |= ELLIPSIS_CODE;  if (user_strikes)    cp->h.code |= USER_CODE;  cp_silent = 0;#ifdef DEBUG_MATCHING  cp_error ("final eval %s", print_harshness (&cp->h));#endif}/* Subroutine of ideal_candidate.  See if X or Y is a better match   than the other.  */static intstrictly_better (x, y)     unsigned short x, y;{  unsigned short xor;  if (x == y)    return 0;  xor = x ^ y;  if (xor >= x || xor >= y)    return 1;  return 0;}/* 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 i, j = -1, best_code;  /* For each argument, sort the functions from best to worst for the arg.     For each function that's not best for this arg, set its overall     harshness to EVIL so that other args won't like it.  The candidate     list for the last argument is the intersection of all the best-liked     functions.  */#if 0  for (i = 0; i < len; i++)    {      qsort (candidates, n_candidates, sizeof (struct candidate),	     rank_for_overload);      best_code = cp[-1].h.code;      /* To find out functions that are worse than that represented	 by BEST_CODE, we can't just do a comparison like h.code>best_code.	 The total harshness for the "best" fn may be 8|8 for two args, and	 the harshness for the next-best may be 8|2.  If we just compared,	 that would be checking 8>10, which would lead to the next-best	 being disqualified.  What we actually want to do is get rid	 of functions that are definitely worse than that represented	 by best_code, i.e. those which have bits set higher than the	 highest in best_code.  Sooooo, what we do is clear out everything	 represented by best_code, and see if we still come up with something	 higher.  If so (e.g., 8|8 vs 8|16), it'll disqualify it properly.  */      for (j = n_candidates-2; j >= 0; j--)	if ((candidates[j].h.code & ~best_code) > best_code)	  candidates[j].h.code = EVIL_CODE;    }  if (cp[-1].h.code & EVIL_CODE)    return NULL;#else  qsort (candidates, n_candidates, sizeof (struct candidate),	 rank_for_overload);  best_code = cp[-1].h.code;#endif  /* If they're at least as good as each other, do an arg-by-arg check.  */  if (! strictly_better (cp[-1].h.code, cp[-2].h.code))    {      int better = 0;      int worse = 0;      for (j = 0; j < n_candidates; j++)	if (! strictly_better (candidates[j].h.code, best_code))	  break;      qsort (candidates+j, n_candidates-j, sizeof (struct candidate),	     rank_for_ideal);      for (i = 0; i < len; i++)	{	  if (cp[-1].harshness[i].code < cp[-2].harshness[i].code)	    better = 1;	  else if (cp[-1].harshness[i].code > cp[-2].harshness[i].code)	    worse = 1;	  else if (cp[-1].harshness[i].code & STD_CODE)	    {	      /* If it involves a standard conversion, let the		 inheritance lattice be the final arbiter.  */	      if (cp[-1].harshness[i].distance > cp[-2].harshness[i].distance)		worse = 1;	      else if (cp[-1].harshness[i].distance < cp[-2].harshness[i].distance)		better = 1;	    }	  else if (cp[-1].harshness[i].code & PROMO_CODE)	    {	      /* For integral promotions, take into account a finer		 granularity for determining which types should be favored		 over others in such promotions.  */	      if (cp[-1].harshness[i].int_penalty > cp[-2].harshness[i].int_penalty)		worse = 1;	      else if (cp[-1].harshness[i].int_penalty < cp[-2].harshness[i].int_penalty)		better = 1;	    }	}      if (! better || worse)	return NULL;    }  return cp-1;}/* 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;}treebuild_vfield_ref (datum, type)     tree datum, type;{  tree rval;  int old_assume_nonnull_objects = flag_assume_nonnull_objects;  if (datum == error_mark_node)    return error_mark_node;  /* 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)     tree basetype_path, instance_ptr, name, parms;{  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)	{	  cp_error ("`this' has no member named `%D'", 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, NULL_TREE);	  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 access     violations.  */  if (field == error_mark_node)    return error_mark_node;  if (field)    {      tree basetype;      tree ftype = TREE_TYPE (field);      if (TREE_CODE (ftype) == REFERENCE_TYPE)	ftype = TREE_TYPE (ftype);      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, NULL_PTR);	  return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,				 build_component_ref_1 (instance, field, 0),				 parms, NULL_TREE);	}      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,							     NULL_PTR),					 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);    }#if 0  /* XXX This needs to be fixed better.  */  if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE)    {      sorry ("nested class lookup in template type");      return NULL_TREE;    }#endif  /* 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 + -