/* Functions related to invoking methods and overloaded functions.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
+ Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
#include "intl.h"
#include "target.h"
#include "convert.h"
+#include "langhooks.h"
/* The various kinds of conversion. */
static tree build_temp (tree, tree, int, diagnostic_fn_t *);
static void check_constructor_callable (tree, tree);
-/* Returns nonzero iff the destructor name specified in NAME
- (a BIT_NOT_EXPR) matches BASETYPE. The operand of NAME can take many
- forms... */
+/* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
+ NAME can take many forms... */
bool
check_dtor_name (tree basetype, tree name)
{
- name = TREE_OPERAND (name, 0);
-
/* Just accept something we've already complained about. */
if (name == error_mark_node)
return true;
if ((IS_AGGR_TYPE (basetype) && name == constructor_name (basetype))
|| (TREE_CODE (basetype) == ENUMERAL_TYPE
&& name == TYPE_IDENTIFIER (basetype)))
- name = basetype;
+ return true;
else
name = get_type_value (name);
}
return false;
}
- if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
- return true;
- return false;
+ if (!name)
+ return false;
+ return same_type_p (TYPE_MAIN_VARIANT (basetype), TYPE_MAIN_VARIANT (name));
}
/* We want the address of a function or method. We avoid creating a
TREE_VALUE (tmp), t);
}
- function = build3 (CALL_EXPR, result_type, function, parms, NULL_TREE);
+ function = build_call_list (result_type, function, parms);
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_NOTHROW (function) = nothrow;
A null pointer constant is an integral constant expression
(_expr.const_) rvalue of integer type that evaluates to zero. */
t = integral_constant_value (t);
- if (t == null_node
- || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
+ if (t == null_node)
return true;
+ if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))
+ {
+ STRIP_NOPS (t);
+ if (!TREE_OVERFLOW (t))
+ return true;
+ }
return false;
}
alloc_conversion (conversion_kind kind)
{
conversion *c;
- c = conversion_obstack_alloc (sizeof (conversion));
+ c = (conversion *) conversion_obstack_alloc (sizeof (conversion));
c->kind = kind;
return c;
}
static conversion **
alloc_conversions (size_t n)
{
- return conversion_obstack_alloc (n * sizeof (conversion *));
+ return (conversion **) conversion_obstack_alloc (n * sizeof (conversion *));
}
static conversion *
conv = build_conv (ck_lvalue, from, conv);
}
else if (fromref || (expr && lvalue_p (expr)))
- conv = build_conv (ck_rvalue, from, conv);
+ {
+ if (expr)
+ {
+ tree bitfield_type;
+ bitfield_type = is_bitfield_expr_with_lowered_type (expr);
+ if (bitfield_type)
+ from = strip_top_quals (bitfield_type);
+ }
+ conv = build_conv (ck_rvalue, from, conv);
+ }
/* Allow conversion between `__complex__' data types. */
if (tcode == COMPLEX_TYPE && fcode == COMPLEX_TYPE)
that necessitates this conversion is ill-formed.
Therefore, we use DERIVED_FROM_P, and do not check
access or uniqueness. */
- && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
+ && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from))
+ /* If FROM is not yet complete, then we must be parsing
+ the body of a class. We know what's derived from
+ what, but we can't actually perform a
+ derived-to-base conversion. For example, in:
+
+ struct D : public B {
+ static const int i = sizeof((B*)(D*)0);
+ };
+
+ the D*-to-B* conversion is a reinterpret_cast, not a
+ static_cast. */
+ && COMPLETE_TYPE_P (TREE_TYPE (from)))
{
from =
cp_build_qualified_type (TREE_TYPE (to),
|| !compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
|| cp_type_quals (fbase) != cp_type_quals (tbase))
- return 0;
+ return NULL;
from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
from = build_method_type_directly (from,
|| tcode == REAL_TYPE)
{
if (! (INTEGRAL_CODE_P (fcode) || fcode == REAL_TYPE))
- return 0;
+ return NULL;
conv = build_conv (ck_std, to, conv);
/* Give this a better rank if it's a promotion. */
conv->rank = cr_promotion;
}
else if (fcode == VECTOR_TYPE && tcode == VECTOR_TYPE
- && vector_types_convertible_p (from, to))
+ && vector_types_convertible_p (from, to, false))
return build_conv (ck_std, to, conv);
else if (!(flags & LOOKUP_CONSTRUCTOR_CALLABLE)
&& IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
tree access_path, tree conversion_path,
int viable)
{
- struct z_candidate *cand
- = conversion_obstack_alloc (sizeof (struct z_candidate));
+ struct z_candidate *cand = (struct z_candidate *)
+ conversion_obstack_alloc (sizeof (struct z_candidate));
cand->fn = fn;
cand->args = args;
break;
if (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
break;
- if (TREE_CODE (type1) == ENUMERAL_TYPE && TREE_CODE (type2) == ENUMERAL_TYPE)
+ if (TREE_CODE (type1) == ENUMERAL_TYPE
+ && TREE_CODE (type2) == ENUMERAL_TYPE)
break;
- if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
+ if (TYPE_PTR_P (type1)
+ && null_ptr_cst_p (args[1])
+ && !uses_template_parms (type1))
{
type2 = type1;
break;
}
- if (null_ptr_cst_p (args[0]) && TYPE_PTR_P (type2))
+ if (null_ptr_cst_p (args[0])
+ && TYPE_PTR_P (type2)
+ && !uses_template_parms (type2))
{
type1 = type2;
break;
(candidates, code, code2, fnname, TREE_VALUE (types[0]),
NULL_TREE, args, argtypes, flags);
}
-
- return;
}
/* Indent successive candidates by the width of the translation
of the above string. */
size_t len = gcc_gettext_width (str) + 1;
- char *spaces = alloca (len);
+ char *spaces = (char *) alloca (len);
memset (spaces, ' ', len-1);
spaces[len - 1] = '\0';
candidates = splice_viable (candidates, pedantic, &any_viable_p);
if (!any_viable_p)
- return 0;
+ return NULL;
cand = tourney (candidates);
if (cand == 0)
error ("invalid use of void expression");
return error_mark_node;
}
+ else if (invalid_nonstatic_memfn_p (arg))
+ return error_mark_node;
}
return args;
}
required by the allocation, and is updated if that is changed here.
*COOKIE_SIZE is non-NULL if a cookie should be used. If this
function determines that no cookie should be used, after all,
- *COOKIE_SIZE is set to NULL_TREE. */
+ *COOKIE_SIZE is set to NULL_TREE. If FN is non-NULL, it will be
+ set, upon return, to the allocation function called. */
tree
-build_operator_new_call (tree fnname, tree args, tree *size, tree *cookie_size)
+build_operator_new_call (tree fnname, tree args,
+ tree *size, tree *cookie_size,
+ tree *fn)
{
tree fns;
struct z_candidate *candidates;
struct z_candidate *cand;
bool any_viable_p;
+ if (fn)
+ *fn = NULL_TREE;
args = tree_cons (NULL_TREE, *size, args);
args = resolve_args (args);
if (args == error_mark_node)
*cookie_size = NULL_TREE;
}
+ /* Tell our caller which function we decided to call. */
+ if (fn)
+ *fn = cand->fn;
+
/* Build the CALL_EXPR. */
return build_over_call (cand, LOOKUP_NORMAL);
}
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
- arg2_type = TREE_TYPE (arg2);
- arg3_type = TREE_TYPE (arg3);
+ arg2_type = is_bitfield_expr_with_lowered_type (arg2);
+ if (!arg2_type)
+ arg2_type = TREE_TYPE (arg2);
+ arg3_type = is_bitfield_expr_with_lowered_type (arg3);
+ if (!arg3_type)
+ arg3_type = TREE_TYPE (arg3);
if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type))
{
/* Do the conversions. We don't these for `void' type arguments
result_type = void_type_node;
else
{
- error ("%qE has type %<void%> and is not a throw-expression",
- VOID_TYPE_P (arg2_type) ? arg2 : arg3);
+ if (VOID_TYPE_P (arg2_type))
+ error ("second operand to the conditional operator "
+ "is of type %<void%>, "
+ "but the third operand is neither a throw-expression "
+ "nor of type %<void%>");
+ else
+ error ("third operand to the conditional operator "
+ "is of type %<void%>, "
+ "but the second operand is neither a throw-expression "
+ "nor of type %<void%>");
return error_mark_node;
}
|| (conv3 && conv3->kind == ck_ambig))
{
error ("operands to ?: have different types %qT and %qT",
- arg2_type, arg3_type);
+ arg2_type, arg3_type);
result = error_mark_node;
}
else if (conv2 && (!conv2->bad_p || !conv3))
arg2 = convert_like (conv2, arg2);
arg2 = convert_from_reference (arg2);
arg2_type = TREE_TYPE (arg2);
+ /* Even if CONV2 is a valid conversion, the result of the
+ conversion may be invalid. For example, if ARG3 has type
+ "volatile X", and X does not have a copy constructor
+ accepting a "volatile X&", then even if ARG2 can be
+ converted to X, the conversion will fail. */
+ if (error_operand_p (arg2))
+ result = error_mark_node;
}
else if (conv3 && (!conv3->bad_p || !conv2))
{
arg3 = convert_like (conv3, arg3);
arg3 = convert_from_reference (arg3);
arg3_type = TREE_TYPE (arg3);
+ if (error_operand_p (arg3))
+ result = error_mark_node;
}
/* Free all the conversions we allocated. */
if (!result_type)
{
- error ("operands to ?: have different types %qT and %qT",
- arg2_type, arg3_type);
+ error ("operands to ?: have different types %qT and %qT",
+ arg2_type, arg3_type);
return error_mark_node;
}
/* We can't use result_type below, as fold might have returned a
throw_expr. */
- /* Expand both sides into the same slot, hopefully the target of the
- ?: expression. We used to check for TARGET_EXPRs here, but now we
- sometimes wrap them in NOP_EXPRs so the test would fail. */
- if (!lvalue_p && CLASS_TYPE_P (TREE_TYPE (result)))
- result = get_target_expr (result);
-
- /* If this expression is an rvalue, but might be mistaken for an
- lvalue, we must add a NON_LVALUE_EXPR. */
- if (!lvalue_p && real_lvalue_p (result))
- result = rvalue (result);
+ if (!lvalue_p)
+ {
+ /* Expand both sides into the same slot, hopefully the target of
+ the ?: expression. We used to check for TARGET_EXPRs here,
+ but now we sometimes wrap them in NOP_EXPRs so the test would
+ fail. */
+ if (CLASS_TYPE_P (TREE_TYPE (result)))
+ result = get_target_expr (result);
+ /* If this expression is an rvalue, but might be mistaken for an
+ lvalue, we must add a NON_LVALUE_EXPR. */
+ result = rvalue (result);
+ }
return result;
}
SIZE is the size of the memory block to be deleted.
GLOBAL_P is true if the delete-expression should not consider
class-specific delete operators.
- PLACEMENT is the corresponding placement new call, or NULL_TREE. */
+ PLACEMENT is the corresponding placement new call, or NULL_TREE.
+ If PLACEMENT is non-NULL, then ALLOC_FN is the allocation function
+ called to perform the placement new. */
tree
build_op_delete_call (enum tree_code code, tree addr, tree size,
- bool global_p, tree placement)
+ bool global_p, tree placement,
+ tree alloc_fn)
{
tree fn = NULL_TREE;
tree fns, fnname, argtypes, args, type;
if (placement)
{
- tree alloc_fn;
- tree call_expr;
-
- /* Find the allocation function that is being called. */
- call_expr = placement;
- /* Extract the function. */
- alloc_fn = get_callee_fndecl (call_expr);
+ /* Get the parameter types for the allocation function that is
+ being called. */
gcc_assert (alloc_fn != NULL_TREE);
- /* Then the second parm type. */
argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
/* Also the second argument. */
- args = TREE_CHAIN (TREE_OPERAND (call_expr, 1));
+ args = TREE_CHAIN (TREE_OPERAND (placement, 1));
}
else
{
/* On the second pass, the second argument must be
"size_t". */
else if (pass == 1
- && same_type_p (TREE_VALUE (t), sizetype)
+ && same_type_p (TREE_VALUE (t), size_type_node)
&& TREE_CHAIN (t) == void_list_node)
break;
}
/* If the FN is a member function, make sure that it is
accessible. */
if (DECL_CLASS_SCOPE_P (fn))
- perform_or_defer_access_check (TYPE_BINFO (type), fn);
+ perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
/* If the current scope isn't allowed to access DECL along
BASETYPE_PATH, give an error. The most derived class in
- BASETYPE_PATH is the one used to qualify DECL. */
+ BASETYPE_PATH is the one used to qualify DECL. DIAG_DECL is
+ the declaration to use in the error diagnostic. */
bool
-enforce_access (tree basetype_path, tree decl)
+enforce_access (tree basetype_path, tree decl, tree diag_decl)
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
if (!accessible_p (basetype_path, decl, true))
{
if (TREE_PRIVATE (decl))
- error ("%q+#D is private", decl);
+ error ("%q+#D is private", diag_decl);
else if (TREE_PROTECTED (decl))
- error ("%q+#D is protected", decl);
+ error ("%q+#D is protected", diag_decl);
else
- error ("%q+#D is inaccessible", decl);
+ error ("%q+#D is inaccessible", diag_decl);
error ("within this context");
return false;
}
tree t = non_reference (totype);
/* Issue warnings about peculiar, but valid, uses of NULL. */
- if (ARITHMETIC_TYPE_P (t) && expr == null_node)
+ if (expr == null_node && TREE_CODE (t) != BOOLEAN_TYPE && ARITHMETIC_TYPE_P (t))
{
if (fn)
warning (OPT_Wconversion, "passing NULL to non-pointer argument %P of %qD",
}
case ck_identity:
if (type_unknown_p (expr))
- expr = instantiate_type (totype, expr, tf_error | tf_warning);
+ expr = instantiate_type (totype, expr, tf_warning_or_error);
/* Convert a constant to its underlying value, unless we are
about to bind it to a reference, in which case we need to
leave it as an lvalue. */
switch (convs->kind)
{
case ck_rvalue:
+ expr = convert_bitfield_to_declared_type (expr);
if (! IS_AGGR_TYPE (totype))
return expr;
/* Else fall through. */
if (! pod_type_p (type))
{
+ /* Remove reference types so we don't ICE later on. */
+ tree type1 = non_reference (type);
/* Undefined behavior [expr.call] 5.2.2/7. */
warning (0, "cannot receive objects of non-POD type %q#T through %<...%>; "
"call will abort at runtime", type);
- expr = convert (build_pointer_type (type), null_node);
+ expr = convert (build_pointer_type (type1), null_node);
expr = build2 (COMPOUND_EXPR, TREE_TYPE (expr),
call_builtin_trap (), expr);
expr = build_indirect_ref (expr, NULL);
tree expr;
tree return_type;
return_type = TREE_TYPE (TREE_TYPE (fn));
- expr = build3 (CALL_EXPR, return_type, fn, args, NULL_TREE);
+ expr = build_call_list (return_type, fn, args);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
if (DECL_TEMPLATE_INFO (fn)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
perform_or_defer_access_check (cand->access_path,
- DECL_TI_TEMPLATE (fn));
+ DECL_TI_TEMPLATE (fn), fn);
else
- perform_or_defer_access_check (cand->access_path, fn);
+ perform_or_defer_access_check (cand->access_path, fn, fn);
}
if (args && TREE_CODE (args) != TREE_LIST)
tree type = TREE_VALUE (parm);
conv = convs[i];
+
+ /* Don't make a copy here if build_call is going to. */
+ if (conv->kind == ck_rvalue
+ && !TREE_ADDRESSABLE (complete_type (type)))
+ conv = conv->u.next;
+
val = convert_like_with_context
(conv, TREE_VALUE (arg), fn, i - is_method);
tree_cons (NULL_TREE, java_int_type_node,
endlink)));
java_iface_lookup_fn
- = builtin_function ("_Jv_LookupInterfaceMethodIdx",
- build_function_type (ptr_type_node, t),
- 0, NOT_BUILT_IN, NULL, NULL_TREE);
+ = add_builtin_function ("_Jv_LookupInterfaceMethodIdx",
+ build_function_type (ptr_type_node, t),
+ 0, NOT_BUILT_IN, NULL, NULL_TREE);
}
/* Look up the pointer to the runtime java.lang.Class object for `instance'.
lookup_fn = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
java_iface_lookup_fn);
- return build3 (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE);
+ return build_call_list (ptr_type_node, lookup_fn, lookup_args);
}
/* Returns the value to use for the in-charge parameter when making a
return build_new_method_call (instance, fns, args,
TYPE_BINFO (BINFO_TYPE (binfo)),
- flags);
+ flags, /*fn=*/NULL);
}
/* Return the NAME, as a C string. The NAME indicates a function that
return pretty_name;
}
-/* Build a call to "INSTANCE.FN (ARGS)". */
+/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
+ be set, upon return, to the function called. */
tree
build_new_method_call (tree instance, tree fns, tree args,
- tree conversion_path, int flags)
+ tree conversion_path, int flags,
+ tree *fn_p)
{
struct z_candidate *candidates = 0, *cand;
tree explicit_targs = NULL_TREE;
gcc_assert (instance != NULL_TREE);
+ /* We don't know what function we're going to call, yet. */
+ if (fn_p)
+ *fn_p = NULL_TREE;
+
if (error_operand_p (instance)
|| error_operand_p (fns)
|| args == error_mark_node)
}
else
{
+ fn = cand->fn;
+
if (!(flags & LOOKUP_NONVIRTUAL)
- && DECL_PURE_VIRTUAL_P (cand->fn)
+ && DECL_PURE_VIRTUAL_P (fn)
&& instance == current_class_ref
&& (DECL_CONSTRUCTOR_P (current_function_decl)
|| DECL_DESTRUCTOR_P (current_function_decl)))
warning (0, (DECL_CONSTRUCTOR_P (current_function_decl) ?
"abstract virtual %q#D called from constructor"
: "abstract virtual %q#D called from destructor"),
- cand->fn);
+ fn);
- if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
+ if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
&& is_dummy_object (instance_ptr))
{
error ("cannot call member function %qD without object",
- cand->fn);
+ fn);
call = error_mark_node;
}
else
{
- if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
+ if (DECL_VINDEX (fn) && ! (flags & LOOKUP_NONVIRTUAL)
&& resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
-
+ /* Now we know what function is being called. */
+ if (fn_p)
+ *fn_p = fn;
+ /* Build the actual CALL_EXPR. */
call = build_over_call (cand, flags);
-
/* In an expression of the form `a->f()' where `f' turns
out to be a static member function, `a' is
none-the-less evaluated. */
- if (TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE
+ if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE
&& !is_dummy_object (instance_ptr)
- && TREE_SIDE_EFFECTS (instance))
+ && TREE_SIDE_EFFECTS (instance_ptr))
call = build2 (COMPOUND_EXPR, TREE_TYPE (call),
- instance, call);
+ instance_ptr, call);
}
}
}
if (processing_template_decl && call != error_mark_node)
- call = (build_min_non_dep
- (CALL_EXPR, call,
+ call = (build_min_non_dep_call_list
+ (call,
build_min_nt (COMPONENT_REF, orig_instance, orig_fns, NULL_TREE),
- orig_args, NULL_TREE));
+ orig_args));
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
static void
add_warning (struct z_candidate *winner, struct z_candidate *loser)
{
- candidate_warning *cw;
-
- cw = conversion_obstack_alloc (sizeof (candidate_warning));
+ candidate_warning *cw = (candidate_warning *)
+ conversion_obstack_alloc (sizeof (candidate_warning));
cw->loser = loser;
cw->next = winner->warnings;
winner->warnings = cw;
if (warn)
{
- warning (0, "passing %qT chooses %qT over %qT",
- type, type1, type2);
- warning (0, " in call to %qD", w->fn);
+ warning (OPT_Wsign_promo, "passing %qT chooses %qT over %qT",
+ type, type1, type2);
+ warning (OPT_Wsign_promo, " in call to %qD", w->fn);
}
else
add_warning (w, l);
tree source = source_type (w->convs[0]);
if (! DECL_CONSTRUCTOR_P (w->fn))
source = TREE_TYPE (source);
- warning (0, "choosing %qD over %qD", w->fn, l->fn);
- warning (0, " for conversion from %qT to %qT",
+ warning (OPT_Wconversion, "choosing %qD over %qD", w->fn, l->fn);
+ warning (OPT_Wconversion, " for conversion from %qT to %qT",
source, w->second_conv->type);
- warning (0, " because conversion sequence for the argument is better");
+ inform (" because conversion sequence for the argument is better");
}
else
add_warning (w, l);
{
champ = challenger->next;
if (champ == 0)
- return 0;
+ return NULL;
champ_compared_to_predecessor = 0;
}
else
{
fate = joust (champ, challenger, 0);
if (fate != 1)
- return 0;
+ return NULL;
}
return champ;
error ("could not convert %qE to %qT", expr, type);
expr = error_mark_node;
}
+ else if (processing_template_decl)
+ {
+ /* In a template, we are only concerned about determining the
+ type of non-dependent expressions, so we do not have to
+ perform the actual conversion. */
+ if (TREE_TYPE (expr) != type)
+ expr = build_nop (type, expr);
+ }
else
expr = convert_like (conv, expr);