FreeBSD/contrib/gcc/cp/typeck.c
/* Perform a const_cast from EXPR to TYPE.  If the cast is valid,
   return an appropriate expression.  Otherwise, return
   error_mark_node.  If the cast is not valid, and COMPLAIN is true,
   then a diagnostic will be issued.  If VALID_P is non-NULL, we are
   performing a C-style cast, its value upon return will indicate
   whether or not the conversion succeeded.  */
Perform a const_cast from EXPR to TYPE.  If the cast is valid,
return an appropriate expression.
Perform a const_cast from EXPR to TYPE . If the cast is valid return an appropriate expression .
static tree
build_const_cast_1 (tree dst_type, tree expr, bool complain,
		    bool *valid_p)
{
  tree src_type;
  tree reference_type;
  gcc_assert (dst_type != error_mark_node);
  gcc_assert (!processing_template_decl);
  if (valid_p)
    *valid_p = false;
  if (!POINTER_TYPE_P (dst_type) && !TYPE_PTRMEM_P (dst_type))
    {
      if (complain)
	error ("invalid use of const_cast with type %qT, "
	       "which is not a pointer, "
	       "reference, nor a pointer-to-data-member type", dst_type);
      return error_mark_node;
    }
  if (TREE_CODE (TREE_TYPE (dst_type)) == FUNCTION_TYPE)
    {
      if (complain)
	error ("invalid use of const_cast with type %qT, which is a pointer "
	       "or reference to a function type", dst_type);
      return error_mark_node;
    }
  used_types_insert (dst_type);
  src_type = TREE_TYPE (expr);
  if (TREE_CODE (src_type) == REFERENCE_TYPE)
    src_type = TREE_TYPE (src_type);
  if (TREE_CODE (dst_type) == REFERENCE_TYPE)
    {
      reference_type = dst_type;
      if (! real_lvalue_p (expr))
	{
	  if (complain)
	    error ("invalid const_cast of an rvalue of type %qT to type %qT",
		   src_type, dst_type);
	  return error_mark_node;
	}
      dst_type = build_pointer_type (TREE_TYPE (dst_type));
      src_type = build_pointer_type (src_type);
    }
  else
    {
      reference_type = NULL_TREE;
      src_type = type_decays_to (src_type);
      if (src_type == error_mark_node)
	return error_mark_node;
    }
  if ((TYPE_PTR_P (src_type) || TYPE_PTRMEM_P (src_type))
      && comp_ptr_ttypes_const (dst_type, src_type))
    {
      if (valid_p)
	{
	  *valid_p = true;
	  if (warn_cast_qual)
	    check_for_casting_away_constness (src_type, dst_type,
					      warning0,
					      "cast");
	}
      if (reference_type)
	{
	  expr = build_unary_op (ADDR_EXPR, expr, 0);
	  expr = build_nop (reference_type, expr);
	  return convert_from_reference (expr);
	}
      else
	{
	  expr = decay_conversion (expr);
	  if (TREE_CODE (expr) == NOP_EXPR
	      && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
	    expr = TREE_OPERAND (expr, 0);
	  return build_nop (dst_type, expr);
	}
    }
  if (complain)
    error ("invalid const_cast from type %qT to type %qT",
	   src_type, dst_type);
  return error_mark_node;
}
static tree build_const_cast_1 ( tree dst_type , tree expr , bool complain , bool * valid_p ) { tree src_type ; tree reference_type ; gcc_assert ( dst_type != error_mark_node ) ; gcc_assert ( ! processing_template_decl ) ; if ( valid_p ) * valid_p = false ; if ( ! POINTER_TYPE_P ( dst_type ) && ! TYPE_PTRMEM_P ( dst_type ) ) { if ( complain ) error ( " " " " " " , dst_type ) ; return error_mark_node ; } if ( TREE_CODE ( TREE_TYPE ( dst_type ) ) == FUNCTION_TYPE ) { if ( complain ) error ( " " " " , dst_type ) ; return error_mark_node ; } used_types_insert ( dst_type ) ; src_type = TREE_TYPE ( expr ) ; if ( TREE_CODE ( src_type ) == REFERENCE_TYPE ) src_type = TREE_TYPE ( src_type ) ; if ( TREE_CODE ( dst_type ) == REFERENCE_TYPE ) { reference_type = dst_type ; if ( ! real_lvalue_p ( expr ) ) { if ( complain ) error ( " " , src_type , dst_type ) ; return error_mark_node ; } dst_type = build_pointer_type ( TREE_TYPE ( dst_type ) ) ; src_type = build_pointer_type ( src_type ) ; } else { reference_type = NULL_TREE ; src_type = type_decays_to ( src_type ) ; if ( src_type == error_mark_node ) return error_mark_node ; } if ( ( TYPE_PTR_P ( src_type ) || TYPE_PTRMEM_P ( src_type ) ) && comp_ptr_ttypes_const ( dst_type , src_type ) ) { if ( valid_p ) { * valid_p = true ; if ( warn_cast_qual ) check_for_casting_away_constness ( src_type , dst_type , warning0 , " " ) ; } if ( reference_type ) { expr = build_unary_op ( ADDR_EXPR , expr , 0 ) ; expr = build_nop ( reference_type , expr ) ; return convert_from_reference ( expr ) ; } else { expr = decay_conversion ( expr ) ; if ( TREE_CODE ( expr ) == NOP_EXPR && TREE_TYPE ( expr ) == TREE_TYPE ( TREE_OPERAND ( expr , 0 ) ) ) expr = TREE_OPERAND ( expr , 0 ) ; return build_nop ( dst_type , expr ) ; } } if ( complain ) error ( " " , src_type , dst_type ) ; return error_mark_node ; }
Perform a const_cast from EXPR to TYPE.
Perform a const_cast from EXPR to TYPE .
/* Callers are responsible for handling error_mark_node as a
     destination type.  */ /* In a template, callers should be building syntactic
     representations of casts, not using this machinery.  */ /* Assume the conversion is invalid.  */ /* Save casted types in the function's used types hash table.  */ /* Expressions do not really have reference types.  */ /* [expr.const.cast]

     An lvalue of type T1 can be explicitly converted to an lvalue of
     type T2 using the cast const_cast<T2&> (where T1 and T2 are object
     types) if a pointer to T1 can be explicitly converted to the type
     pointer to T2 using a const_cast.  */ /* If the destination type is not a reference type, the
	 lvalue-to-rvalue, array-to-pointer, and function-to-pointer
	 conversions are performed.  */ /* This cast is actually a C-style cast.  Issue a warning if
	     the user is making a potentially unsafe cast.  */ /* build_c_cast puts on a NOP_EXPR to make the result not an
	     lvalue.  Strip such NOP_EXPRs if VALUE is being used in
	     non-lvalue context.  */