/* 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 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
You should have received a copy of the GNU General Public License
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. */
+the Free Software Foundation, 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
/* This file contains the functions for converting C++ expressions
#include "convert.h"
#include "toplev.h"
#include "decl.h"
+#include "target.h"
static tree cp_convert_to_pointer (tree, tree, bool);
static tree convert_to_pointer_force (tree, tree);
narrowing is always done with a NOP_EXPR:
In convert.c, convert_to_integer.
In c-typeck.c, build_binary_op_nodefault (boolean ops),
- and c_common_truthvalue_conversion.
+ and c_common_truthvalue_conversion.
In expr.c: expand_expr, for operands of a MULT_EXPR.
In fold-const.c: fold.
In tree.c: get_narrower and get_unwidened.
if (!COMPLETE_TYPE_P (intype))
{
error ("can't convert from incomplete type %qT to %qT",
- intype, type);
+ intype, type);
return error_mark_node;
}
{
if (rval == error_mark_node)
error ("conversion of %qE from %qT to %qT is ambiguous",
- expr, intype, type);
+ expr, intype, type);
return rval;
}
}
intype_class = TREE_TYPE (intype);
type_class = TREE_TYPE (type);
- same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
+ same_p = same_type_p (TYPE_MAIN_VARIANT (intype_class),
TYPE_MAIN_VARIANT (type_class));
binfo = NULL_TREE;
/* Try derived to base conversion. */
if (TYPE_PTRMEMFUNC_P (type))
{
error ("cannot convert %qE from type %qT to type %qT",
- expr, intype, type);
+ expr, intype, type);
return error_mark_node;
}
}
else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
{
- tree b1;
+ tree b1;
tree b2;
tree binfo;
enum tree_code code = PLUS_EXPR;
if (bk == bk_via_virtual)
{
if (force)
- warning ("pointer to member cast from %qT to %qT is via"
- " virtual base", intype, type);
+ 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);
+ " via virtual base", intype, type);
return error_mark_node;
}
/* This is a reinterpret cast, whose result is unspecified.
expr = cplus_expand_constant (expr);
if (binfo && !integer_zerop (BINFO_OFFSET (binfo)))
- expr = size_binop (code,
+ expr = size_binop (code,
build_nop (sizetype, expr),
BINFO_OFFSET (binfo));
return build_nop (type, expr);
}
}
error ("cannot convert %qE from type %qT to type %qT",
- expr, intype, type);
+ expr, intype, type);
return error_mark_node;
}
}
else
expr = build_int_cst (type, 0);
-
+
return expr;
}
else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
as a pointer. */
gcc_assert (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
== GET_MODE_SIZE (TYPE_MODE (type)));
-
+
return convert_to_pointer (type, expr);
}
return instantiate_type (type, expr, tf_error | tf_warning);
error ("cannot convert %qE from type %qT to type %qT",
- expr, intype, type);
+ expr, intype, type);
return error_mark_node;
}
{
tree intype = TREE_TYPE (expr);
enum tree_code form = TREE_CODE (intype);
-
+
if (form == POINTER_TYPE)
{
intype = TYPE_MAIN_VARIANT (intype);
if (binfo)
{
expr = build_base_path (code, expr, binfo, 0);
- if (expr == error_mark_node)
- return error_mark_node;
+ if (expr == error_mark_node)
+ return error_mark_node;
/* Add any qualifier conversions. */
if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
TREE_TYPE (type)))
/* Process the initializer for the declaration. */
DECL_INITIAL (arg) = targ;
- cp_finish_decl (arg, targ, NULL_TREE,
+ cp_finish_decl (arg, targ, NULL_TREE,
LOOKUP_ONLYCONVERTING|DIRECT_BIND);
}
else if (!(flags & DIRECT_BIND) && ! lvalue_p (arg))
/* Subroutine of convert_to_reference. REFTYPE is the target reference type.
INTYPE is the original rvalue type and DECL is an optional _DECL node
for diagnostics.
-
+
[dcl.init.ref] says that if an rvalue is used to
initialize a reference, then the reference must be to a
non-volatile const type. */
warn_ref_binding (tree reftype, tree intype, tree decl)
{
tree ttl = TREE_TYPE (reftype);
-
+
if (!CP_TYPE_CONST_NON_VOLATILE_P (ttl))
{
const char *msg;
if (CP_TYPE_VOLATILE_P (ttl) && decl)
msg = "initialization of volatile reference type %q#T from"
- " rvalue of type %qT";
+ " rvalue of type %qT";
else if (CP_TYPE_VOLATILE_P (ttl))
msg = "conversion to volatile reference type %q#T "
- " from rvalue of type %qT";
+ " from rvalue of type %qT";
else if (decl)
msg = "initialization of non-const reference type %q#T from"
- " rvalue of type %qT";
+ " rvalue of type %qT";
else
msg = "conversion to non-const reference type %q#T from"
- " rvalue of type %qT";
+ " rvalue of type %qT";
pedwarn (msg, reftype, intype);
}
tree
convert_to_reference (tree reftype, tree expr, int convtype,
- int flags, tree decl)
+ int flags, tree decl)
{
tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));
tree intype;
tree rval_as_conversion = NULL_TREE;
bool can_convert_intype_to_type;
- if (TREE_CODE (type) == FUNCTION_TYPE
+ if (TREE_CODE (type) == FUNCTION_TYPE
&& TREE_TYPE (expr) == unknown_type_node)
- expr = instantiate_type (type, expr,
+ expr = instantiate_type (type, expr,
(flags & LOOKUP_COMPLAIN)
? tf_error | tf_warning : tf_none);
if (! real_lvalue_p (expr))
warn_ref_binding (reftype, intype, decl);
-
+
if (! (convtype & CONV_CONST)
&& !at_least_as_qualified_p (ttl, ttr))
pedwarn ("conversion from %qT to %qT discards qualifiers",
- ttr, reftype);
+ ttr, reftype);
}
return build_up_reference (reftype, expr, flags, decl);
should be done directly (jason). (int &)ri ---> *(int*)&ri */
/* B* bp; A& ar = (A&)bp; is valid, but it's probably not what they
- meant. */
+ meant. */
if (TREE_CODE (intype) == POINTER_TYPE
&& (comptypes (TREE_TYPE (intype), type,
COMPARE_BASE | COMPARE_DERIVED)))
- warning ("casting %qT to %qT does not dereference pointer",
+ warning (0, "casting %qT to %qT does not dereference pointer",
intype, reftype);
-
+
rval = build_unary_op (ADDR_EXPR, expr, 0);
if (rval != error_mark_node)
rval = convert_force (build_pointer_type (TREE_TYPE (reftype)),
{
tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val)));
tree ref = build1 (INDIRECT_REF, t, val);
-
+
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
so that we get the proper error message if the result is used
to assign to. Also, &* is supposed to be a no-op. */
REFERENCE_REF_P (ref) = 1;
val = ref;
}
-
- return val;
-}
-
-/* Implicitly convert the lvalue EXPR to another lvalue of type TOTYPE,
- preserving cv-qualification. */
-tree
-convert_lvalue (tree totype, tree expr)
-{
- totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr)));
- totype = build_reference_type (totype);
- expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL,
- NULL_TREE);
- return convert_from_reference (expr);
+ return val;
}
/* Really perform an lvalue-to-rvalue conversion, including copying an
{
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)
convert, which will call ocp_convert, etc. */
return e;
/* For complex data types, we need to perform componentwise
- conversion. */
+ conversion. */
else if (TREE_CODE (type) == COMPLEX_TYPE)
- return fold_if_not_in_template (convert_to_complex (type, e));
+ return fold_if_not_in_template (convert_to_complex (type, e));
else if (TREE_CODE (e) == TARGET_EXPR)
{
/* Don't build a NOP_EXPR of class type. Instead, change the
{
tree intype = TREE_TYPE (e);
/* enum = enum, enum = int, enum = float, (enum)pointer are all
- errors. */
+ errors. */
if (TREE_CODE (type) == ENUMERAL_TYPE
&& (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
- || TREE_CODE (intype) == REAL_TYPE)
+ || TREE_CODE (intype) == REAL_TYPE)
&& ! (convtype & CONV_STATIC))
|| TREE_CODE (intype) == POINTER_TYPE))
{
{
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;
+ 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));
}
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
else
- ctor = build_special_member_call (NULL_TREE,
+ ctor = build_special_member_call (NULL_TREE,
complete_ctor_identifier,
build_tree_list (NULL_TREE, ctor),
type, flags);
if (flags & LOOKUP_COMPLAIN)
error ("conversion from %qT to non-scalar type %qT requested",
- TREE_TYPE (expr), type);
+ TREE_TYPE (expr), type);
return error_mark_node;
}
volatile references we do not do this interpretation, because that would
make it impossible to ignore the reference return value from functions. We
issue warnings in the confusing cases.
-
+
IMPLICIT is tells us the context of an implicit void conversion. */
tree
convert_to_void (tree expr, const char *implicit)
{
- if (expr == error_mark_node
+ 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 (TREE_CODE (expr) == PSEUDO_DTOR_EXPR)
+ {
+ error ("pseudo-destructor is not called");
+ return error_mark_node;
+ }
if (VOID_TYPE_P (TREE_TYPE (expr)))
return expr;
switch (TREE_CODE (expr))
{
case COND_EXPR:
{
- /* 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
+ /* 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_SIDE_EFFECTS (op2)
? "second operand of conditional" : NULL));
- tree new_op2 = convert_to_void
+ tree new_op2 = convert_to_void
(op2, (implicit && !TREE_SIDE_EFFECTS (op1)
? "third operand of conditional" : NULL));
-
+
expr = build3 (COND_EXPR, TREE_TYPE (new_op1),
TREE_OPERAND (expr, 0), new_op1, new_op2);
- break;
+ break;
}
-
+
case COMPOUND_EXPR:
{
- /* The second part of a compound expr contains the value. */
- tree op1 = TREE_OPERAND (expr,1);
- tree new_op1 = convert_to_void
+ /* 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_NO_WARNING (expr)
? "right-hand operand of comma" : NULL));
-
- if (new_op1 != op1)
+
+ if (new_op1 != op1)
{
tree t = build2 (COMPOUND_EXPR, TREE_TYPE (new_op1),
TREE_OPERAND (expr, 0), new_op1);
expr = t;
}
- break;
+ break;
}
-
+
case NON_LVALUE_EXPR:
case NOP_EXPR:
/* These have already decayed to rvalue. */
break;
-
+
case CALL_EXPR: /* We have a special meaning for volatile void fn(). */
break;
-
+
case INDIRECT_REF:
{
- tree type = TREE_TYPE (expr);
- int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
- == REFERENCE_TYPE;
- int is_volatile = TYPE_VOLATILE (type);
- int is_complete = COMPLETE_TYPE_P (complete_type (type));
-
- if (is_volatile && !is_complete)
- warning ("object of incomplete type %qT will not be accessed in %s",
- type, implicit ? implicit : "void context");
- else if (is_reference && is_volatile)
- warning ("object of type %qT will not be accessed in %s",
- TREE_TYPE (TREE_OPERAND (expr, 0)),
- implicit ? implicit : "void context");
- if (is_reference || !is_volatile || !is_complete)
- expr = TREE_OPERAND (expr, 0);
-
- break;
+ tree type = TREE_TYPE (expr);
+ int is_reference = TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0)))
+ == REFERENCE_TYPE;
+ int is_volatile = TYPE_VOLATILE (type);
+ int is_complete = COMPLETE_TYPE_P (complete_type (type));
+
+ if (is_volatile && !is_complete)
+ warning (0, "object of incomplete type %qT will not be accessed in %s",
+ type, implicit ? implicit : "void context");
+ else if (is_reference && is_volatile)
+ warning (0, "object of type %qT will not be accessed in %s",
+ TREE_TYPE (TREE_OPERAND (expr, 0)),
+ implicit ? implicit : "void context");
+ if (is_reference || !is_volatile || !is_complete)
+ expr = TREE_OPERAND (expr, 0);
+
+ break;
}
-
+
case VAR_DECL:
{
- /* External variables might be incomplete. */
- tree type = TREE_TYPE (expr);
- int is_complete = COMPLETE_TYPE_P (complete_type (type));
-
- if (TYPE_VOLATILE (type) && !is_complete)
- warning ("object %qE of incomplete type %qT will not be accessed in %s",
- expr, type, implicit ? implicit : "void context");
- break;
+ /* External variables might be incomplete. */
+ tree type = TREE_TYPE (expr);
+ int is_complete = COMPLETE_TYPE_P (complete_type (type));
+
+ if (TYPE_VOLATILE (type) && !is_complete)
+ warning (0, "object %qE of incomplete type %qT will not be accessed in %s",
+ expr, type, implicit ? implicit : "void context");
+ break;
}
default:;
}
{
tree probe = expr;
-
+
if (TREE_CODE (probe) == ADDR_EXPR)
probe = TREE_OPERAND (expr, 0);
if (type_unknown_p (probe))
}
else if (implicit && probe == expr && is_overloaded_fn (probe))
/* Only warn when there is no &. */
- warning ("%s is a reference, not call, to function %qE",
+ warning (0, "%s is a reference, not call, to function %qE",
implicit, expr);
}
-
+
if (expr != error_mark_node && !VOID_TYPE_P (TREE_TYPE (expr)))
{
- if (implicit && warn_unused_value
- && !TREE_SIDE_EFFECTS (expr) && !TREE_NO_WARNING (expr))
- warning ("%s has no effect", implicit);
+ if (implicit && warn_unused_value && !TREE_NO_WARNING (expr))
+ {
+ /* The middle end does not warn about expressions that have
+ been explicitly cast to void, so we must do so here. */
+ if (!TREE_SIDE_EFFECTS (expr))
+ warning (0, "%s has no effect", implicit);
+ else
+ {
+ tree e;
+ enum tree_code code;
+ enum tree_code_class class;
+
+ e = expr;
+ /* We might like to warn about (say) "(int) f()", as the
+ cast has no effect, but the compiler itself will
+ generate implicit conversions under some
+ circumstances. (For example a block copy will be
+ turned into a call to "__builtin_memcpy", with a
+ conversion of the return value to an appropriate
+ type.) So, to avoid false positives, we strip
+ conversions. Do not use STRIP_NOPs because it will
+ not strip conversions to "void", as that is not a
+ mode-preserving conversion. */
+ while (TREE_CODE (e) == NOP_EXPR)
+ e = TREE_OPERAND (e, 0);
+
+ code = TREE_CODE (e);
+ class = TREE_CODE_CLASS (code);
+ if (class == tcc_comparison
+ || class == tcc_unary
+ || (class == tcc_binary
+ && !(code == MODIFY_EXPR
+ || code == INIT_EXPR
+ || code == PREDECREMENT_EXPR
+ || code == PREINCREMENT_EXPR
+ || code == POSTDECREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)))
+ warning (0, "value computed is not used");
+ }
+ }
expr = build1 (CONVERT_EXPR, void_type_node, expr);
}
return expr;
enum tree_code code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
- return (fold_if_not_in_template
+ return (fold_if_not_in_template
(convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
NULL_TREE)));
tree conv = NULL_TREE;
tree winner = NULL_TREE;
- if (expr == null_node
- && (desires & WANT_INT)
+ if (expr == null_node
+ && (desires & WANT_INT)
&& !(desires & WANT_NULL))
- warning ("converting NULL to non-pointer type");
-
+ warning (0, "converting NULL to non-pointer type");
+
basetype = TREE_TYPE (expr);
if (basetype == error_mark_node)
return expr;
/* else fall through... */
+ case VECTOR_TYPE:
case BOOLEAN_TYPE:
return (desires & WANT_INT) ? expr : NULL_TREE;
case ENUMERAL_TYPE:
return (desires & WANT_FLOAT) ? expr : NULL_TREE;
case POINTER_TYPE:
return (desires & WANT_POINTER) ? expr : NULL_TREE;
-
+
case FUNCTION_TYPE:
case ARRAY_TYPE:
return (desires & WANT_POINTER) ? decay_conversion (expr)
- : NULL_TREE;
+ : NULL_TREE;
default:
return NULL_TREE;
}
if (complain)
{
error ("ambiguous default type conversion from %qT",
- basetype);
+ basetype);
error (" candidate conversions include %qD and %qD",
- winner, cand);
+ winner, cand);
}
return error_mark_node;
}
}
else if (type == float_type_node)
type = double_type_node;
-
+
return type;
}
to TYPE. Return the resulting expression, or error_mark_node if
the conversion was impossible. */
-tree
+tree
perform_qualification_conversions (tree type, tree expr)
{
tree expr_type;