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

📄 call.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Functions related to invoking methods and overloaded functions.   Copyright (C) 1987, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.   Contributed by Michael Tiemann (tiemann@cygnus.com) and   hacked by Brendan Kehoe (brendan@cygnus.com).This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING.  If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA.  *//* High-level class interface. */#include "config.h"#include "tree.h"#include <stdio.h>#include "cp-tree.h"#include "class.h"#include "output.h"#include "flags.h"#include "obstack.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern void sorry ();extern int inhibit_warnings;extern int flag_assume_nonnull_objects;extern tree ctor_label, dtor_label;/* From typeck.c:  */extern tree unary_complex_lvalue ();/* Compute the ease with which a conversion can be performed   between an expected and the given type.  */static struct harshness_code convert_harshness ();#define EVIL_RETURN(ARG)	((ARG).code = EVIL_CODE, (ARG))#define STD_RETURN(ARG)		((ARG).code = STD_CODE, (ARG))#define QUAL_RETURN(ARG)	((ARG).code = QUAL_CODE, (ARG))#define TRIVIAL_RETURN(ARG)	((ARG).code = TRIVIAL_CODE, (ARG))#define ZERO_RETURN(ARG)	((ARG).code = 0, (ARG))/* Ordering function for overload resolution.  Compare two candidates   by gross quality.  */intrank_for_overload (x, y)     struct candidate *x, *y;{  if (y->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))    return y->h.code - x->h.code;  if (x->h.code & (EVIL_CODE|ELLIPSIS_CODE|USER_CODE))    return -1;  /* This is set by compute_conversion_costs, for calling a non-const     member function from a const member function.  */  if ((y->harshness[0].code & CONST_CODE) ^ (x->harshness[0].code & CONST_CODE))    return y->harshness[0].code - x->harshness[0].code;  if (y->h.code & STD_CODE)    {      if (x->h.code & STD_CODE)	return y->h.distance - x->h.distance;      return 1;    }  if (x->h.code & STD_CODE)    return -1;  return y->h.code - x->h.code;}/* Compare two candidates, argument by argument.  */intrank_for_ideal (x, y)     struct candidate *x, *y;{  int i;  if (x->h_len != y->h_len)    abort ();  for (i = 0; i < x->h_len; i++)    {      if (y->harshness[i].code - x->harshness[i].code)	return y->harshness[i].code - x->harshness[i].code;      if ((y->harshness[i].code & STD_CODE)	  && (y->harshness[i].distance - x->harshness[i].distance))	return y->harshness[i].distance - x->harshness[i].distance;      /* They're both the same code.  Now see if we're dealing with an	 integral promotion that needs a finer grain of accuracy.  */      if (y->harshness[0].code & PROMO_CODE	  && (y->harshness[i].int_penalty ^ x->harshness[i].int_penalty))	return y->harshness[i].int_penalty - x->harshness[i].int_penalty;    }  return 0;}/* TYPE is the type we wish to convert to.  PARM is the parameter   we have to work with.  We use a somewhat arbitrary cost function   to measure this conversion.  */static struct harshness_codeconvert_harshness (type, parmtype, parm)     register tree type, parmtype;     tree parm;{  struct harshness_code h;  register enum tree_code codel;  register enum tree_code coder;  int lvalue;  h.code = 0;  h.distance = 0;  h.int_penalty = 0;#ifdef GATHER_STATISTICS  n_convert_harshness++;#endif  if (TREE_CODE (parmtype) == REFERENCE_TYPE)    {      if (parm)	parm = convert_from_reference (parm);      parmtype = TREE_TYPE (parmtype);      lvalue = 1;    }  else if (parm)    lvalue = lvalue_p (parm);  else    lvalue = 0;  if (TYPE_PTRMEMFUNC_P (type))    type = TYPE_PTRMEMFUNC_FN_TYPE (type);  if (TYPE_PTRMEMFUNC_P (parmtype))    parmtype = TYPE_PTRMEMFUNC_FN_TYPE (parmtype);  codel = TREE_CODE (type);  coder = TREE_CODE (parmtype);  if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))    return ZERO_RETURN (h);  if (coder == ERROR_MARK)    return EVIL_RETURN (h);  if (codel == REFERENCE_TYPE)    {      tree ttl, ttr;      int constp = parm ? TREE_READONLY (parm) : TYPE_READONLY (parmtype);      int volatilep = (parm ? TREE_THIS_VOLATILE (parm)		       : TYPE_VOLATILE (parmtype));      register tree intype = TYPE_MAIN_VARIANT (parmtype);      register enum tree_code form = TREE_CODE (intype);      int penalty = 0;      ttl = TREE_TYPE (type);      /* Only allow const reference binding if we were given a parm to deal         with, since it isn't really a conversion.  This is a hack to         prevent build_type_conversion from finding this conversion, but         still allow overloading to find it.  */      if (! lvalue && ! (parm && TYPE_READONLY (ttl)))	return EVIL_RETURN (h);      if (TYPE_READONLY (ttl) < constp	  || TYPE_VOLATILE (ttl) < volatilep)	return EVIL_RETURN (h);      /* When passing a non-const argument into a const reference, dig it a	 little, so a non-const reference is preferred over this one.  */      penalty = ((TYPE_READONLY (ttl) > constp)		 + (TYPE_VOLATILE (ttl) > volatilep));      ttl = TYPE_MAIN_VARIANT (ttl);      if (form == OFFSET_TYPE)	{	  intype = TREE_TYPE (intype);	  form = TREE_CODE (intype);	}      ttr = intype;      if (TREE_CODE (ttl) == ARRAY_TYPE && TREE_CODE (ttr) == ARRAY_TYPE)	{	  if (comptypes (ttl, ttr, 1))	    return ZERO_RETURN (h);	  return EVIL_RETURN (h);	}      h = convert_harshness (ttl, ttr, NULL_TREE);      if (penalty && h.code == 0)	{	  h.code = QUAL_CODE;	  h.int_penalty = penalty;	}      return h;    }  if (codel == POINTER_TYPE && fntype_p (parmtype))    {      tree p1, p2;      struct harshness_code h1, h2;      /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be.  */      type = TREE_TYPE (type);      if (coder == POINTER_TYPE)	{	  parmtype = TREE_TYPE (parmtype);	  coder = TREE_CODE (parmtype);	}      if (coder != TREE_CODE (type))	return EVIL_RETURN (h);      if (type != parmtype && coder == METHOD_TYPE)	{	  tree ttl = TYPE_METHOD_BASETYPE (type);	  tree ttr = TYPE_METHOD_BASETYPE (parmtype);	  int b_or_d = get_base_distance (ttr, ttl, 0, 0);	  if (b_or_d < 0)	    {	      b_or_d = get_base_distance (ttl, ttr, 0, 0);	      if (b_or_d < 0)		return EVIL_RETURN (h);	      h.distance = -b_or_d;	    }	  else	    h.distance = b_or_d;	  h.code = STD_CODE;	  type = build_function_type	    (TREE_TYPE (type), TREE_CHAIN (TYPE_ARG_TYPES (type)));	  parmtype = build_function_type	    (TREE_TYPE (parmtype), TREE_CHAIN (TYPE_ARG_TYPES (parmtype)));	}      /* We allow the default conversion between function type	 and pointer-to-function type for free.  */      if (comptypes (type, parmtype, 1))	return h;      if (pedantic)	return EVIL_RETURN (h);      /* Compare return types.  */      p1 = TREE_TYPE (type);      p2 = TREE_TYPE (parmtype);      h2 = convert_harshness (p1, p2, NULL_TREE);      if (h2.code & EVIL_CODE)	return h2;      h1.code = TRIVIAL_CODE;      h1.distance = 0;      if (h2.distance != 0)	{	  tree binfo;	  /* This only works for pointers.  */	  if (TREE_CODE (p1) != POINTER_TYPE	      && TREE_CODE (p1) != REFERENCE_TYPE)	    return EVIL_RETURN (h);	  p1 = TREE_TYPE (p1);	  p2 = TREE_TYPE (p2);	  /* Don't die if we happen to be dealing with void*.  */	  if (!IS_AGGR_TYPE (p1) || !IS_AGGR_TYPE (p2))	    return EVIL_RETURN (h);	  if (h2.distance < 0)	    binfo = get_binfo (p2, p1, 0);	  else	    binfo = get_binfo (p1, p2, 0);	  if (! BINFO_OFFSET_ZEROP (binfo))	    {#if 0	      static int explained = 0;	      if (h2.distance < 0)		message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p2, p1);	      else		message_2_types (sorry, "cannot cast `%s' to `%s' at function call site", p1, p2);	      if (! explained++)		sorry ("(because pointer values change during conversion)");#endif	      return EVIL_RETURN (h);	    }	}      h1.code |= h2.code;      if (h2.distance > h1.distance)	h1.distance = h2.distance;      p1 = TYPE_ARG_TYPES (type);      p2 = TYPE_ARG_TYPES (parmtype);      while (p1 && TREE_VALUE (p1) != void_type_node	     && p2 && TREE_VALUE (p2) != void_type_node)	{	  h2 = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2),				       NULL_TREE);	  if (h2.code & EVIL_CODE)	    return h2;	  if (h2.distance)	    {	      /* This only works for pointers and references. */	      if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE		  && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE)		return EVIL_RETURN (h);	      h2.distance = - h2.distance;	    }	  h1.code |= h2.code;	  if (h2.distance > h1.distance)	    h1.distance = h2.distance;	  p1 = TREE_CHAIN (p1);	  p2 = TREE_CHAIN (p2);	}      if (p1 == p2)	return h1;      if (p2)	{	  if (p1)	    return EVIL_RETURN (h);	  h1.code |= ELLIPSIS_CODE;	  return h1;	}      if (p1)	{	  if (TREE_PURPOSE (p1) == NULL_TREE)	    h1.code |= EVIL_CODE;	  return h1;	}    }  else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)    {      tree ttl, ttr;      /* Get to the OFFSET_TYPE that this might be.  */      type = TREE_TYPE (type);      if (coder != TREE_CODE (type))	return EVIL_RETURN (h);      ttl = TYPE_OFFSET_BASETYPE (type);      ttr = TYPE_OFFSET_BASETYPE (parmtype);      if (ttl == ttr)	h.code = 0;      else	{	  int b_or_d = get_base_distance (ttr, ttl, 0, 0);	  if (b_or_d < 0)	    {	      b_or_d = get_base_distance (ttl, ttr, 0, 0);	      if (b_or_d < 0)		return EVIL_RETURN (h);	      h.distance = -b_or_d;	    }	  else	    h.distance = b_or_d;	  h.code = STD_CODE;	}      /* Now test the OFFSET_TYPE's target compatibility.  */      type = TREE_TYPE (type);      parmtype = TREE_TYPE (parmtype);    }  if (coder == UNKNOWN_TYPE)    {      if (codel == FUNCTION_TYPE	  || codel == METHOD_TYPE	  || (codel == POINTER_TYPE	      && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE		  || TREE_CODE (TREE_TYPE (type)) == METHOD_TYPE)))	return TRIVIAL_RETURN (h);      return EVIL_RETURN (h);    }  if (coder == VOID_TYPE)    return EVIL_RETURN (h);  if (codel == BOOLEAN_TYPE)    {      if (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE)	return STD_RETURN (h);      else if (coder == POINTER_TYPE || coder == OFFSET_TYPE)	{	  /* Make this worse than any conversion to another pointer.	     FIXME this is how I think the language should work, but it may not	     end up being how the language is standardized (jason 1/30/95).  */	  h.distance = 32767;	  return STD_RETURN (h);	}      return EVIL_RETURN (h);    }  if (INTEGRAL_CODE_P (codel))    {      /* Control equivalence of ints an enums.  */      if (codel == ENUMERAL_TYPE	  && flag_int_enum_equivalence == 0)	{	  /* Enums can be converted to ints, but not vice-versa.  */	  if (coder != ENUMERAL_TYPE	      || TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (parmtype))	    return EVIL_RETURN (h);	}      /* else enums and ints (almost) freely interconvert.  */      if (INTEGRAL_CODE_P (coder))	{	  if (TYPE_MAIN_VARIANT (type)	      == TYPE_MAIN_VARIANT (type_promotes_to (parmtype)))	    {	      h.code = PROMO_CODE;#if 0 /* What purpose does this serve?  -jason */	      /* A char, short, wchar_t, etc., should promote to an int if		 it can handle it, otherwise to an unsigned.  So we'll make		 an unsigned.  */	      if (type != integer_type_node)		h.int_penalty = 1;#endif	    }	  else	    h.code = STD_CODE;	    	  return h;	}      else if (coder == REAL_TYPE)	{	  h.code = STD_CODE;	  h.distance = 0;	  return h;	}    }

⌨️ 快捷键说明

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