FreeBSD/contrib/gcc/cp/cvt.c
/* 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.  */
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.
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 .
tree
convert_to_reference (tree reftype, tree expr, int convtype,
		      int flags, tree decl)
{
  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
  tree intype;
  tree rval = NULL_TREE;
  tree rval_as_conversion = NULL_TREE;
  bool can_convert_intype_to_type;
  if (TREE_CODE (type) == FUNCTION_TYPE
      && TREE_TYPE (expr) == unknown_type_node)
    expr = instantiate_type (type, expr,
			     (flags & LOOKUP_COMPLAIN)
			     ? tf_warning_or_error : tf_none);
  if (expr == error_mark_node)
    return error_mark_node;
  intype = TREE_TYPE (expr);
  gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE);
  gcc_assert (TREE_CODE (reftype) == REFERENCE_TYPE);
  intype = TYPE_MAIN_VARIANT (intype);
  can_convert_intype_to_type = can_convert (type, intype);
  if (!can_convert_intype_to_type
      && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
      && ! (flags & LOOKUP_NO_CONVERSION))
    {
      rval_as_conversion
	= build_type_conversion (reftype, expr);
      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;
	  can_convert_intype_to_type = 1;
	}
    }
  if (((convtype & CONV_STATIC) && can_convert (intype, type))
      || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
    {
      if (flags & LOOKUP_COMPLAIN)
	{
	  tree ttl = TREE_TYPE (reftype);
	  tree ttr = lvalue_type (expr);
	  if (! real_lvalue_p (expr))
	    warn_ref_binding (reftype, intype, decl);
	  if (! (convtype & CONV_CONST)
		   && !at_least_as_qualified_p (ttl, ttr))
	    pedwarn ("conversion from %qT to %qT discards qualifiers",
		     ttr, reftype);
	}
      return build_up_reference (reftype, expr, flags, decl);
    }
  else if ((convtype & CONV_REINTERPRET) && lvalue_p (expr))
    {
      if (TREE_CODE (intype) == POINTER_TYPE
	  && (comptypes (TREE_TYPE (intype), type,
			 COMPARE_BASE | COMPARE_DERIVED)))
	warning (0, "casting %qT to %qT 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
    {
      rval = convert_for_initialization (NULL_TREE, type, expr, flags,
					 "converting", 0, 0);
      if (rval == NULL_TREE || rval == error_mark_node)
	return rval;
      warn_ref_binding (reftype, intype, decl);
      rval = build_up_reference (reftype, rval, flags, decl);
    }
  if (rval)
    {
      return rval;
    }
  if (flags & LOOKUP_COMPLAIN)
    error ("cannot convert type %qT to type %qT", intype, reftype);
  return error_mark_node;
}
tree convert_to_reference ( tree reftype , tree expr , int convtype , int flags , tree decl ) { tree type = TYPE_MAIN_VARIANT ( TREE_TYPE ( reftype ) ) ; tree intype ; tree rval = NULL_TREE ; tree rval_as_conversion = NULL_TREE ; bool can_convert_intype_to_type ; if ( TREE_CODE ( type ) == FUNCTION_TYPE && TREE_TYPE ( expr ) == unknown_type_node ) expr = instantiate_type ( type , expr , ( flags & LOOKUP_COMPLAIN ) ? tf_warning_or_error : tf_none ) ; if ( expr == error_mark_node ) return error_mark_node ; intype = TREE_TYPE ( expr ) ; gcc_assert ( TREE_CODE ( intype ) != REFERENCE_TYPE ) ; gcc_assert ( TREE_CODE ( reftype ) == REFERENCE_TYPE ) ; intype = TYPE_MAIN_VARIANT ( intype ) ; can_convert_intype_to_type = can_convert ( type , intype ) ; if ( ! can_convert_intype_to_type && ( convtype & CONV_IMPLICIT ) && IS_AGGR_TYPE ( intype ) && ! ( flags & LOOKUP_NO_CONVERSION ) ) { rval_as_conversion = build_type_conversion ( reftype , expr ) ; 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 ; can_convert_intype_to_type = 1 ; } } if ( ( ( convtype & CONV_STATIC ) && can_convert ( intype , type ) ) || ( ( convtype & CONV_IMPLICIT ) && can_convert_intype_to_type ) ) { if ( flags & LOOKUP_COMPLAIN ) { tree ttl = TREE_TYPE ( reftype ) ; tree ttr = lvalue_type ( expr ) ; if ( ! real_lvalue_p ( expr ) ) warn_ref_binding ( reftype , intype , decl ) ; if ( ! ( convtype & CONV_CONST ) && ! at_least_as_qualified_p ( ttl , ttr ) ) pedwarn ( " " , ttr , reftype ) ; } return build_up_reference ( reftype , expr , flags , decl ) ; } else if ( ( convtype & CONV_REINTERPRET ) && lvalue_p ( expr ) ) { if ( TREE_CODE ( intype ) == POINTER_TYPE && ( comptypes ( TREE_TYPE ( intype ) , type , COMPARE_BASE | COMPARE_DERIVED ) ) ) warning ( 0 , " " , 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 { rval = convert_for_initialization ( NULL_TREE , type , expr , flags , " " , 0 , 0 ) ; if ( rval == NULL_TREE || rval == error_mark_node ) return rval ; warn_ref_binding ( reftype , intype , decl ) ; rval = build_up_reference ( reftype , rval , flags , decl ) ; } if ( rval ) { return rval ; } if ( flags & LOOKUP_COMPLAIN ) error ( " " , intype , reftype ) ; return error_mark_node ; }
For C++: Only need to do one-level references, but cannot
get tripped up on signed/unsigned differences.
For C ++ : Only need to do one - level references but cannot get tripped up on signed / unsigned differences .
/* Look for a user-defined conversion to lvalue that we can use.  */ /* 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 we found a way to convert earlier, then use it.  */