summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/cvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/cvt.c')
-rw-r--r--contrib/gcc/cp/cvt.c419
1 files changed, 195 insertions, 224 deletions
diff --git a/contrib/gcc/cp/cvt.c b/contrib/gcc/cp/cvt.c
index 75a6a3a..48be5c5 100644
--- a/contrib/gcc/cp/cvt.c
+++ b/contrib/gcc/cp/cvt.c
@@ -1,33 +1,35 @@
/* Language-level data type conversion for GNU C++.
Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
-This file is part of GNU CC.
+This file is part of GCC.
-GNU CC is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-GNU CC is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* This file contains the functions for converting C expressions
+/* This file contains the functions for converting C++ expressions
to different data types. The only entry point is `convert'.
Every language front end must have a `convert' function
but what kind of conversions it does will depend on the language. */
#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
#include "tree.h"
#include "flags.h"
#include "cp-tree.h"
@@ -35,10 +37,10 @@ Boston, MA 02111-1307, USA. */
#include "toplev.h"
#include "decl.h"
-static tree cp_convert_to_pointer PARAMS ((tree, tree, int));
-static tree convert_to_pointer_force PARAMS ((tree, tree));
-static tree build_up_reference PARAMS ((tree, tree, int, tree));
-static void warn_ref_binding PARAMS ((tree, tree, tree));
+static tree cp_convert_to_pointer (tree, tree, bool);
+static tree convert_to_pointer_force (tree, tree);
+static tree build_up_reference (tree, tree, int, tree);
+static void warn_ref_binding (tree, tree, tree);
/* Change of width--truncation and extension of integers or reals--
is represented with NOP_EXPR. Proper functioning of many things
@@ -72,12 +74,10 @@ static void warn_ref_binding PARAMS ((tree, tree, tree));
but not static_cast). */
static tree
-cp_convert_to_pointer (type, expr, force)
- tree type, expr;
- int force;
+cp_convert_to_pointer (tree type, tree expr, bool force)
{
- register tree intype = TREE_TYPE (expr);
- register enum tree_code form;
+ tree intype = TREE_TYPE (expr);
+ enum tree_code form;
tree rval;
if (IS_AGGR_TYPE (intype))
@@ -109,24 +109,26 @@ cp_convert_to_pointer (type, expr, force)
functions. */
if (TYPE_PTRMEMFUNC_P (intype))
{
- tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
- tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
- expr = build (OFFSET_REF, fntype, decl, expr);
+ if (pedantic || warn_pmf2ptr)
+ pedwarn ("converting from `%T' to `%T'", intype, type);
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ expr = build_address (PTRMEM_CST_MEMBER (expr));
+ else
+ {
+ tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype),
+ 0);
+ decl = build_address (decl);
+ expr = get_member_function_from_ptrfunc (&decl, expr);
+ }
}
-
- if (TREE_CODE (expr) == OFFSET_REF
- && TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
- expr = resolve_offset_ref (expr);
- if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
- expr = build_addr_func (expr);
- if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+ else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
{
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
- if (pedantic || warn_pmf2ptr)
- pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr),
- type);
- return build1 (NOP_EXPR, type, expr);
+ if (pedantic || warn_pmf2ptr)
+ pedwarn ("converting from `%T' to `%T'", intype, type);
+ expr = build_addr_func (expr);
}
+ if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
+ return build_nop (type, expr);
intype = TREE_TYPE (expr);
}
@@ -178,68 +180,81 @@ cp_convert_to_pointer (type, expr, force)
}
}
- if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ if (TYPE_PTRMEMFUNC_P (type))
{
- tree b1;
- tree b2;
- tree binfo;
- enum tree_code code = PLUS_EXPR;
- base_kind bk;
+ error ("cannot convert `%E' from type `%T' to type `%T'",
+ expr, intype, type);
+ return error_mark_node;
+ }
- b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
- b2 = TYPE_OFFSET_BASETYPE (TREE_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;
+ 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 (bk == bk_via_virtual)
+ {
+ if (force)
+ warning ("pointer to member cast from `%T' to `%T' is via virtual base",
+ intype, type);
+ else
{
- if (force)
- warning ("pointer to member cast from `%T' to `%T' is via virtual base",
- TREE_TYPE (intype), TREE_TYPE (type));
- else
- {
- error ("pointer to member cast from `%T' to `%T' is via virtual base",
- TREE_TYPE (intype), TREE_TYPE (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);
+ error ("pointer to member cast from `%T' to `%T' is via virtual base",
+ intype, type);
+ return error_mark_node;
}
-
- if (TREE_CODE (expr) == PTRMEM_CST)
- expr = cplus_expand_constant (expr);
-
- if (binfo)
- expr = size_binop (code, convert (sizetype, expr),
- BINFO_OFFSET (binfo));
- }
- else if (TYPE_PTRMEMFUNC_P (type))
- {
- error ("cannot convert `%E' from type `%T' to type `%T'",
- expr, 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);
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);
+ else if (TREE_CODE (expr) == OFFSET_REF)
+ {
+ tree object = TREE_OPERAND (expr, 0);
+ return get_member_function_from_ptrfunc (&object,
+ TREE_OPERAND (expr, 1));
+ }
+ }
error ("cannot convert `%E' from type `%T' to type `%T'",
expr, intype, type);
return error_mark_node;
}
- my_friendly_assert (form != OFFSET_TYPE, 186);
-
if (integer_zerop (expr))
{
if (TYPE_PTRMEMFUNC_P (type))
@@ -256,8 +271,7 @@ cp_convert_to_pointer (type, expr, force)
force_fit_type (expr, 0);
return expr;
}
- else if ((TYPE_PTRMEM_P (type) || TYPE_PTRMEMFUNC_P (type))
- && INTEGRAL_CODE_P (form))
+ else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
{
error ("invalid conversion from '%T' to '%T'", intype, type);
return error_mark_node;
@@ -290,11 +304,10 @@ cp_convert_to_pointer (type, expr, force)
(such as conversion from sub-type to private super-type). */
static tree
-convert_to_pointer_force (type, expr)
- tree type, expr;
+convert_to_pointer_force (tree type, tree expr)
{
- register tree intype = TREE_TYPE (expr);
- register enum tree_code form = TREE_CODE (intype);
+ tree intype = TREE_TYPE (expr);
+ enum tree_code form = TREE_CODE (intype);
if (form == POINTER_TYPE)
{
@@ -333,7 +346,7 @@ convert_to_pointer_force (type, expr)
}
}
- return cp_convert_to_pointer (type, expr, 1);
+ return cp_convert_to_pointer (type, expr, true);
}
/* We are passing something to a function which requires a reference.
@@ -345,9 +358,7 @@ convert_to_pointer_force (type, expr)
If DIRECT_BIND is set, DECL is the reference we're binding to. */
static tree
-build_up_reference (type, arg, flags, decl)
- tree type, arg, decl;
- int flags;
+build_up_reference (tree type, tree arg, int flags, tree decl)
{
tree rval;
tree argtype = TREE_TYPE (arg);
@@ -406,8 +417,7 @@ build_up_reference (type, arg, flags, decl)
non-volatile const type. */
static void
-warn_ref_binding (reftype, intype, decl)
- tree reftype, intype, decl;
+warn_ref_binding (tree reftype, tree intype, tree decl)
{
tree ttl = TREE_TYPE (reftype);
@@ -436,41 +446,35 @@ warn_ref_binding (reftype, intype, decl)
we know it's an initialization. */
tree
-convert_to_reference (reftype, expr, convtype, flags, decl)
- tree reftype, expr;
- int convtype, flags;
- tree decl;
+convert_to_reference (tree reftype, tree expr, int convtype,
+ int flags, tree decl)
{
- register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
- register tree intype;
+ tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
+ tree intype;
tree rval = NULL_TREE;
tree rval_as_conversion = NULL_TREE;
- int i;
+ 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_error | tf_warning : tf_none);
- if (expr == error_mark_node)
- return error_mark_node;
-
- intype = TREE_TYPE (expr);
- }
+ expr = instantiate_type (type, expr,
+ (flags & LOOKUP_COMPLAIN)
+ ? tf_error | tf_warning : tf_none);
else
- {
- expr = convert_from_reference (expr);
- intype = TREE_TYPE (expr);
- }
+ expr = convert_from_reference (expr);
+
+ if (expr == error_mark_node)
+ return error_mark_node;
+
+ intype = TREE_TYPE (expr);
my_friendly_assert (TREE_CODE (intype) != REFERENCE_TYPE, 364);
intype = TYPE_MAIN_VARIANT (intype);
- i = comp_target_types (type, intype, 0);
-
- if (i <= 0 && (convtype & CONV_IMPLICIT) && IS_AGGR_TYPE (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))
{
/* Look for a user-defined conversion to lvalue that we can use. */
@@ -484,12 +488,12 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
expr = rval_as_conversion;
rval_as_conversion = NULL_TREE;
intype = type;
- i = 1;
+ can_convert_intype_to_type = 1;
}
}
- if (((convtype & CONV_STATIC) && i == -1)
- || ((convtype & CONV_IMPLICIT) && i == 1))
+ if (((convtype & CONV_STATIC) && can_convert (intype, type))
+ || ((convtype & CONV_IMPLICIT) && can_convert_intype_to_type))
{
if (flags & LOOKUP_COMPLAIN)
{
@@ -517,10 +521,10 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
/* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
meant. */
if (TREE_CODE (intype) == POINTER_TYPE
- && (comptypes (TREE_TYPE (intype), type,
- COMPARE_BASE | COMPARE_RELAXED )))
+ && (comptypes (TREE_TYPE (intype), type,
+ COMPARE_BASE | COMPARE_DERIVED)))
warning ("casting `%T' to `%T' does not dereference pointer",
- intype, reftype);
+ intype, reftype);
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
@@ -545,8 +549,6 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
return rval;
}
- my_friendly_assert (TREE_CODE (intype) != OFFSET_TYPE, 189);
-
if (flags & LOOKUP_COMPLAIN)
error ("cannot convert type `%T' to type `%T'", intype, reftype);
@@ -560,14 +562,9 @@ convert_to_reference (reftype, expr, convtype, flags, decl)
way down to its lowest form. */
tree
-convert_from_reference (val)
- tree val;
+convert_from_reference (tree val)
{
- tree type = TREE_TYPE (val);
-
- if (TREE_CODE (type) == OFFSET_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == REFERENCE_TYPE)
+ if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
return build_indirect_ref (val, NULL);
return val;
}
@@ -576,8 +573,7 @@ convert_from_reference (val)
preserving cv-qualification. */
tree
-convert_lvalue (totype, expr)
- tree totype, expr;
+convert_lvalue (tree totype, tree expr)
{
totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr)));
totype = build_reference_type (totype);
@@ -604,8 +600,7 @@ force_rvalue (tree expr)
/* C++ conversions, preference to static cast conversions. */
tree
-cp_convert (type, expr)
- tree type, expr;
+cp_convert (tree type, tree expr)
{
return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);
}
@@ -615,15 +610,12 @@ cp_convert (type, expr)
FLAGS indicates how we should behave. */
tree
-ocp_convert (type, expr, convtype, flags)
- tree type, expr;
- int convtype, flags;
+ocp_convert (tree type, tree expr, int convtype, int flags)
{
- register tree e = expr;
- register enum tree_code code = TREE_CODE (type);
+ tree e = expr;
+ enum tree_code code = TREE_CODE (type);
- if (e == error_mark_node
- || TREE_TYPE (e) == error_mark_node)
+ if (error_operand_p (e) || type == error_mark_node)
return error_mark_node;
complete_type (type);
@@ -642,7 +634,7 @@ ocp_convert (type, expr, convtype, flags)
if (same_type_p (type, TREE_TYPE (e)))
/* 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 comparsion in fold is just equality of pointers, not a
+ 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. */
@@ -651,6 +643,20 @@ ocp_convert (type, expr, convtype, flags)
conversion. */
else if (TREE_CODE (type) == COMPLEX_TYPE)
return fold (convert_to_complex (type, e));
+ 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. */
+ if (!same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
+ TYPE_MAIN_VARIANT (type)))
+ abort ();
+ TREE_TYPE (e) = TREE_TYPE (TARGET_EXPR_SLOT (e)) = type;
+ return e;
+ }
+ else if (TREE_ADDRESSABLE (type))
+ /* We shouldn't be treating objects of ADDRESSABLE type as rvalues. */
+ abort ();
else
return fold (build1 (NOP_EXPR, type, e));
}
@@ -661,16 +667,6 @@ ocp_convert (type, expr, convtype, flags)
return e;
}
- /* Just convert to the type of the member. */
- if (code == OFFSET_TYPE)
- {
- type = TREE_TYPE (type);
- code = TREE_CODE (type);
- }
-
- if (TREE_CODE (e) == OFFSET_REF)
- e = resolve_offset_ref (e);
-
if (INTEGRAL_CODE_P (code))
{
tree intype = TREE_TYPE (e);
@@ -698,25 +694,12 @@ ocp_convert (type, expr, convtype, flags)
return error_mark_node;
}
if (code == BOOLEAN_TYPE)
- {
- tree fn = NULL_TREE;
-
- /* Common Ada/Pascal programmer's mistake. We always warn
- about this since it is so bad. */
- if (TREE_CODE (expr) == FUNCTION_DECL)
- fn = expr;
- else if (TREE_CODE (expr) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL)
- fn = TREE_OPERAND (expr, 0);
- if (fn && !DECL_WEAK (fn))
- warning ("the address of `%D', will always be `true'", fn);
- return cp_truthvalue_conversion (e);
- }
+ return cp_truthvalue_conversion (e);
+
return fold (convert_to_integer (type, e));
}
- if (code == POINTER_TYPE || code == REFERENCE_TYPE
- || TYPE_PTRMEMFUNC_P (type))
- return fold (cp_convert_to_pointer (type, e, 0));
+ if (POINTER_TYPE_P (type) || TYPE_PTR_TO_MEMBER_P (type))
+ return fold (cp_convert_to_pointer (type, e, false));
if (code == VECTOR_TYPE)
return fold (convert_to_vector (type, e));
if (code == REAL_TYPE || code == COMPLEX_TYPE)
@@ -787,7 +770,7 @@ ocp_convert (type, expr, convtype, flags)
no lvalue-rvalue and similar conversions happen [expr.static.cast/4,
stmt.expr/1, expr.comma/1]. This permits dereferencing an incomplete type
in a void context. The C++ standard does not define what an `access' to an
- object is, but there is reason to beleive that it is the lvalue to rvalue
+ object is, but there is reason to believe that it is the lvalue to rvalue
conversion -- if it were not, `*&*p = 1' would violate [expr]/4 in that it
accesses `*p' not to calculate the value to be stored. But, dcl.type.cv/8
indicates that volatile semantics should be the same between C and C++
@@ -801,15 +784,15 @@ ocp_convert (type, expr, convtype, flags)
IMPLICIT is tells us the context of an implicit void conversion. */
tree
-convert_to_void (expr, implicit)
- tree expr;
- const char *implicit;
+convert_to_void (tree expr, const char *implicit)
{
if (expr == error_mark_node
|| TREE_TYPE (expr) == error_mark_node)
return error_mark_node;
if (!TREE_TYPE (expr))
return expr;
+ if (invalid_nonstatic_memfn_p (expr))
+ return error_mark_node;
if (VOID_TYPE_P (TREE_TYPE (expr)))
return expr;
switch (TREE_CODE (expr))
@@ -819,8 +802,12 @@ convert_to_void (expr, implicit)
/* The two parts of a cond expr might be separate lvalues. */
tree op1 = TREE_OPERAND (expr,1);
tree op2 = TREE_OPERAND (expr,2);
- tree new_op1 = convert_to_void (op1, implicit);
- tree new_op2 = convert_to_void (op2, implicit);
+ tree new_op1 = convert_to_void
+ (op1, (implicit && !TREE_SIDE_EFFECTS (op2)
+ ? "second operand of conditional" : NULL));
+ tree new_op2 = convert_to_void
+ (op2, (implicit && !TREE_SIDE_EFFECTS (op1)
+ ? "third operand of conditional" : NULL));
expr = build (COND_EXPR, TREE_TYPE (new_op1),
TREE_OPERAND (expr, 0), new_op1, new_op2);
@@ -831,14 +818,14 @@ convert_to_void (expr, implicit)
{
/* The second part of a compound expr contains the value. */
tree op1 = TREE_OPERAND (expr,1);
- tree new_op1 = convert_to_void (op1, implicit);
+ tree new_op1 = convert_to_void
+ (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr)
+ ? "right-hand operand of comma" : NULL));
if (new_op1 != op1)
{
tree t = build (COMPOUND_EXPR, TREE_TYPE (new_op1),
TREE_OPERAND (expr, 0), new_op1);
- TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (expr);
- TREE_NO_UNUSED_WARNING (t) = TREE_NO_UNUSED_WARNING (expr);
expr = t;
}
@@ -850,7 +837,7 @@ convert_to_void (expr, implicit)
/* These have already decayed to rvalue. */
break;
- case CALL_EXPR: /* we have a special meaning for volatile void fn() */
+ case CALL_EXPR: /* We have a special meaning for volatile void fn(). */
break;
case INDIRECT_REF:
@@ -886,10 +873,6 @@ convert_to_void (expr, implicit)
break;
}
- case OFFSET_REF:
- expr = resolve_offset_ref (expr);
- break;
-
default:;
}
{
@@ -903,6 +886,7 @@ convert_to_void (expr, implicit)
of an overloaded function, and this is not one of them. */
pedwarn ("%s cannot resolve address of overloaded function",
implicit ? implicit : "void cast");
+ expr = void_zero_node;
}
else if (implicit && probe == expr && is_overloaded_fn (probe))
/* Only warn when there is no &. */
@@ -912,13 +896,9 @@ convert_to_void (expr, implicit)
if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
{
- /* FIXME: This is where we should check for expressions with no
- effects. At the moment we do that in both build_x_component_expr
- and expand_expr_stmt -- inconsistently too. For the moment
- leave implicit void conversions unadorned so that expand_expr_stmt
- has a chance of detecting some of the cases. */
- if (!implicit)
- expr = build1 (CONVERT_EXPR, void_type_node, expr);
+ if (implicit && !TREE_SIDE_EFFECTS (expr) && warn_unused_value)
+ warning ("%s has no effect", implicit);
+ expr = build1 (CONVERT_EXPR, void_type_node, expr);
}
return expr;
}
@@ -941,8 +921,7 @@ convert_to_void (expr, implicit)
do a little bit more work. */
tree
-convert (type, expr)
- tree type, expr;
+convert (tree type, tree expr)
{
tree intype;
@@ -966,13 +945,10 @@ convert (type, expr)
(such as conversion from sub-type to private super-type). */
tree
-convert_force (type, expr, convtype)
- tree type;
- tree expr;
- int convtype;
+convert_force (tree type, tree expr, int convtype)
{
- register tree e = expr;
- register enum tree_code code = TREE_CODE (type);
+ tree e = expr;
+ enum tree_code code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
@@ -1010,8 +986,7 @@ convert_force (type, expr, convtype)
(jason 8/9/95) */
tree
-build_type_conversion (xtype, expr)
- tree xtype, expr;
+build_type_conversion (tree xtype, tree expr)
{
/* C++: check to see if we can convert this aggregate type
into the required type. */
@@ -1020,14 +995,11 @@ build_type_conversion (xtype, expr)
/* Convert the given EXPR to one of a group of types suitable for use in an
expression. DESIRES is a combination of various WANT_* flags (q.v.)
- which indicates which types are suitable. If COMPLAIN is 1, complain
+ which indicates which types are suitable. If COMPLAIN is true, complain
about ambiguity; otherwise, the caller will deal with it. */
tree
-build_expr_type_conversion (desires, expr, complain)
- int desires;
- tree expr;
- int complain;
+build_expr_type_conversion (int desires, tree expr, bool complain)
{
tree basetype = TREE_TYPE (expr);
tree conv = NULL_TREE;
@@ -1038,8 +1010,6 @@ build_expr_type_conversion (desires, expr, complain)
&& !(desires & WANT_NULL))
warning ("converting NULL to non-pointer type");
- if (TREE_CODE (expr) == OFFSET_REF)
- expr = resolve_offset_ref (expr);
expr = convert_from_reference (expr);
basetype = TREE_TYPE (expr);
@@ -1065,7 +1035,7 @@ build_expr_type_conversion (desires, expr, complain)
case FUNCTION_TYPE:
case ARRAY_TYPE:
- return (desires & WANT_POINTER) ? default_conversion (expr)
+ return (desires & WANT_POINTER) ? decay_conversion (expr)
: NULL_TREE;
default:
return NULL_TREE;
@@ -1073,8 +1043,9 @@ build_expr_type_conversion (desires, expr, complain)
/* The code for conversions from class type is currently only used for
delete expressions. Other expressions are handled by build_new_op. */
-
- if (! TYPE_HAS_CONVERSION (basetype))
+ if (!complete_type_or_else (basetype, expr))
+ return error_mark_node;
+ if (!TYPE_HAS_CONVERSION (basetype))
return NULL_TREE;
for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
@@ -1086,9 +1057,7 @@ build_expr_type_conversion (desires, expr, complain)
if (winner && winner == cand)
continue;
- candidate = TREE_TYPE (TREE_TYPE (cand));
- if (TREE_CODE (candidate) == REFERENCE_TYPE)
- candidate = TREE_TYPE (candidate);
+ candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
switch (TREE_CODE (candidate))
{
@@ -1126,9 +1095,7 @@ build_expr_type_conversion (desires, expr, complain)
if (winner)
{
- tree type = TREE_TYPE (TREE_TYPE (winner));
- if (TREE_CODE (type) == REFERENCE_TYPE)
- type = TREE_TYPE (type);
+ tree type = non_reference (TREE_TYPE (TREE_TYPE (winner)));
return build_user_type_conversion (type, expr, LOOKUP_NORMAL);
}
@@ -1138,15 +1105,11 @@ build_expr_type_conversion (desires, expr, complain)
/* Implements integral promotion (4.1) and float->double promotion. */
tree
-type_promotes_to (type)
- tree type;
+type_promotes_to (tree type)
{
- int type_quals;
-
if (type == error_mark_node)
return error_mark_node;
- type_quals = cp_type_quals (type);
type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same
@@ -1179,8 +1142,8 @@ type_promotes_to (type)
}
else if (type == float_type_node)
type = double_type_node;
-
- return cp_build_qualified_type (type, type_quals);
+
+ return type;
}
/* The routines below this point are carefully written to conform to
@@ -1193,14 +1156,22 @@ type_promotes_to (type)
the conversion was impossible. */
tree
-perform_qualification_conversions (type, expr)
- tree type;
- tree expr;
+perform_qualification_conversions (tree type, tree expr)
{
- if (TREE_CODE (type) == POINTER_TYPE
- && TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE
- && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (TREE_TYPE (expr))))
- return build1 (NOP_EXPR, type, expr);
+ tree expr_type;
+
+ expr_type = TREE_TYPE (expr);
+
+ if (TYPE_PTR_P (type) && TYPE_PTR_P (expr_type)
+ && comp_ptr_ttypes (TREE_TYPE (type), TREE_TYPE (expr_type)))
+ return build_nop (type, expr);
+ else if (TYPE_PTR_TO_MEMBER_P (type)
+ && TYPE_PTR_TO_MEMBER_P (expr_type)
+ && same_type_p (TYPE_PTRMEM_CLASS_TYPE (type),
+ TYPE_PTRMEM_CLASS_TYPE (expr_type))
+ && comp_ptr_ttypes (TYPE_PTRMEM_POINTED_TO_TYPE (type),
+ TYPE_PTRMEM_POINTED_TO_TYPE (expr_type)))
+ return build_nop (type, expr);
else
return error_mark_node;
}
OpenPOWER on IntegriCloud