/* 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.
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.
tree intype = TREE_TYPE (expr);
enum tree_code form;
tree rval;
+ if (intype == error_mark_node)
+ return error_mark_node;
if (IS_AGGR_TYPE (intype))
{
intype = complete_type (intype);
if (!COMPLETE_TYPE_P (intype))
{
- error ("can't convert from incomplete type `%T' to `%T'",
- intype, type);
+ error ("can't convert from incomplete type %qT to %qT",
+ intype, type);
return error_mark_node;
}
if (rval)
{
if (rval == error_mark_node)
- error ("conversion of `%E' from `%T' to `%T' is ambiguous",
- expr, intype, type);
+ error ("conversion of %qE from %qT to %qT is ambiguous",
+ expr, intype, type);
return rval;
}
}
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|| VOID_TYPE_P (TREE_TYPE (type))))
{
- /* Allow an implicit this pointer for pointer to member
- functions. */
- if (TYPE_PTRMEMFUNC_P (intype))
- {
- 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);
- }
- }
- else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
- {
- if (pedantic || warn_pmf2ptr)
- pedwarn ("converting from `%T' to `%T'", intype, type);
- expr = build_addr_func (expr);
- }
+ if (TYPE_PTRMEMFUNC_P (intype)
+ || TREE_CODE (intype) == METHOD_TYPE)
+ return convert_member_func_to_ptr (type, expr);
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
return build_nop (type, expr);
intype = TREE_TYPE (expr);
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 `%E' from type `%T' to type `%T'",
- expr, intype, type);
+ error ("cannot convert %qE from type %qT to type %qT",
+ 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 `%T' to `%T' 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 `%T' to `%T' is via virtual base",
- intype, type);
+ 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.
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);
}
else if (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))
- return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
+ /*c_cast_p=*/false);
else if (TYPE_PTRMEMFUNC_P (intype))
{
if (!warn_pmf2ptr)
TREE_OPERAND (expr, 1));
}
}
- error ("cannot convert `%E' from type `%T' to type `%T'",
- expr, intype, type);
+ error ("cannot convert %qE from type %qT to type %qT",
+ expr, intype, type);
return error_mark_node;
}
if (integer_zerop (expr))
{
if (TYPE_PTRMEMFUNC_P (type))
- return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
+ /*c_cast_p=*/false);
if (TYPE_PTRMEM_P (type))
- /* A NULL pointer-to-member is represented by -1, not by
- zero. */
- expr = build_int_2 (-1, -1);
+ {
+ /* A NULL pointer-to-member is represented by -1, not by
+ zero. */
+ expr = build_int_cst (type, -1);
+ /* Fix up the representation of -1 if appropriate. */
+ expr = force_fit_type (expr, 0, false, false);
+ }
else
- expr = build_int_2 (0, 0);
- TREE_TYPE (expr) = type;
- /* Fix up the representation of -1 if appropriate. */
- force_fit_type (expr, 0);
+ expr = build_int_cst (type, 0);
+
return expr;
}
else if (TYPE_PTR_TO_MEMBER_P (type) && INTEGRAL_CODE_P (form))
{
- error ("invalid conversion from '%T' to '%T'", intype, type);
+ error ("invalid conversion from %qT to %qT", intype, type);
return error_mark_node;
}
if (TYPE_PRECISION (intype) == POINTER_SIZE)
return build1 (CONVERT_EXPR, type, expr);
expr = cp_convert (c_common_type_for_size (POINTER_SIZE, 0), expr);
- /* Modes may be different but sizes should be the same. */
- if (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (expr)))
- != GET_MODE_SIZE (TYPE_MODE (type)))
- /* There is supposed to be some integral type
- that is the same width as a pointer. */
- abort ();
+ /* Modes may be different but sizes should be the same. There
+ is supposed to be some integral type that is the same width
+ 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);
}
if (type_unknown_p (expr))
return instantiate_type (type, expr, tf_error | tf_warning);
- error ("cannot convert `%E' from type `%T' to type `%T'",
- expr, intype, type);
+ error ("cannot convert %qE from type %qT to type %qT",
+ 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);
tree binfo;
binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
- ba_ignore, NULL);
+ ba_unique, NULL);
if (!binfo)
{
binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_ignore, NULL);
+ ba_unique, NULL);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
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)))
tree argtype = TREE_TYPE (arg);
tree target_type = TREE_TYPE (type);
- my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 187);
+ gcc_assert (TREE_CODE (type) == REFERENCE_TYPE);
if ((flags & DIRECT_BIND) && ! real_lvalue_p (arg))
{
/* 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 `%#T' from rvalue of type `%T'";
+ msg = "initialization of volatile reference type %q#T from"
+ " rvalue of type %qT";
else if (CP_TYPE_VOLATILE_P (ttl))
- msg = "conversion to volatile reference type `%#T' from rvalue of type `%T'";
+ msg = "conversion to volatile reference type %q#T "
+ " from rvalue of type %qT";
else if (decl)
- msg = "initialization of non-const reference type `%#T' from rvalue of type `%T'";
+ msg = "initialization of non-const reference type %q#T from"
+ " rvalue of type %qT";
else
- msg = "conversion to non-const reference type `%#T' from rvalue of type `%T'";
+ msg = "conversion to non-const reference type %q#T from"
+ " 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);
- else
- 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);
+ gcc_assert (TREE_CODE (intype) != REFERENCE_TYPE);
intype = TYPE_MAIN_VARIANT (intype);
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 `%T' to `%T' discards qualifiers",
- ttr, reftype);
+ pedwarn ("conversion from %qT to %qT discards qualifiers",
+ 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 `%T' to `%T' 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)),
}
if (flags & LOOKUP_COMPLAIN)
- error ("cannot convert type `%T' to type `%T'", intype, reftype);
+ error ("cannot convert type %qT to type %qT", intype, reftype);
return error_mark_node;
}
convert_from_reference (tree val)
{
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
- return build_indirect_ref (val, NULL);
- return val;
-}
-
-/* Implicitly convert the lvalue EXPR to another lvalue of type TOTYPE,
- preserving cv-qualification. */
+ {
+ 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. */
+ TREE_READONLY (ref) = CP_TYPE_CONST_P (t);
+ TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t);
+ TREE_SIDE_EFFECTS (ref)
+ = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (val));
+ REFERENCE_REF_P (ref) = 1;
+ val = ref;
+ }
-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
complete_type (type);
complete_type (TREE_TYPE (expr));
- e = decl_constant_value (e);
+ e = integral_constant_value (e);
if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
/* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
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 (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
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 ();
+ gcc_assert (same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (e)),
+ TYPE_MAIN_VARIANT (type)));
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));
+ {
+ /* We shouldn't be treating objects of ADDRESSABLE type as
+ rvalues. */
+ gcc_assert (!TREE_ADDRESSABLE (type));
+ return fold_if_not_in_template (build_nop (type, e));
+ }
}
if (code == VOID_TYPE && (convtype & CONV_STATIC))
{
tree intype = TREE_TYPE (e);
/* enum = enum, enum = int, enum = float, (enum)pointer are all
- errors. */
+ errors. */
if (TREE_CODE (type) == ENUMERAL_TYPE
- && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))
- || (TREE_CODE (intype) == POINTER_TYPE)))
+ && (((INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
+ || TREE_CODE (intype) == REAL_TYPE)
+ && ! (convtype & CONV_STATIC))
+ || TREE_CODE (intype) == POINTER_TYPE))
{
- pedwarn ("conversion from `%#T' to `%#T'", intype, type);
+ if (flags & LOOKUP_COMPLAIN)
+ pedwarn ("conversion from %q#T to %q#T", intype, type);
if (flag_pedantic_errors)
return error_mark_node;
if (rval)
return rval;
if (flags & LOOKUP_COMPLAIN)
- error ("`%#T' used where a `%T' was expected", intype, type);
+ error ("%q#T used where a %qT was expected", intype, type);
return error_mark_node;
}
if (code == BOOLEAN_TYPE)
return cp_truthvalue_conversion (e);
- return fold (convert_to_integer (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 (cp_convert_to_pointer (type, e, false));
+ return fold_if_not_in_template (cp_convert_to_pointer (type, e, false));
if (code == VECTOR_TYPE)
- return fold (convert_to_vector (type, e));
+ {
+ tree in_vtype = TREE_TYPE (e);
+ if (IS_AGGR_TYPE (in_vtype))
+ {
+ 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;
+ }
+ return fold_if_not_in_template (convert_to_vector (type, e));
+ }
if (code == REAL_TYPE || code == COMPLEX_TYPE)
{
if (IS_AGGR_TYPE (TREE_TYPE (e)))
return rval;
else
if (flags & LOOKUP_COMPLAIN)
- error ("`%#T' used where a floating point value was expected",
+ error ("%q#T used where a floating point value was expected",
TREE_TYPE (e));
}
if (code == REAL_TYPE)
- return fold (convert_to_real (type, e));
+ return fold_if_not_in_template (convert_to_real (type, e));
else if (code == COMPLEX_TYPE)
- return fold (convert_to_complex (type, e));
+ return fold_if_not_in_template (convert_to_complex (type, e));
}
/* New C++ semantics: since assignment is now based on
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_BINFO (type), flags);
+ type, flags);
if (ctor)
return build_cplus_new (type, ctor);
}
if (flags & LOOKUP_COMPLAIN)
- error ("conversion from `%T' to non-scalar type `%T' requested",
- TREE_TYPE (expr), type);
+ error ("conversion from %qT to non-scalar type %qT requested",
+ 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 = build (COND_EXPR, TREE_TYPE (new_op1),
- TREE_OPERAND (expr, 0), new_op1, new_op2);
- break;
+
+ expr = build3 (COND_EXPR, TREE_TYPE (new_op1),
+ TREE_OPERAND (expr, 0), new_op1, new_op2);
+ 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
- (op1, (implicit && !TREE_NO_UNUSED_WARNING (expr)
+ /* 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 = build (COMPOUND_EXPR, TREE_TYPE (new_op1),
- TREE_OPERAND (expr, 0), new_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 `%T' will not be accessed in %s",
- type, implicit ? implicit : "void context");
- else if (is_reference && is_volatile)
- warning ("object of type `%T' 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 `%E' of incomplete type `%T' 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 `%E'",
+ 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 && !TREE_SIDE_EFFECTS (expr) && warn_unused_value)
- 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;
intype = TREE_TYPE (expr);
if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
- {
- expr = decl_constant_value (expr);
- return fold (build1 (NOP_EXPR, type, expr));
- }
+ return fold_if_not_in_template (build_nop (type, expr));
return ocp_convert (type, expr, CONV_OLD_CONVERT,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
enum tree_code code = TREE_CODE (type);
if (code == REFERENCE_TYPE)
- return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
- NULL_TREE));
- else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)
- e = convert_from_reference (e);
+ return (fold_if_not_in_template
+ (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,
+ NULL_TREE)));
if (code == POINTER_TYPE)
- return fold (convert_to_pointer_force (type, e));
+ return fold_if_not_in_template (convert_to_pointer_force (type, e));
/* From typeck.c convert_for_assignment */
if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
|| integer_zerop (e)
|| TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
&& TYPE_PTRMEMFUNC_P (type))
- {
- /* compatible pointer to member functions. */
- return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
- }
+ /* compatible pointer to member functions. */
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1,
+ /*c_cast_p=*/1);
return ocp_convert (type, e, CONV_C_CAST|convtype, LOOKUP_NORMAL);
}
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");
-
- expr = convert_from_reference (expr);
+ 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 `%T'",
- basetype);
- error (" candidate conversions include `%D' and `%D'",
- winner, cand);
+ error ("ambiguous default type conversion from %qT",
+ basetype);
+ error (" candidate conversions include %qD and %qD",
+ 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;