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

📄 cp-call.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Functions related to invoking methods and overloaded functions.   Copyright (C) 1987, 1992 Free Software Foundation, Inc.   Contributed by Michael Tiemann (tiemann@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, 675 Mass Ave, Cambridge, MA 02139, USA.  *//* High-level class interface. */#include "config.h"#include "tree.h"#include <stdio.h>#include "cp-tree.h"#include "flags.h"#include "cp-class.h"#include "obstack.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern void sorry ();extern tree build_function_call_maybe ();extern int inhibit_warnings;extern int flag_assume_nonnull_objects;extern tree ctor_label, dtor_label;/* From cp-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 int convert_harshness ();#define EVIL_HARSHNESS(ARG) ((ARG) & 1)#define USER_HARSHNESS(ARG) ((ARG) & 2)#define CONTRAVARIANT_HARSHNESS(ARG) ((ARG) & 4)#define BASE_DERIVED_HARSHNESS(ARG) ((ARG) & 8)#define INT_TO_BD_HARSHNESS(ARG) (((ARG) << 4) | 8)#define INT_FROM_BD_HARSHNESS(ARG) ((ARG) >> 4)#define INT_TO_EASY_HARSHNESS(ARG) ((ARG) << 4)#define INT_FROM_EASY_HARSHNESS(ARG) ((ARG) >> 4)#define ONLY_EASY_HARSHNESS(ARG) (((ARG) & 15) == 0)#define CONST_HARSHNESS(ARG) ((ARG) & 1024)/* Ordering function for overload resolution.  */intrank_for_overload (x, y)     struct candidate *x, *y;{  if (y->evil - x->evil)    return y->evil - x->evil;  if (CONST_HARSHNESS (y->harshness[0]) ^ CONST_HARSHNESS (x->harshness[0]))    return y->harshness[0] - x->harshness[0];  if (y->user - x->user)    return y->user - x->user;  if (y->b_or_d - x->b_or_d)    return y->b_or_d - x->b_or_d;  return y->easy - x->easy;}/* 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 intconvert_harshness (type, parmtype, parm)     register tree type, parmtype;     tree parm;{  register enum tree_code codel = TREE_CODE (type);  register enum tree_code coder = TREE_CODE (parmtype);#ifdef GATHER_STATISTICS  n_convert_harshness++;#endif  if (TYPE_MAIN_VARIANT (parmtype) == TYPE_MAIN_VARIANT (type))    return 0;  if (coder == ERROR_MARK)    return 1;  if (codel == POINTER_TYPE      && (coder == METHOD_TYPE || coder == FUNCTION_TYPE))    {      tree p1, p2;      int harshness, new_harshness;      /* Get to the METHOD_TYPE or FUNCTION_TYPE that this might be.  */      type = TREE_TYPE (type);      if (coder != TREE_CODE (type))	return 1;      harshness = 0;      /* We allow the default conversion between function type	 and pointer-to-function type for free.  */      if (type == parmtype)	return 0;      /* Compare return types.  */      p1 = TREE_TYPE (type);      p2 = TREE_TYPE (parmtype);      new_harshness = convert_harshness (p1, p2, 0);      if (new_harshness & 1)	return 1;      if (BASE_DERIVED_HARSHNESS (new_harshness))	{	  tree binfo;	  /* This only works for pointers.  */	  if (TREE_CODE (p1) != POINTER_TYPE	      && TREE_CODE (p1) != REFERENCE_TYPE)	    return 1;	  p1 = TREE_TYPE (p1);	  p2 = TREE_TYPE (p2);	  if (CONTRAVARIANT_HARSHNESS (new_harshness))	    binfo = get_binfo (p2, p1, 0);	  else	    binfo = get_binfo (p1, p2, 0);	  if (! BINFO_OFFSET_ZEROP (binfo))	    {	      static int explained;	      if (CONTRAVARIANT_HARSHNESS (new_harshness))		message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p2, p1);	      else		message_2_types (sorry, "cannot cast `%d' to `%d' at function call site", p1, p2);	      if (! explained++)		sorry ("(because pointer values change during conversion)");	      return 1;	    }	}      harshness |= new_harshness;      p1 = TYPE_ARG_TYPES (type);      p2 = TYPE_ARG_TYPES (parmtype);      while (p1 && p2)	{	  new_harshness = convert_harshness (TREE_VALUE (p1), TREE_VALUE (p2), 0);	  if (EVIL_HARSHNESS (new_harshness))	    return 1;	  if (BASE_DERIVED_HARSHNESS (new_harshness))	    {	      /* This only works for pointers and references. */	      if (TREE_CODE (TREE_VALUE (p1)) != POINTER_TYPE		  && TREE_CODE (TREE_VALUE (p1)) != REFERENCE_TYPE)		return 1;	      new_harshness ^= CONTRAVARIANT_HARSHNESS (new_harshness);	      harshness |= new_harshness;	    }	  /* This trick allows use to accumulate easy type	     conversions without messing up the bits that encode	     info about more involved things.  */	  else if (ONLY_EASY_HARSHNESS (new_harshness))	    harshness += new_harshness;	  else	    harshness |= new_harshness;	  p1 = TREE_CHAIN (p1);	  p2 = TREE_CHAIN (p2);	}      if (p1 == p2)	return harshness;      if (p2)	return 1;      if (p1)	return harshness | (TREE_PURPOSE (p1) == NULL_TREE);    }  else if (codel == POINTER_TYPE && coder == OFFSET_TYPE)    {      int harshness;      /* Get to the OFFSET_TYPE that this might be.  */      type = TREE_TYPE (type);      if (coder != TREE_CODE (type))	return 1;      harshness = 0;      if (TYPE_OFFSET_BASETYPE (type) == TYPE_OFFSET_BASETYPE (parmtype))	harshness = 0;      else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (type),			       TYPE_OFFSET_BASETYPE (parmtype)))	harshness = INT_TO_BD_HARSHNESS (1);      else if (UNIQUELY_DERIVED_FROM_P (TYPE_OFFSET_BASETYPE (parmtype),			       TYPE_OFFSET_BASETYPE (type)))	harshness = CONTRAVARIANT_HARSHNESS (-1);      else	return 1;      /* 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 0;      return 1;    }  if (coder == VOID_TYPE)    return 1;  if (codel == ENUMERAL_TYPE || codel == INTEGER_TYPE)    {      /* 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 1;	}      /* else enums and ints (almost) freely interconvert.  */      if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)	{	  int easy = TREE_UNSIGNED (type) ^ TREE_UNSIGNED (parmtype);	  if (codel != coder)	    easy += 1;	  if (TYPE_MODE (type) != TYPE_MODE (parmtype))	    easy += 2;	  return INT_TO_EASY_HARSHNESS (easy);	}      else if (coder == REAL_TYPE)	return INT_TO_EASY_HARSHNESS (4);    }  if (codel == REAL_TYPE)    if (coder == REAL_TYPE)      /* Shun converting between float and double if a choice exists.  */      {	if (TYPE_MODE (type) != TYPE_MODE (parmtype))	  return INT_TO_EASY_HARSHNESS (2);	return 0;      }    else if (coder == INTEGER_TYPE || coder == ENUMERAL_TYPE)      return INT_TO_EASY_HARSHNESS (4);  /* convert arrays which have not previously been converted.  */  if (codel == ARRAY_TYPE)    codel = POINTER_TYPE;  if (coder == ARRAY_TYPE)    coder = POINTER_TYPE;  /* Conversions among pointers */  if (codel == POINTER_TYPE && coder == POINTER_TYPE)    {      register tree ttl = TYPE_MAIN_VARIANT (TREE_TYPE (type));      register tree ttr = TYPE_MAIN_VARIANT (TREE_TYPE (parmtype));      int penalty = 4 * (ttl != ttr);      /* Anything converts to void *.  void * converts to anything.	 Since these may be `const void *' (etc.) use VOID_TYPE	 instead of void_type_node.	 Otherwise, the targets must be the same,	 except that we do allow (at some cost) conversion	 between signed and unsinged pointer types.  */      if ((TREE_CODE (ttl) == METHOD_TYPE	   || TREE_CODE (ttl) == FUNCTION_TYPE)	  && TREE_CODE (ttl) == TREE_CODE (ttr))	{	  if (comptypes (ttl, ttr, -1))	    return INT_TO_EASY_HARSHNESS (penalty);	  return 1;	}      if (!(TREE_CODE (ttl) == VOID_TYPE	    || TREE_CODE (ttr) == VOID_TYPE	    || (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (ttr)		&& (ttl = unsigned_type (ttl),		    ttr = unsigned_type (ttr),		    penalty = 10, 0))	    || (comp_target_types (ttl, ttr, 0))))	return 1;      if (penalty == 10)	return INT_TO_EASY_HARSHNESS (10);      if (ttr == ttl)	return INT_TO_BD_HARSHNESS (0);      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);	    }	  return INT_TO_BD_HARSHNESS (b_or_d);	}      /* If converting from a `class*' to a `void*', make it	 less favorable than any inheritance relationship.  */      if (TREE_CODE (ttl) == VOID_TYPE && IS_AGGR_TYPE (ttr))	return INT_TO_BD_HARSHNESS (CLASSTYPE_MAX_DEPTH (ttr)+1);      return INT_TO_EASY_HARSHNESS (penalty);    }  if (codel == POINTER_TYPE && coder == INTEGER_TYPE)    {      /* This is not a bad match, but don't let it beat	 integer-enum combinations.  */      if (parm && integer_zerop (parm))	return INT_TO_EASY_HARSHNESS (4);    }  /* C++: one of the types must be a reference type.  */  {    tree ttl, ttr;    register tree intype = TYPE_MAIN_VARIANT (parmtype);    register enum tree_code form = TREE_CODE (intype);    int penalty;    if (codel == REFERENCE_TYPE || coder == REFERENCE_TYPE)      {	ttl = TYPE_MAIN_VARIANT (type);	if (codel == REFERENCE_TYPE)	  {	    ttl = TREE_TYPE (ttl);	    /* When passing a non-const argument into a const reference,	       dig it a little, so a non-const reference is preferred over	       this one. (mrs) */	    if (TREE_READONLY (ttl) && ! TREE_READONLY (parm))	      penalty = 2;	    else	      penalty = 0;	    ttl = TYPE_MAIN_VARIANT (ttl);	    if (form == OFFSET_TYPE)	      {		intype = TREE_TYPE (intype);		form = TREE_CODE (intype);	      }	    if (form == REFERENCE_TYPE)	      {		intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));		if (ttl == intype)		  return 0;		penalty = 2;	      }	    else	      {		/* Can reference be built up?  */		if (ttl == intype && penalty == 0) {		  /* Becuase the READONLY bits are not always in the type,		     this extra check is necessary.  The problem should		     be fixed someplace else, and this extra code removed.		     Also, if type if a reference, the readonly bits could		     either be in the outer type (with reference) or on the		     inner type (the thing being referenced).  (mrs)  */		  if (TREE_READONLY (parm)		      && ! (TYPE_READONLY (type)			    || (TREE_CODE (type) == REFERENCE_TYPE				&& TYPE_READONLY (TREE_TYPE (type)))))		    penalty = 2;		  else		    return 0;		}		else		  penalty = 2;	      }	  }	else if (form == REFERENCE_TYPE)	  {	    if (parm)	      {		tree tmp = convert_from_reference (parm);		intype = TYPE_MAIN_VARIANT (TREE_TYPE (tmp));	      }	    else	      {		intype = parmtype;		do		  {		    intype = TREE_TYPE (intype);		  }		while (TREE_CODE (intype) == REFERENCE_TYPE);		intype = TYPE_MAIN_VARIANT (intype);	      }	    if (ttl == intype)	      return 0;	    else	      penalty = 2;	  }	if (TREE_UNSIGNED (ttl) ^ TREE_UNSIGNED (intype))	  {	    ttl = unsigned_type (ttl);	    intype = unsigned_type (intype);	    penalty += 2;	  }	ttr = intype;	/* If the initializer is not an lvalue, then it does not

⌨️ 快捷键说明

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