cvt.c

来自「GCC编译器源代码」· C语言 代码 · 共 1,673 行 · 第 1/4 页

C
1,673
字号
     address, transform all occurrences of the register, into a memory     reference we could win better.  */  rval = build_unary_op (ADDR_EXPR, arg, 1);  if ((flags & LOOKUP_PROTECT)      && TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)      && IS_AGGR_TYPE (argtype)      && IS_AGGR_TYPE (target_type))    {      /* We go through get_binfo for the access control.  */      tree binfo = get_binfo (target_type, argtype, 1);      if (binfo == error_mark_node)	return error_mark_node;      if (binfo == NULL_TREE)	return error_not_base_type (target_type, argtype);      rval = convert_pointer_to_real (binfo, rval);    }  else    rval      = convert_to_pointer_force (build_pointer_type (target_type), rval);  rval = build1 (NOP_EXPR, type, rval);  TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));  return rval;}/* For C++: Only need to do one-level references, but cannot   get tripped up on signed/unsigned differences.   DECL is either NULL_TREE or the _DECL node for a reference that is being   initialized.  It can be error_mark_node if we don't know the _DECL but   we know it's an initialization.  */treeconvert_to_reference (reftype, expr, convtype, flags, decl)     tree reftype, expr;     int convtype, flags;     tree decl;{  register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));  register tree intype = TREE_TYPE (expr);  tree rval = NULL_TREE;  tree rval_as_conversion = NULL_TREE;  int i;  if (TREE_CODE (intype) == REFERENCE_TYPE)    my_friendly_abort (364);  intype = TYPE_MAIN_VARIANT (intype);  i = comp_target_types (type, intype, 0);  if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)      && ! (flags & LOOKUP_NO_CONVERSION))    {      /* Look for a user-defined conversion to lvalue that we can use.  */      if (flag_ansi_overloading)	rval_as_conversion	  = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);      else	rval_as_conversion = build_type_conversion (CONVERT_EXPR, type, expr, 1);      if (rval_as_conversion && rval_as_conversion != error_mark_node	  && real_lvalue_p (rval_as_conversion))	{	  expr = rval_as_conversion;	  rval_as_conversion = NULL_TREE;	  intype = type;	  i = 1;	}    }  if (((convtype & CONV_STATIC) && i == -1)      || ((convtype & CONV_IMPLICIT) && i == 1))    {      if (flags & LOOKUP_COMPLAIN)	{	  tree ttl = TREE_TYPE (reftype);	  tree ttr;	  	  {	    int r = TREE_READONLY (expr);	    int v = TREE_THIS_VOLATILE (expr);	    ttr = cp_build_type_variant (TREE_TYPE (expr), r, v);	  }	  if (! real_lvalue_p (expr) && ! TYPE_READONLY (ttl))	    {	      if (decl)		/* Ensure semantics of [dcl.init.ref] */		cp_pedwarn ("initialization of non-const reference `%#T' from rvalue `%T'",			    reftype, intype);	      else		cp_pedwarn ("conversion to non-const `%T' from rvalue `%T'",			    reftype, intype);	    }	  else if (! (convtype & CONV_CONST))	    {	      if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))		cp_pedwarn ("conversion from `%T' to `%T' discards const",			    ttr, reftype);	      else if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))		cp_pedwarn ("conversion from `%T' to `%T' discards volatile",			    ttr, reftype);	    }	}      return build_up_reference (reftype, expr, flags,				 ! (convtype & CONV_CONST));    }  else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))    {      /* When casting an lvalue to a reference type, just convert into	 a pointer to the new type and deference it.  This is allowed	 by San Diego WP section 5.2.9 paragraph 12, though perhaps it	 should be done directly (jason).  (int &)ri ---> *(int*)&ri */      /* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they         meant.  */      if (TREE_CODE (intype) == POINTER_TYPE	  && (comptypes (TREE_TYPE (intype), type, -1)))	cp_warning ("casting `%T' to `%T' does not dereference pointer",		    intype, reftype);	        rval = build_unary_op (ADDR_EXPR, expr, 0);      if (rval != error_mark_node)	rval = convert_force (build_pointer_type (TREE_TYPE (reftype)), rval, 0);      if (rval != error_mark_node)	rval = build1 (NOP_EXPR, reftype, rval);    }  else if (flag_ansi_overloading)    {      rval = convert_for_initialization (NULL_TREE, type, expr, flags,					 "converting", 0, 0);      if (rval == error_mark_node)	return error_mark_node;      rval = build_up_reference (reftype, rval, flags, 1);      if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))	cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",		    reftype, intype);    }  else    {      tree rval_as_ctor = NULL_TREE;            if (rval_as_conversion)	{	  if (rval_as_conversion == error_mark_node)	    {	      cp_error ("conversion from `%T' to `%T' is ambiguous",			intype, reftype);	      return error_mark_node;	    }	  rval_as_conversion = build_up_reference (reftype, rval_as_conversion,						   flags, 1);	}            /* Definitely need to go through a constructor here.  */      if (TYPE_HAS_CONSTRUCTOR (type)	  && ! CLASSTYPE_ABSTRACT_VIRTUALS (type)	  && (rval = build_method_call	      (NULL_TREE, ctor_identifier,	       build_expr_list (NULL_TREE, expr), TYPE_BINFO (type),	       LOOKUP_NO_CONVERSION|LOOKUP_SPECULATIVELY	       | LOOKUP_ONLYCONVERTING)))	{	  tree init;	  if (toplevel_bindings_p ())	    {	      tree t = get_temp_name (type, toplevel_bindings_p ());	      init = build_method_call (t, ctor_identifier,					build_expr_list (NULL_TREE, expr),					TYPE_BINFO (type),					LOOKUP_NORMAL|LOOKUP_NO_CONVERSION					| LOOKUP_ONLYCONVERTING);	      if (init == error_mark_node)		return error_mark_node;	      make_decl_rtl (t, NULL_PTR, 1);	      static_aggregates = perm_tree_cons (expr, t, static_aggregates);	      rval = build_unary_op (ADDR_EXPR, t, 0);	    }	  else	    {	      init = build_method_call (NULL_TREE, ctor_identifier,					build_expr_list (NULL_TREE, expr),					TYPE_BINFO (type),					LOOKUP_NORMAL|LOOKUP_NO_CONVERSION					|LOOKUP_ONLYCONVERTING);	      if (init == error_mark_node)		return error_mark_node;	      rval = build_cplus_new (type, init);	      rval = build_up_reference (reftype, rval, flags, 1);	    }	  rval_as_ctor = rval;	}      if (rval_as_ctor && rval_as_conversion)	{	  cp_error ("ambiguous conversion from `%T' to `%T'; both user-defined conversion and constructor apply",		    intype, reftype);	  return error_mark_node;	}      else if (rval_as_ctor)	rval = rval_as_ctor;      else if (rval_as_conversion)	rval = rval_as_conversion;      else if (! IS_AGGR_TYPE (type) && ! IS_AGGR_TYPE (intype))	{	  rval = cp_convert (type, expr);	  if (rval == error_mark_node)	    return error_mark_node;	  	  rval = build_up_reference (reftype, rval, flags, 1);	}      if (rval && ! TYPE_READONLY (TREE_TYPE (reftype)))	cp_pedwarn ("initializing non-const `%T' with `%T' will use a temporary",		    reftype, intype);    }  if (rval)    {      /* If we found a way to convert earlier, then use it.  */      return rval;    }  my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);  if (flags & LOOKUP_COMPLAIN)    cp_error ("cannot convert type `%T' to type `%T'", intype, reftype);  if (flags & LOOKUP_SPECULATIVELY)    return NULL_TREE;  return error_mark_node;}/* We are using a reference VAL for its value. Bash that reference all the   way down to its lowest form.  */treeconvert_from_reference (val)     tree val;{  tree type = TREE_TYPE (val);  if (TREE_CODE (type) == OFFSET_TYPE)    type = TREE_TYPE (type);  if (TREE_CODE (type) == REFERENCE_TYPE)    return build_indirect_ref (val, NULL_PTR);  return val;}/* 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;#if 0  /* See code below that used this.  */  tree method_name;#endif  tree access;  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;    }  access = access_public_node;  can_be_private = 0;  can_be_protected = IDENTIFIER_CLASS_VALUE (name) || name == current_class_name;  parmlist = build_expr_list (NULL_TREE, expr);  parmtypes = scratch_tree_cons (NULL_TREE, TREE_TYPE (expr), void_list_node);  if (TYPE_USES_VIRTUAL_BASECLASSES (basetype))    {      parmtypes = expr_tree_cons (NULL_TREE, integer_type_node, parmtypes);      parmlist = scratch_tree_cons (NULL_TREE, integer_one_node, parmlist);    }  /* The type of the first argument will be filled in inside the loop.  */  parmlist = expr_tree_cons (NULL_TREE, integer_zero_node, parmlist);  parmtypes = scratch_tree_cons (NULL_TREE, build_pointer_type (basetype), parmtypes);  /* No exact conversion was found.  See if an approximate     one will do.  */  fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0);  {    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->h_len = 2;	cp->harshness = (struct harshness_code *)	  alloca (3 * sizeof (struct harshness_code));	compute_conversion_costs (fndecl, parmlist, cp, 2);	if ((cp->h.code & EVIL_CODE) == 0)	  {	    cp->u.field = fndecl;	    if (protect)	      {		if (TREE_PRIVATE (fndecl))		  access = access_private_node;		else if (TREE_PROTECTED (fndecl))		  access = access_protected_node;		else		  access = access_public_node;	      }	    else	      access = access_public_node;	    if (access == access_private_node		? (basetype == current_class_type		   || is_friend (basetype, cp->function)		   || purpose_member (basetype, DECL_ACCESS (fndecl)))		: access == access_protected_node		? (can_be_protected		   || purpose_member (basetype, DECL_ACCESS (fndecl)))		: 1)	      {		if (cp->h.code <= TRIVIAL_CODE)		  goto found_and_ok;		cp++;	      }	    else	      {		if (access == access_private_node)		  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 */		 (int (*) PROTO((const void *, const void *))) rank_for_overload); /* int (*compar)() */	--cp;	if (cp->h.code & EVIL_CODE)	  {	    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";	else	  *msgp = "no appropriate conversion to type `%s'";      }    return error_mark_node;  }  /* NOTREACHED */ found:  if (access == access_private_node)    if (! can_be_private)      {	if (msgp)	  *msgp = TREE_PRIVATE (fndecl)	    ? "conversion to type `%s' is private"	    : "conversion to type `%s' is from private base class";	return error_mark_node;      }  if (access == access_protected_node)    if (! can_be_protected)      {	if (msgp)

⌨️ 快捷键说明

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