FreeBSD/contrib/gcc/cp/cvt.c
/* Conversion...

   FLAGS indicates how we should behave.  */
Conversion
FLAGS indicates how we should behave.
Conversion FLAGS indicates how we should behave .
tree
ocp_convert (tree type, tree expr, int convtype, int flags)
{
  tree e = expr;
  enum tree_code code = TREE_CODE (type);
  const char *invalid_conv_diag;
  if (error_operand_p (e) || type == error_mark_node)
    return error_mark_node;
  complete_type (type);
  complete_type (TREE_TYPE (expr));
  if ((invalid_conv_diag
       = targetm.invalid_conversion (TREE_TYPE (expr), type)))
    {
      error (invalid_conv_diag, "");
      return error_mark_node;
    }
  e = integral_constant_value (e);
  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
      && TYPE_HAS_CONSTRUCTOR (type))
    ;
  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
    {
      if (same_type_p (type, TREE_TYPE (e)))
	return e;
      else if (TREE_CODE (type) == COMPLEX_TYPE)
	return fold_if_not_in_template (convert_to_complex (type, e));
      else if (TREE_CODE (e) == TARGET_EXPR)
	{
	  gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
				   TYPE_MAIN_VARIANT (type)));
	  TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
	  return e;
	}
      else
	{
	  gcc_assert (!TREE_ADDRESSABLE (type));
	  return fold_if_not_in_template (build_nop (type, e));
	}
    }
  if (code == VOID_TYPE && (convtype & CONV_STATIC))
    {
      e = convert_to_void (e, NULL);
      return e;
    }
  if (INTEGRAL_CODE_P (code))
    {
      tree intype = TREE_TYPE (e);
      if (TREE_CODE (type) == ENUMERAL_TYPE
	  && (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
		|| TREE_CODE (intype) == REAL_TYPE)
	       && ! (convtype & CONV_STATIC))
	      || TREE_CODE (intype) == POINTER_TYPE))
	{
	  if (flags & LOOKUP_COMPLAIN)
	    pedwarn ("conversion from %q#T to %q#T", intype, type);
	  if (flag_pedantic_errors)
	    return error_mark_node;
	}
      if (IS_AGGR_TYPE (intype))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  if (flags & LOOKUP_COMPLAIN)
	    error ("%q#T used where a %qT was expected", intype, type);
	  return error_mark_node;
	}
      if (code == BOOLEAN_TYPE)
	return cp_truthvalue_conversion (e);
      return fold_if_not_in_template (convert_to_integer (type, e));
    }
  if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
    return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
  if (code == VECTOR_TYPE)
    {
      tree in_vtype = TREE_TYPE (e);
      if (IS_AGGR_TYPE (in_vtype))
	{
	  tree ret_val;
	  ret_val = build_type_conversion (type, e);
	  if (ret_val)
	    return ret_val;
	  if (flags & LOOKUP_COMPLAIN)
	    error ("%q#T used where a %qT was expected", in_vtype, type);
	  return error_mark_node;
	}
      return fold_if_not_in_template (convert_to_vector (type, e));
    }
  if (code == REAL_TYPE || code == COMPLEX_TYPE)
    {
      if (IS_AGGR_TYPE (TREE_TYPE (e)))
	{
	  tree rval;
	  rval = build_type_conversion (type, e);
	  if (rval)
	    return rval;
	  else
	    if (flags & LOOKUP_COMPLAIN)
	      error ("%q#T used where a floating point value was expected",
			TREE_TYPE (e));
	}
      if (code == REAL_TYPE)
	return fold_if_not_in_template (convert_to_real (type, e));
      else if (code == COMPLEX_TYPE)
	return fold_if_not_in_template (convert_to_complex (type, e));
    }
  if (IS_AGGR_TYPE_CODE (code))
    {
      tree dtype = TREE_TYPE (e);
      tree ctor = NULL_TREE;
      dtype = TYPE_MAIN_VARIANT (dtype);
      ctor = e;
      if (abstract_virtuals_error (NULL_TREE, type))
	return error_mark_node;
      if ((flags & LOOKUP_ONLYCONVERTING)
	  && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
	ctor = build_user_type_conversion (type, ctor, flags);
      else
	ctor = build_special_member_call (NULL_TREE,
					  complete_ctor_identifier,
					  build_tree_list (NULL_TREE, ctor),
					  type, flags);
      if (ctor)
	return build_cplus_new (type, ctor);
    }
  if (flags & LOOKUP_COMPLAIN)
    error ("conversion from %qT to non-scalar type %qT requested",
	   TREE_TYPE (expr), type);
  return error_mark_node;
}
tree ocp_convert ( tree type , tree expr , int convtype , int flags ) { tree e = expr ; enum tree_code code = TREE_CODE ( type ) ; const char * invalid_conv_diag ; if ( error_operand_p ( e ) || type == error_mark_node ) return error_mark_node ; complete_type ( type ) ; complete_type ( TREE_TYPE ( expr ) ) ; if ( ( invalid_conv_diag = targetm . invalid_conversion ( TREE_TYPE ( expr ) , type ) ) ) { error ( invalid_conv_diag , " " ) ; return error_mark_node ; } e = integral_constant_value ( e ) ; if ( IS_AGGR_TYPE ( type ) && ( convtype & CONV_FORCE_TEMP ) && TYPE_HAS_CONSTRUCTOR ( type ) ) ; else if ( TYPE_MAIN_VARIANT ( type ) == TYPE_MAIN_VARIANT ( TREE_TYPE ( e ) ) ) { if ( same_type_p ( type , TREE_TYPE ( e ) ) ) return e ; else if ( TREE_CODE ( type ) == COMPLEX_TYPE ) return fold_if_not_in_template ( convert_to_complex ( type , e ) ) ; else if ( TREE_CODE ( e ) == TARGET_EXPR ) { gcc_assert ( same_type_p ( TYPE_MAIN_VARIANT ( TREE_TYPE ( e ) ) , TYPE_MAIN_VARIANT ( type ) ) ) ; TREE_TYPE ( e ) = TREE_TYPE ( TARGET_EXPR_SLOT ( e ) ) = type ; return e ; } else { gcc_assert ( ! TREE_ADDRESSABLE ( type ) ) ; return fold_if_not_in_template ( build_nop ( type , e ) ) ; } } if ( code == VOID_TYPE && ( convtype & CONV_STATIC ) ) { e = convert_to_void ( e , NULL ) ; return e ; } if ( INTEGRAL_CODE_P ( code ) ) { tree intype = TREE_TYPE ( e ) ; if ( TREE_CODE ( type ) == ENUMERAL_TYPE && ( ( ( INTEGRAL_OR_ENUMERATION_TYPE_P ( intype ) || TREE_CODE ( intype ) == REAL_TYPE ) && ! ( convtype & CONV_STATIC ) ) || TREE_CODE ( intype ) == POINTER_TYPE ) ) { if ( flags & LOOKUP_COMPLAIN ) pedwarn ( " " , intype , type ) ; if ( flag_pedantic_errors ) return error_mark_node ; } if ( IS_AGGR_TYPE ( intype ) ) { tree rval ; rval = build_type_conversion ( type , e ) ; if ( rval ) return rval ; if ( flags & LOOKUP_COMPLAIN ) error ( " " , intype , type ) ; return error_mark_node ; } if ( code == BOOLEAN_TYPE ) return cp_truthvalue_conversion ( e ) ; return fold_if_not_in_template ( convert_to_integer ( type , e ) ) ; } if ( POINTER_TYPE_P ( type ) || TYPE_PTR_TO_MEMBER_P ( type ) ) return fold_if_not_in_template ( cp_convert_to_pointer ( type , e , false ) ) ; if ( code == VECTOR_TYPE ) { tree in_vtype = TREE_TYPE ( e ) ; if ( IS_AGGR_TYPE ( in_vtype ) ) { tree ret_val ; ret_val = build_type_conversion ( type , e ) ; if ( ret_val ) return ret_val ; if ( flags & LOOKUP_COMPLAIN ) error ( " " , in_vtype , type ) ; return error_mark_node ; } return fold_if_not_in_template ( convert_to_vector ( type , e ) ) ; } if ( code == REAL_TYPE || code == COMPLEX_TYPE ) { if ( IS_AGGR_TYPE ( TREE_TYPE ( e ) ) ) { tree rval ; rval = build_type_conversion ( type , e ) ; if ( rval ) return rval ; else if ( flags & LOOKUP_COMPLAIN ) error ( " " , TREE_TYPE ( e ) ) ; } if ( code == REAL_TYPE ) return fold_if_not_in_template ( convert_to_real ( type , e ) ) ; else if ( code == COMPLEX_TYPE ) return fold_if_not_in_template ( convert_to_complex ( type , e ) ) ; } if ( IS_AGGR_TYPE_CODE ( code ) ) { tree dtype = TREE_TYPE ( e ) ; tree ctor = NULL_TREE ; dtype = TYPE_MAIN_VARIANT ( dtype ) ; ctor = e ; if ( abstract_virtuals_error ( NULL_TREE , type ) ) return error_mark_node ; if ( ( flags & LOOKUP_ONLYCONVERTING ) && ! ( IS_AGGR_TYPE ( dtype ) && DERIVED_FROM_P ( type , dtype ) ) ) ctor = build_user_type_conversion ( type , ctor , flags ) ; else ctor = build_special_member_call ( NULL_TREE , complete_ctor_identifier , build_tree_list ( NULL_TREE , ctor ) , type , flags ) ; if ( ctor ) return build_cplus_new ( type , ctor ) ; } if ( flags & LOOKUP_COMPLAIN ) error ( " " , TREE_TYPE ( expr ) , type ) ; return error_mark_node ; }
Conversion...
FLAGS indicates how we should behave.
Conversion ... FLAGS indicates how we should behave .
/* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
	 don't go through finish_struct, so they don't have the synthesized
	 constructors.  So don't force a temporary.  */ /* We need a new temporary; don't take this shortcut.  */ /* The call to fold will not always remove the NOP_EXPR as
	   might be expected, since if one of the types is a typedef;
	   the comparison in fold is just equality of pointers, not a
	   call to comptypes.  We don't call fold in this case because
	   that can result in infinite recursion; fold will call
	   convert, which will call ocp_convert, etc.  */ /* For complex data types, we need to perform componentwise
	 conversion.  */ /* Don't build a NOP_EXPR of class type.  Instead, change the
	     type of the temporary.  Only allow this for cv-qual changes,
	     though.  */ /* We shouldn't be treating objects of ADDRESSABLE type as
	     rvalues.  */ /*implicit=*/ /* enum = enum, enum = int, enum = float, (enum)pointer are all
	 errors.  */ /* New C++ semantics:  since assignment is now based on
     memberwise copying,  if the rhs type is derived from the
     lhs type, then we may still do a conversion.  */ /* Conversion between aggregate types.  New C++ semantics allow
	 objects of derived type to be cast to objects of base type.
	 Old semantics only allowed this between pointers.

	 There may be some ambiguity between using a constructor
	 vs. using a type conversion operator when both apply.  */ /* For copy-initialization, first we create a temp of the proper type
	   with a user-defined conversion sequence, then we direct-initialize
	   the target with the temp (see [dcl.init]).  */