/* Language-level data type conversion for GNU C++.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
#include "decl.h"
#include "target.h"
-static tree cp_convert_to_pointer (tree, tree, bool);
+static tree cp_convert_to_pointer (tree, tree);
static tree convert_to_pointer_force (tree, tree);
static tree build_type_conversion (tree, tree);
static tree build_up_reference (tree, tree, int, tree);
else if dealing with method pointers, delegate
else convert blindly
else if converting class, pass off to build_type_conversion
- else try C-style pointer conversion. If FORCE is true then allow
- conversions via virtual bases (these are permitted by reinterpret_cast,
- but not static_cast). */
+ else try C-style pointer conversion. */
static tree
-cp_convert_to_pointer (tree type, tree expr, bool force)
+cp_convert_to_pointer (tree type, tree expr)
{
tree intype = TREE_TYPE (expr);
enum tree_code form;
if (intype == error_mark_node)
return error_mark_node;
- if (IS_AGGR_TYPE (intype))
+ if (MAYBE_CLASS_TYPE_P (intype))
{
intype = complete_type (intype);
if (!COMPLETE_TYPE_P (intype))
if (TYPE_MAIN_VARIANT (type) != intype
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (type))
- && IS_AGGR_TYPE (TREE_TYPE (intype))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
return build_nop (type, expr);
}
- else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
- {
- tree b1;
- tree b2;
- tree binfo;
- enum tree_code code = PLUS_EXPR;
- base_kind bk;
-
- b1 = TYPE_PTRMEM_CLASS_TYPE (type);
- b2 = TYPE_PTRMEM_CLASS_TYPE (intype);
- binfo = lookup_base (b1, b2, ba_check, &bk);
- if (!binfo)
- {
- binfo = lookup_base (b2, b1, ba_check, &bk);
- code = MINUS_EXPR;
- }
- if (binfo == error_mark_node)
- return error_mark_node;
-
- if (bk == bk_via_virtual)
- {
- if (force)
- warning (0, "pointer to member cast from %qT to %qT is via"
- " virtual base", intype, type);
- else
- {
- error ("pointer to member cast from %qT to %qT is"
- " via virtual base", intype, type);
- return error_mark_node;
- }
- /* This is a reinterpret cast, whose result is unspecified.
- We choose to do nothing. */
- return build1 (NOP_EXPR, type, expr);
- }
-
- if (TREE_CODE (expr) == PTRMEM_CST)
- expr = cplus_expand_constant (expr);
-
- if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
- expr = size_binop (code,
- build_nop (sizetype, expr),
- BINFO_OFFSET (binfo));
- return build_nop (type, expr);
- }
- else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
- return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
- /*c_cast_p=*/false);
+ else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ return convert_ptrmem (type, expr, /*allow_inverse_p=*/false,
+ /*c_cast_p=*/false);
else if (TYPE_PTRMEMFUNC_P (intype))
{
if (!warn_pmf2ptr)
{
if (TREE_CODE (expr) == PTRMEM_CST)
return cp_convert_to_pointer (type,
- PTRMEM_CST_MEMBER (expr),
- force);
+ PTRMEM_CST_MEMBER (expr));
else if (TREE_CODE (expr) == OFFSET_REF)
{
tree object = TREE_OPERAND (expr, 0);
if (TYPE_MAIN_VARIANT (type) != intype
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
- && IS_AGGR_TYPE (TREE_TYPE (type))
- && IS_AGGR_TYPE (TREE_TYPE (intype))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (type))
+ && MAYBE_CLASS_TYPE_P (TREE_TYPE (intype))
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
}
}
- return cp_convert_to_pointer (type, expr, true);
+ return cp_convert_to_pointer (type, expr);
}
/* We are passing something to a function which requires a reference.
if ((flags & LOOKUP_PROTECT)
&& TYPE_MAIN_VARIANT (argtype) != TYPE_MAIN_VARIANT (target_type)
- && IS_AGGR_TYPE (argtype)
- && IS_AGGR_TYPE (target_type))
+ && MAYBE_CLASS_TYPE_P (argtype)
+ && MAYBE_CLASS_TYPE_P (target_type))
{
/* We go through lookup_base for the access control. */
tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
msg = "conversion to non-const reference type %q#T from"
" rvalue of type %qT";
- pedwarn (msg, reftype, intype);
+ permerror (msg, reftype, intype);
}
}
can_convert_intype_to_type = can_convert (type, intype);
if (!can_convert_intype_to_type
- && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (intype)
+ && (convtype & CONV_IMPLICIT) && MAYBE_CLASS_TYPE_P (intype)
&& ! (flags & LOOKUP_NO_CONVERSION))
{
/* Look for a user-defined conversion to lvalue that we can use. */
if (! (convtype & CONV_CONST)
&& !at_least_as_qualified_p (ttl, ttr))
- pedwarn ("conversion from %qT to %qT discards qualifiers",
- ttr, reftype);
+ permerror ("conversion from %qT to %qT discards qualifiers",
+ ttr, reftype);
}
return build_up_reference (reftype, expr, flags, decl);
tree
force_rvalue (tree expr)
{
- if (IS_AGGR_TYPE (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (expr)) && TREE_CODE (expr) != TARGET_EXPR)
expr = ocp_convert (TREE_TYPE (expr), expr,
CONV_IMPLICIT|CONV_FORCE_TEMP, LOOKUP_NORMAL);
else
e = integral_constant_value (e);
- if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
- /* 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. */
- && TYPE_HAS_CONSTRUCTOR (type))
+ if (MAYBE_CLASS_TYPE_P (type) && (convtype & CONV_FORCE_TEMP))
/* We need a new temporary; don't take this shortcut. */;
- else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))
+ else if (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (e)))
{
if (same_type_p (type, TREE_TYPE (e)))
/* The call to fold will not always remove the NOP_EXPR as
else if (TREE_CODE (e) == TARGET_EXPR)
{
/* Don't build a NOP_EXPR of class type. Instead, change the
- type of the temporary. Only allow this for cv-qual changes,
- though. */
- gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
- TYPE_MAIN_VARIANT (type)));
+ type of the temporary. */
TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
return e;
}
|| TREE_CODE (intype) == POINTER_TYPE))
{
if (flags & LOOKUP_COMPLAIN)
- pedwarn ("conversion from %q#T to %q#T", intype, type);
+ permerror ("conversion from %q#T to %q#T", intype, type);
- if (flag_pedantic_errors)
+ if (!flag_permissive)
return error_mark_node;
}
- if (IS_AGGR_TYPE (intype))
+ if (MAYBE_CLASS_TYPE_P (intype))
{
tree rval;
rval = build_type_conversion (type, 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));
+ return fold_if_not_in_template (cp_convert_to_pointer (type, e));
if (code == VECTOR_TYPE)
{
tree in_vtype = TREE_TYPE (e);
- if (IS_AGGR_TYPE (in_vtype))
+ if (MAYBE_CLASS_TYPE_P (in_vtype))
{
tree ret_val;
ret_val = build_type_conversion (type, e);
}
if (code == REAL_TYPE || code == COMPLEX_TYPE)
{
- if (IS_AGGR_TYPE (TREE_TYPE (e)))
+ if (MAYBE_CLASS_TYPE_P (TREE_TYPE (e)))
{
tree rval;
rval = build_type_conversion (type, e);
/* 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. */
- if (IS_AGGR_TYPE_CODE (code))
+ if (RECORD_OR_UNION_CODE_P (code))
{
tree dtype = TREE_TYPE (e);
tree ctor = NULL_TREE;
return error_mark_node;
if ((flags & LOOKUP_ONLYCONVERTING)
- && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
+ && ! (MAYBE_CLASS_TYPE_P (dtype) && DERIVED_FROM_P (type, dtype)))
/* 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]). */
{
/* [over.over] enumerates the places where we can take the address
of an overloaded function, and this is not one of them. */
- pedwarn ("%s cannot resolve address of overloaded function",
- implicit ? implicit : "void cast");
+ error ("%s cannot resolve address of overloaded function",
+ implicit ? implicit : "void cast");
expr = void_zero_node;
}
else if (implicit && probe == expr && is_overloaded_fn (probe))
if (basetype == error_mark_node)
return error_mark_node;
- if (! IS_AGGR_TYPE (basetype))
+ if (! MAYBE_CLASS_TYPE_P (basetype))
switch (TREE_CODE (basetype))
{
case INTEGER_TYPE: