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

📄 cp-cvt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
   For example, if adding two longs and converting to an int,   we can equally well convert both to ints and then add.   For the operations handled here, such truncation distribution   is always safe.   It is desirable in these cases:   1) when truncating down to full-word from a larger size   2) when truncating takes no work.   3) when at least one operand of the arithmetic has been extended   (as by C's default conversions).  In this case we need two conversions   if we do the arithmetic as already requested, so we might as well   truncate both and then combine.  Perhaps that way we need only one.   Note that in general we cannot do the arithmetic in a type   shorter than the desired result of conversion, even if the operands   are both extended from a shorter type, because they might overflow   if combined in that type.  The exceptions to this--the times when   two narrow values can be combined in their narrow type even to   make a wider result--are handled by "shorten" in build_binary_op.  */      switch (ex_form)	{	case RSHIFT_EXPR:	  /* We can pass truncation down through right shifting	     when the shift count is a nonpositive constant.  */	  if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST	      && tree_int_cst_lt (TREE_OPERAND (expr, 1), integer_one_node))	    goto trunc1;	  break;	case LSHIFT_EXPR:	  /* We can pass truncation down through left shifting	     when the shift count is a nonnegative constant.  */	  if (TREE_CODE (TREE_OPERAND (expr, 1)) == INTEGER_CST	      && ! tree_int_cst_lt (TREE_OPERAND (expr, 1), integer_zero_node)	      && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST)	    {	      /* If shift count is less than the width of the truncated type,		 really shift.  */	      if (tree_int_cst_lt (TREE_OPERAND (expr, 1), TYPE_SIZE (type)))		/* In this case, shifting is like multiplication.  */		goto trunc1;	      else		/* If it is >= that width, result is zero.		   Handling this with trunc1 would give the wrong result:		   (int) ((long long) a << 32) is well defined (as 0)		   but (int) a << 32 is undefined and would get a warning.  */		return convert_to_integer (type, integer_zero_node);	    }	  break;	case MAX_EXPR:	case MIN_EXPR:	case MULT_EXPR:	  {	    tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);	    tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);	    /* Don't distribute unless the output precision is at least as big	       as the actual inputs.  Otherwise, the comparison of the	       truncated values will be wrong.  */	    if (outprec >= TYPE_PRECISION (TREE_TYPE (arg0))		&& outprec >= TYPE_PRECISION (TREE_TYPE (arg1))		/* If signedness of arg0 and arg1 don't match,		   we can't necessarily find a type to compare them in.  */		&& (TREE_UNSIGNED (TREE_TYPE (arg0))		    == TREE_UNSIGNED (TREE_TYPE (arg1))))	      goto trunc1;	    break;	  }	case PLUS_EXPR:	case MINUS_EXPR:	case BIT_AND_EXPR:	case BIT_IOR_EXPR:	case BIT_XOR_EXPR:	case BIT_ANDTC_EXPR:	trunc1:	  {	    tree arg0 = get_unwidened (TREE_OPERAND (expr, 0), type);	    tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);	    if (outprec >= BITS_PER_WORD		|| TRULY_NOOP_TRUNCATION (outprec, inprec)		|| inprec > TYPE_PRECISION (TREE_TYPE (arg0))		|| inprec > TYPE_PRECISION (TREE_TYPE (arg1)))	      {		/* Do the arithmetic in type TYPEX,		   then convert result to TYPE.  */		register tree typex = type;		/* Can't do arithmetic in enumeral types		   so use an integer type that will hold the values.  */		if (TREE_CODE (typex) == ENUMERAL_TYPE)		  typex = type_for_size (TYPE_PRECISION (typex),					 TREE_UNSIGNED (typex));		/* But now perhaps TYPEX is as wide as INPREC.		   In that case, do nothing special here.		   (Otherwise would recurse infinitely in convert.  */		if (TYPE_PRECISION (typex) != inprec)		  {		    /* Don't do unsigned arithmetic where signed was wanted,		       or vice versa.		       Exception 1: if we will eventually truncate		       the result, then do the work as unsigned;		       this can prevent unnecessary sign-extension.		       Exception 2: if either of the original operands were		       unsigned then can safely do the work as unsigned.		       And we may need to do it as unsigned		       if we truncate to the original size.  */		    typex = (((outprec <= TYPE_PRECISION (typex)			       && TREE_UNSIGNED (type))			      || TREE_UNSIGNED (TREE_TYPE (expr))			      || TREE_UNSIGNED (TREE_TYPE (arg0))			      || TREE_UNSIGNED (TREE_TYPE (arg1)))			     ? unsigned_type (typex) : signed_type (typex));		    return convert (type,				    build_binary_op_nodefault (ex_form,							       convert (typex, arg0),							       convert (typex, arg1),							       ex_form));		  }	      }	  }	  break;	case NEGATE_EXPR:	case BIT_NOT_EXPR:	case ABS_EXPR:	  {	    register tree typex = type;	    /* Can't do arithmetic in enumeral types	       so use an integer type that will hold the values.  */	    if (TREE_CODE (typex) == ENUMERAL_TYPE)	      typex = type_for_size (TYPE_PRECISION (typex),				     TREE_UNSIGNED (typex));	    /* But now perhaps TYPEX is as wide as INPREC.	       In that case, do nothing special here.	       (Otherwise would recurse infinitely in convert.  */	    if (TYPE_PRECISION (typex) != inprec)	      {		/* Don't do unsigned arithmetic where signed was wanted,		   or vice versa.  */		typex = (((outprec <= TYPE_PRECISION (typex)			   && TREE_UNSIGNED (type))			  || TREE_UNSIGNED (TREE_TYPE (expr)))			 ? unsigned_type (typex) : signed_type (typex));		return convert (type,				build_unary_op (ex_form,						convert (typex, TREE_OPERAND (expr, 0)),						1));	      }	  }	case NOP_EXPR:	  /* If truncating after truncating, might as well do all at once.	     If truncating after extending, we may get rid of wasted work.  */	  return convert (type, get_unwidened (TREE_OPERAND (expr, 0), type));	case COND_EXPR:	  /* Can treat the two alternative values like the operands	     of an arithmetic expression.  */	  {	    tree arg1 = get_unwidened (TREE_OPERAND (expr, 1), type);	    tree arg2 = get_unwidened (TREE_OPERAND (expr, 2), type);	    if (outprec >= BITS_PER_WORD		|| TRULY_NOOP_TRUNCATION (outprec, inprec)		|| inprec > TYPE_PRECISION (TREE_TYPE (arg1))		|| inprec > TYPE_PRECISION (TREE_TYPE (arg2)))	      {		/* Do the arithmetic in type TYPEX,		   then convert result to TYPE.  */		register tree typex = type;		/* Can't do arithmetic in enumeral types		   so use an integer type that will hold the values.  */		if (TREE_CODE (typex) == ENUMERAL_TYPE)		  typex = type_for_size (TYPE_PRECISION (typex),					 TREE_UNSIGNED (typex));		/* But now perhaps TYPEX is as wide as INPREC.		   In that case, do nothing special here.		   (Otherwise would recurse infinitely in convert.  */		if (TYPE_PRECISION (typex) != inprec)		  {		    /* Don't do unsigned arithmetic where signed was wanted,		       or vice versa.  */		    typex = (((outprec <= TYPE_PRECISION (typex)			       && TREE_UNSIGNED (type))			      || TREE_UNSIGNED (TREE_TYPE (expr)))			     ? unsigned_type (typex) : signed_type (typex));		    return convert (type,				    fold (build (COND_EXPR, typex,						 TREE_OPERAND (expr, 0),						 convert (typex, arg1),						 convert (typex, arg2))));		  }		else		  /* It is sometimes worthwhile		     to push the narrowing down through the conditional.  */		  return fold (build (COND_EXPR, type,				      TREE_OPERAND (expr, 0),				      convert (type, TREE_OPERAND (expr, 1)), 				      convert (type, TREE_OPERAND (expr, 2))));	      }	  }	}      return build1 (NOP_EXPR, type, expr);    }  if (form == REAL_TYPE)    return build1 (FIX_TRUNC_EXPR, type, expr);  if (form == OFFSET_TYPE)    error_with_decl (TYPE_NAME (TYPE_OFFSET_BASETYPE (intype)),		     "pointer-to-member expression object not composed with type `%s' object");  else    {      if (IS_AGGR_TYPE (intype))	{	  tree rval;	  rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);	  if (rval) return rval;	}      error ("aggregate value used where an integer was expected");    }  {    register tree tem = build_int_2 (0, 0);    TREE_TYPE (tem) = type;    return tem;  }}/* See if there is a constructor of type TYPE which will convert   EXPR.  The reference manual seems to suggest (8.5.6) that we need   not worry about finding constructors for base classes, then converting   to the derived class.   MSGP is a pointer to a message that would be an appropriate error   string.  If MSGP is NULL, then we are not interested in reporting   errors.  */treeconvert_to_aggr (type, expr, msgp, protect)     tree type, expr;     char **msgp;     int protect;{  tree basetype = type;  tree name = TYPE_IDENTIFIER (basetype);  tree function, fndecl, fntype, parmtypes, parmlist, result;  tree method_name;  enum visibility_type visibility;  int can_be_private, can_be_protected;  if (! TYPE_HAS_CONSTRUCTOR (basetype))    {      if (msgp)	*msgp = "type `%s' does not have a constructor";      return error_mark_node;    }  visibility = visibility_public;  can_be_private = 0;  can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;  parmlist = build_tree_list (NULL_TREE, expr);  parmtypes = tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);  if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))    {      parmtypes = tree_cons (NULL_TREE, integer_type_node, parmtypes);      parmlist = tree_cons (NULL_TREE, integer_one_node, parmlist);    }  /* The type of the first argument will be filled in inside the loop.  */  parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);  parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);  method_name = build_decl_overload (name, parmtypes, 1);  /* constructors are up front.  */  fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);  if (TYPE_HAS_DESTRUCTOR (basetype))    fndecl = DECL_CHAIN (fndecl);  while (fndecl)    {      if (DECL_ASSEMBLER_NAME (fndecl) == method_name)	{	  function = fndecl;	  if (protect)	    {	      if (TREE_PRIVATE (fndecl))		{		  can_be_private =		    (basetype == current_class_type		     || is_friend (basetype, current_function_decl)		     || purpose_member (basetype, DECL_VISIBILITY (fndecl)));		  if (! can_be_private)		    goto found;		}	      else if (TREE_PROTECTED (fndecl))		{		  if (! can_be_protected)		    goto found;		}	    }	  goto found_and_ok;	}      fndecl = DECL_CHAIN (fndecl);    }  /* No exact conversion was found.  See if an approximate     one will do.  */  fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);  if (TYPE_HAS_DESTRUCTOR (basetype))    fndecl = DECL_CHAIN (fndecl);  {    int saw_private = 0;    int saw_protected = 0;    struct candidate *candidates =      (struct candidate *) alloca ((decl_list_length (fndecl)+1) * sizeof (struct candidate));    struct candidate *cp = candidates;    while (fndecl)      {	function = fndecl;	cp->harshness = (unsigned short *)alloca (3 * sizeof (short));	compute_conversion_costs (fndecl, parmlist, cp, 2);	if (cp->evil == 0)	  {	    cp->u.field = fndecl;	    if (protect)	      {		if (TREE_PRIVATE (fndecl))		  visibility = visibility_private;		else if (TREE_PROTECTED (fndecl))		  visibility = visibility_protected;		else		  visibility = visibility_public;	      }	    else	      visibility = visibility_public;	    if (visibility == visibility_private		? (basetype == current_class_type		   || is_friend (basetype, cp->function)		   || purpose_member (basetype, DECL_VISIBILITY (fndecl)))		: visibility == visibility_protected		? (can_be_protected		   || purpose_member (basetype, DECL_VISIBILITY (fndecl)))		: 1)	      {		if (cp->user == 0 && cp->b_or_d == 0		    && cp->easy <= 1)		  {		    goto found_and_ok;		  }		cp++;	      }	    else	      {		if (visibility == visibility_private)		  saw_private = 1;		else		  saw_protected = 1;	      }	  }	fndecl = DECL_CHAIN (fndecl);      }    if (cp - candidates)      {	/* Rank from worst to best.  Then cp will point to best one.	   Private fields have their bits flipped.  For unsigned	   numbers, this should make them look very large.	   If the best alternate has a (signed) negative value,	   then all we ever saw were private members.  */	if (cp - candidates > 1)	  qsort (candidates,	/* char *base */		 cp - candidates, /* int nel */		 sizeof (struct candidate), /* int width */		 rank_for_overload); /* int (*compar)() */	--cp;	if (cp->evil > 1)	  {	    if (msgp)	      *msgp = "ambiguous type conversion possible for `%s'";	    return error_mark_node;	  }	function = cp->function;	fndecl = cp->u.field;	goto found_and_ok;      }    else if (msgp)      {	if (saw_private)	  if (saw_protected)	    *msgp = "only private and protected conversions apply";	  else	    *msgp = "only private conversions apply";	else if (saw_protected)	  *msgp = "only protected conversions apply";      }    return error_mark_node;  }  /* NOTREACHED */ not_found:  if (msgp) *msgp = "no appropriate conversion to type `%s'";  return error_mark_node; found:  if (visibility == visibility_private)

⌨️ 快捷键说明

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