FreeBSD/contrib/gcc/cp/typeck.c
/* Perform a static_cast from EXPR to TYPE.  When C_CAST_P is true,
   this static_cast is being attempted as one of the possible casts
   allowed by a C-style cast.  (In that case, accessibility of base
   classes is not considered, and it is OK to cast away
   constness.)  Return the result of the cast.  *VALID_P is set to
   indicate whether or not the cast was valid.  */
Perform a static_cast from EXPR to TYPE.  When C_CAST_P is true,
this static_cast is being attempted as one of the possible casts
allowed by a C-style cast.  (In that case, accessibility of base
classes is not considered, and it is OK to cast away
constness.)  Return the result of the cast.  *VALID_P is set to
indicate whether or not the cast was valid.
Perform a static_cast from EXPR to TYPE . When C_CAST_P is true this static_cast is being attempted as one of the possible casts allowed by a C - style cast . ( In that case accessibility of base classes is not considered and it is OK to cast away constness . ) Return the result of the cast . * VALID_P is set to indicate whether or not the cast was valid .
static tree
build_static_cast_1 (tree type, tree expr, bool c_cast_p,
		     bool *valid_p)
{
  tree intype;
  tree result;
  tree orig;
  void (*diag_fn)(const char*, ...) ATTRIBUTE_GCC_CXXDIAG(1,2);
  const char *desc;
  *valid_p = true;
  intype = TREE_TYPE (expr);
  used_types_insert (type);
  if (c_cast_p)
    {
      diag_fn = warn_cast_qual ? warning0 : NULL;
      desc = "cast";
    }
  else
    {
      diag_fn = error;
      desc = "static_cast";
    }
  if (TREE_CODE (type) == REFERENCE_TYPE
      && CLASS_TYPE_P (TREE_TYPE (type))
      && CLASS_TYPE_P (intype)
      && real_lvalue_p (expr)
      && DERIVED_FROM_P (intype, TREE_TYPE (type))
      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
		      build_pointer_type (TYPE_MAIN_VARIANT
					  (TREE_TYPE (type))))
      && (c_cast_p
	  || at_least_as_qualified_p (TREE_TYPE (type), intype)))
    {
      tree base;
      base = lookup_base (TREE_TYPE (type), intype,
			  c_cast_p ? ba_unique : ba_check,
			  NULL);
      expr = build_base_path (MINUS_EXPR, build_address (expr),
			      base, false);
      return convert_from_reference (build_nop (type, expr));
    }
  orig = expr;
  result = perform_direct_initialization_if_possible (type, expr,
						      c_cast_p);
  if (result)
    {
      result = convert_from_reference (result);
      result = ignore_overflows (result, orig);
      if (TREE_CODE (type) != REFERENCE_TYPE)
	result = rvalue (result);
      return result;
    }
  if (TREE_CODE (type) == VOID_TYPE)
    return convert_to_void (expr, NULL);
  if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
      && (INTEGRAL_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype)))
    {
      expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
      expr = ignore_overflows (expr, orig);
      return expr;
    }
  if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
      && CLASS_TYPE_P (TREE_TYPE (type))
      && CLASS_TYPE_P (TREE_TYPE (intype))
      && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
					  (TREE_TYPE (intype))),
		      build_pointer_type (TYPE_MAIN_VARIANT
					  (TREE_TYPE (type)))))
    {
      tree base;
      if (!c_cast_p)
	check_for_casting_away_constness (intype, type, diag_fn, desc);
      base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
			  c_cast_p ? ba_unique : ba_check,
			  NULL);
      return build_base_path (MINUS_EXPR, expr, base, false);
    }
  if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
      || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
    {
      tree c1;
      tree c2;
      tree t1;
      tree t2;
      c1 = TYPE_PTRMEM_CLASS_TYPE (intype);
      c2 = TYPE_PTRMEM_CLASS_TYPE (type);
      if (TYPE_PTRMEM_P (type))
	{
	  t1 = (build_ptrmem_type
		(c1,
		 TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
	  t2 = (build_ptrmem_type
		(c2,
		 TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
	}
      else
	{
	  t1 = intype;
	  t2 = type;
	}
      if (can_convert (t1, t2))
	{
	  if (!c_cast_p)
	    check_for_casting_away_constness (intype, type, diag_fn,
					      desc);
	  return convert_ptrmem (type, expr, 1,
				 c_cast_p);
	}
    }
  if (TREE_CODE (intype) == POINTER_TYPE
      && VOID_TYPE_P (TREE_TYPE (intype))
      && TYPE_PTROB_P (type))
    {
      if (!c_cast_p)
	check_for_casting_away_constness (intype, type, diag_fn, desc);
      return build_nop (type, expr);
    }
  *valid_p = false;
  return error_mark_node;
}
static tree build_static_cast_1 ( tree type , tree expr , bool c_cast_p , bool * valid_p ) { tree intype ; tree result ; tree orig ; void ( * diag_fn ) ( const char * , ... ) ATTRIBUTE_GCC_CXXDIAG ( 1 , 2 ) ; const char * desc ; * valid_p = true ; intype = TREE_TYPE ( expr ) ; used_types_insert ( type ) ; if ( c_cast_p ) { diag_fn = warn_cast_qual ? warning0 : NULL ; desc = " " ; } else { diag_fn = error ; desc = " " ; } if ( TREE_CODE ( type ) == REFERENCE_TYPE && CLASS_TYPE_P ( TREE_TYPE ( type ) ) && CLASS_TYPE_P ( intype ) && real_lvalue_p ( expr ) && DERIVED_FROM_P ( intype , TREE_TYPE ( type ) ) && can_convert ( build_pointer_type ( TYPE_MAIN_VARIANT ( intype ) ) , build_pointer_type ( TYPE_MAIN_VARIANT ( TREE_TYPE ( type ) ) ) ) && ( c_cast_p || at_least_as_qualified_p ( TREE_TYPE ( type ) , intype ) ) ) { tree base ; base = lookup_base ( TREE_TYPE ( type ) , intype , c_cast_p ? ba_unique : ba_check , NULL ) ; expr = build_base_path ( MINUS_EXPR , build_address ( expr ) , base , false ) ; return convert_from_reference ( build_nop ( type , expr ) ) ; } orig = expr ; result = perform_direct_initialization_if_possible ( type , expr , c_cast_p ) ; if ( result ) { result = convert_from_reference ( result ) ; result = ignore_overflows ( result , orig ) ; if ( TREE_CODE ( type ) != REFERENCE_TYPE ) result = rvalue ( result ) ; return result ; } if ( TREE_CODE ( type ) == VOID_TYPE ) return convert_to_void ( expr , NULL ) ; if ( ( INTEGRAL_TYPE_P ( type ) || SCALAR_FLOAT_TYPE_P ( type ) ) && ( INTEGRAL_TYPE_P ( intype ) || SCALAR_FLOAT_TYPE_P ( intype ) ) ) { expr = ocp_convert ( type , expr , CONV_C_CAST , LOOKUP_NORMAL ) ; expr = ignore_overflows ( expr , orig ) ; return expr ; } if ( TYPE_PTR_P ( type ) && TYPE_PTR_P ( intype ) && CLASS_TYPE_P ( TREE_TYPE ( type ) ) && CLASS_TYPE_P ( TREE_TYPE ( intype ) ) && can_convert ( build_pointer_type ( TYPE_MAIN_VARIANT ( TREE_TYPE ( intype ) ) ) , build_pointer_type ( TYPE_MAIN_VARIANT ( TREE_TYPE ( type ) ) ) ) ) { tree base ; if ( ! c_cast_p ) check_for_casting_away_constness ( intype , type , diag_fn , desc ) ; base = lookup_base ( TREE_TYPE ( type ) , TREE_TYPE ( intype ) , c_cast_p ? ba_unique : ba_check , NULL ) ; return build_base_path ( MINUS_EXPR , expr , base , false ) ; } if ( ( TYPE_PTRMEM_P ( type ) && TYPE_PTRMEM_P ( intype ) ) || ( TYPE_PTRMEMFUNC_P ( type ) && TYPE_PTRMEMFUNC_P ( intype ) ) ) { tree c1 ; tree c2 ; tree t1 ; tree t2 ; c1 = TYPE_PTRMEM_CLASS_TYPE ( intype ) ; c2 = TYPE_PTRMEM_CLASS_TYPE ( type ) ; if ( TYPE_PTRMEM_P ( type ) ) { t1 = ( build_ptrmem_type ( c1 , TYPE_MAIN_VARIANT ( TYPE_PTRMEM_POINTED_TO_TYPE ( intype ) ) ) ) ; t2 = ( build_ptrmem_type ( c2 , TYPE_MAIN_VARIANT ( TYPE_PTRMEM_POINTED_TO_TYPE ( type ) ) ) ) ; } else { t1 = intype ; t2 = type ; } if ( can_convert ( t1 , t2 ) ) { if ( ! c_cast_p ) check_for_casting_away_constness ( intype , type , diag_fn , desc ) ; return convert_ptrmem ( type , expr , 1 , c_cast_p ) ; } } if ( TREE_CODE ( intype ) == POINTER_TYPE && VOID_TYPE_P ( TREE_TYPE ( intype ) ) && TYPE_PTROB_P ( type ) ) { if ( ! c_cast_p ) check_for_casting_away_constness ( intype , type , diag_fn , desc ) ; return build_nop ( type , expr ) ; } * valid_p = false ; return error_mark_node ; }
Perform a static_cast from EXPR to TYPE.
Perform a static_cast from EXPR to TYPE .
/* Assume the cast is valid.  */ /* Save casted types in the function's used types hash table.  */ /* Determine what to do when casting away constness.  */ /* C-style casts are allowed to cast away constness.  With
	 WARN_CAST_QUAL, we still want to issue a warning.  */ /* A static_cast may not cast away constness.  */ /* [expr.static.cast]

     An lvalue of type "cv1 B", where B is a class type, can be cast
     to type "reference to cv2 D", where D is a class derived (clause
     _class.derived_) from B, if a valid standard conversion from
     "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the
     same cv-qualification as, or greater cv-qualification than, cv1,
     and B is not a virtual base class of D.  */ /* We check this case before checking the validity of "TYPE t =
     EXPR;" below because for this case:

       struct B {};
       struct D : public B { D(const B&); };
       extern B& b;
       void f() { static_cast<const D&>(b); }

     we want to avoid constructing a new D.  The standard is not
     completely clear about this issue, but our interpretation is
     consistent with other compilers.  */ /* There is a standard conversion from "D*" to "B*" even if "B"
	 is ambiguous or inaccessible.  If this is really a
	 static_cast, then we check both for inaccessibility and
	 ambiguity.  However, if this is a static_cast being performed
	 because the user wrote a C-style cast, then accessibility is
	 not considered.  */ /* Convert from "B*" to "D*".  This function will check that "B"
	 is not a virtual base of "D".  */ /*nonnull=*/ /* Convert the pointer to a reference -- but then remember that
	 there are no expressions with reference type in C++.  */ /* [expr.static.cast]

     An expression e can be explicitly converted to a type T using a
     static_cast of the form static_cast<T>(e) if the declaration T
     t(e);" is well-formed, for some invented temporary variable
     t.  */ /* Ignore any integer overflow caused by the cast.  */ /* [expr.static.cast]

	 If T is a reference type, the result is an lvalue; otherwise,
	 the result is an rvalue.  */ /* [expr.static.cast]

     Any expression can be explicitly converted to type cv void.  */ /*implicit=*/ /* [expr.static.cast]

     The inverse of any standard conversion sequence (clause _conv_),
     other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
     (_conv.array_), function-to-pointer (_conv.func_), and boolean
     (_conv.bool_) conversions, can be performed explicitly using
     static_cast subject to the restriction that the explicit
     conversion does not cast away constness (_expr.const.cast_), and
     the following additional rules for specific cases:  */ /* For reference, the conversions not excluded are: integral
     promotions, floating point promotion, integral conversions,
     floating point conversions, floating-integral conversions,
     pointer conversions, and pointer to member conversions.  */ /* DR 128

     A value of integral _or enumeration_ type can be explicitly
     converted to an enumeration type.  */ /* The effect of all that is that any conversion between any two
     types which are integral, floating, or enumeration types can be
     performed.  */ /* Ignore any integer overflow caused by the cast.  */ /*nonnull=*/ /*allow_inverse_p=*/ /* [expr.static.cast]

     An rvalue of type "pointer to cv void" can be explicitly
     converted to a pointer to object type.  A value of type pointer
     to object converted to "pointer to cv void" and back to the
     original pointer type will have its original value.  */