/* Functions related to invoking methods and overloaded functions.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
#include "flags.h"
#include "rtl.h"
#include "toplev.h"
-#include "defaults.h"
#include "expr.h"
#include "ggc.h"
+#include "diagnostic.h"
extern int inhibit_warnings;
static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PARAMS ((tree, tree));
static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
-#define convert_like(CONV, EXPR) convert_like_real (CONV, EXPR, NULL_TREE, 0, 0)
-#define convert_like_with_context(CONV, EXPR, FN, ARGNO) convert_like_real (CONV, EXPR, FN, ARGNO, 0)
+static tree build_java_interface_fn_ref PARAMS ((tree, tree));
+#define convert_like(CONV, EXPR) \
+ convert_like_real ((CONV), (EXPR), NULL_TREE, 0, 0)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO) \
+ convert_like_real ((CONV), (EXPR), (FN), (ARGNO), 0)
static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
tree, const char *));
static tree build_this PARAMS ((tree));
static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
static int any_viable PARAMS ((struct z_candidate *));
+static int any_strictly_viable PARAMS ((struct z_candidate *));
static struct z_candidate * add_template_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
unification_kind_t));
static tree non_reference PARAMS ((tree));
static tree build_conv PARAMS ((enum tree_code, tree, tree));
static int is_subseq PARAMS ((tree, tree));
-static int maybe_handle_ref_bind PARAMS ((tree*, tree*));
+static tree maybe_handle_ref_bind PARAMS ((tree*));
static void maybe_handle_implicit_object PARAMS ((tree*));
static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
tree, tree, int));
{
/* If it's a field, try overloading operator (),
or calling if the field is a pointer-to-function. */
- instance = build_indirect_ref (instance_ptr, NULL_PTR);
+ instance = build_indirect_ref (instance_ptr, NULL);
instance = build_component_ref_1 (instance, field, 0);
if (instance == error_mark_node)
if (IS_AGGR_TYPE (TREE_TYPE (instance)))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
instance, parms, NULL_TREE);
- else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE)
- {
- if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE)
- return build_function_call (instance, parms);
- else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
- == METHOD_TYPE)
- return build_function_call
- (instance, tree_cons (NULL_TREE, instance_ptr, parms));
- }
+ else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
+ || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
+ && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
+ == FUNCTION_TYPE)))
+ return build_function_call (instance, parms);
}
return NULL_TREE;
else
name = get_type_value (name);
}
+ /* In the case of:
+
+ template <class T> struct S { ~S(); };
+ int i;
+ i.~S();
+
+ NAME will be a class template. */
+ else if (DECL_CLASS_TEMPLATE_P (name))
+ return 0;
else
- my_friendly_abort (980605);
+ abort ();
if (name && TYPE_MAIN_VARIANT (basetype) == TYPE_MAIN_VARIANT (name))
return 1;
return build_method_call (exp, name, parms, NULL_TREE, LOOKUP_NORMAL);
if (! check_dtor_name (basetype, name))
- cp_error ("qualified type `%T' does not match destructor name `~%T'",
+ error ("qualified type `%T' does not match destructor name `~%T'",
basetype, TREE_OPERAND (name, 0));
/* Destructors can be "called" for simple types; see 5.2.4 and 12.4 Note
if (! IS_AGGR_TYPE (basetype))
{
if (TYPE_MAIN_VARIANT (type) != TYPE_MAIN_VARIANT (basetype))
- cp_error ("type of `%E' does not match destructor type `%T' (type was `%T')",
+ error ("type of `%E' does not match destructor type `%T' (type was `%T')",
exp, basetype, type);
return cp_convert (void_type_node, exp);
if (TREE_CODE (basetype) == NAMESPACE_DECL)
{
- cp_error ("`%D' is a namespace", basetype);
+ error ("`%D' is a namespace", basetype);
return error_mark_node;
}
if (! is_aggr_type (basetype, 1))
if (! IS_AGGR_TYPE (type))
{
- cp_error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
+ error ("base object `%E' of scoped method call is of non-aggregate type `%T'",
exp, type);
return error_mark_node;
}
- if (! binfo)
- {
- binfo = get_binfo (basetype, type, 1);
- if (binfo == error_mark_node)
- return error_mark_node;
- if (! binfo)
- error_not_base_type (basetype, type);
- }
+ decl = build_scoped_ref (exp, basetype, &binfo);
if (binfo)
{
- if (TREE_CODE (exp) == INDIRECT_REF)
- decl = build_indirect_ref
- (convert_pointer_to_real
- (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL_PTR);
- else
- decl = build_scoped_ref (exp, basetype);
-
/* Call to a destructor. */
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
type = build_pointer_type (type);
- if (mark_addressable (function) == 0)
+ if (!cxx_mark_addressable (function))
return error_mark_node;
addr = build1 (ADDR_EXPR, type, function);
throw without being declared throw(). */
nothrow = ((decl && TREE_NOTHROW (decl))
|| TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
-
+
+ if (decl && TREE_THIS_VOLATILE (decl))
+ current_function_returns_abnormally = 1;
+
+ if (decl && TREE_DEPRECATED (decl))
+ warn_deprecated_use (decl);
+
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
|| !strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "__", 2))
mark_used (decl);
else
- my_friendly_abort (990125);
+ abort ();
}
/* Don't pass empty class objects by value. This is useful
basetype = TREE_TYPE (basetype);
if (! check_dtor_name (basetype, name))
- cp_error
+ error
("destructor name `~%T' does not match type `%T' of expression",
TREE_OPERAND (name, 0), basetype);
/* New overloading code. */
-struct z_candidate {
+struct z_candidate GTY(()) {
tree fn;
tree convs;
tree second_conv;
#define BAD_RANK 7
#define ICS_RANK(NODE) \
- (ICS_BAD_FLAG (NODE) ? BAD_RANK \
+ (ICS_BAD_FLAG (NODE) ? BAD_RANK \
: ICS_ELLIPSIS_FLAG (NODE) ? ELLIPSIS_RANK \
: ICS_USER_FLAG (NODE) ? USER_RANK \
: ICS_STD_RANK (NODE))
/* In a REF_BIND or a BASE_CONV, this indicates that a temporary
should be created to hold the result of the conversion. */
-#define NEED_TEMPORARY_P(NODE) (TREE_LANG_FLAG_4 ((NODE)))
+#define NEED_TEMPORARY_P(NODE) TREE_LANG_FLAG_4 (NODE)
-#define USER_CONV_CAND(NODE) \
- ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
+#define USER_CONV_CAND(NODE) WRAPPER_ZC (TREE_OPERAND (NODE, 1))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
int
return 0;
}
+
+/* Returns non-zero if PARMLIST consists of only default parms and/or
+ ellipsis. */
+
+int
+sufficient_parms_p (parmlist)
+ tree parmlist;
+{
+ for (; parmlist && parmlist != void_list_node;
+ parmlist = TREE_CHAIN (parmlist))
+ if (!TREE_PURPOSE (parmlist))
+ return 0;
+ return 1;
+}
+
static tree
build_conv (code, type, from)
enum tree_code code;
tree type, from;
{
- tree t = build1 (code, type, from);
+ tree t;
int rank = ICS_STD_RANK (from);
+
+ /* We can't use buildl1 here because CODE could be USER_CONV, which
+ takes two arguments. In that case, the caller is responsible for
+ filling in the second argument. */
+ t = make_node (code);
+ TREE_TYPE (t) = type;
+ TREE_OPERAND (t, 0) = from;
+
switch (code)
{
case PTR_CONV:
return t;
}
+/* If T is a REFERENCE_TYPE return the type to which T refers.
+ Otherwise, return T itself. */
+
static tree
non_reference (t)
tree t;
if ((TYPE_PTRFN_P (to) || TYPE_PTRMEMFUNC_P (to))
&& expr && type_unknown_p (expr))
{
- expr = instantiate_type (to, expr, itf_none);
+ expr = instantiate_type (to, expr, tf_none);
if (expr == error_mark_node)
return NULL_TREE;
from = TREE_TYPE (expr);
{
conv = build_conv (STD_CONV, to, conv);
}
+ else if ((tcode == INTEGER_TYPE && fcode == POINTER_TYPE)
+ || (tcode == POINTER_TYPE && fcode == INTEGER_TYPE))
+ {
+ /* For backwards brain damage compatibility, allow interconversion of
+ pointers and integers with a pedwarn. */
+ conv = build_conv (STD_CONV, to, conv);
+ ICS_BAD_FLAG (conv) = 1;
+ }
+ else if (tcode == ENUMERAL_TYPE && fcode == INTEGER_TYPE
+ && TYPE_PRECISION (to) == TYPE_PRECISION (from))
+ {
+ /* For backwards brain damage compatibility, allow interconversion of
+ enums and integers with a pedwarn. */
+ conv = build_conv (STD_CONV, to, conv);
+ ICS_BAD_FLAG (conv) = 1;
+ }
else if (tcode == POINTER_TYPE && fcode == POINTER_TYPE)
{
enum tree_code ufcode = TREE_CODE (TREE_TYPE (from));
{
from = build_pointer_type
(cp_build_qualified_type (void_type_node,
- CP_TYPE_QUALS (TREE_TYPE (from))));
+ cp_type_quals (TREE_TYPE (from))));
conv = build_conv (PTR_CONV, from, conv);
}
else if (ufcode == OFFSET_TYPE && utcode == OFFSET_TYPE)
{
from =
cp_build_qualified_type (TREE_TYPE (to),
- CP_TYPE_QUALS (TREE_TYPE (from)));
+ cp_type_quals (TREE_TYPE (from)));
from = build_pointer_type (from);
conv = build_conv (PTR_CONV, from, conv);
}
tree fbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fromfn)));
tree tbase = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (tofn)));
- if (! DERIVED_FROM_P (fbase, tbase)
- || ! same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
- || ! compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
- TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
- || CP_TYPE_QUALS (fbase) != CP_TYPE_QUALS (tbase))
+ if (!DERIVED_FROM_P (fbase, tbase)
+ || !same_type_p (TREE_TYPE (fromfn), TREE_TYPE (tofn))
+ || !compparms (TREE_CHAIN (TYPE_ARG_TYPES (fromfn)),
+ TREE_CHAIN (TYPE_ARG_TYPES (tofn)))
+ || cp_type_quals (fbase) != cp_type_quals (tbase))
return 0;
- from = cp_build_qualified_type (tbase, CP_TYPE_QUALS (fbase));
+ from = cp_build_qualified_type (tbase, cp_type_quals (fbase));
from = build_cplus_method_type (from, TREE_TYPE (fromfn),
TREE_CHAIN (TYPE_ARG_TYPES (fromfn)));
from = build_ptrmemfunc_type (build_pointer_type (from));
return NULL_TREE;
conv = build1 (IDENTITY_CONV, s, expr);
- conv = build_conv (USER_CONV,
- non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
+ conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
conv);
- TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
+ TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
ICS_USER_FLAG (conv) = 1;
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{
- expr = instantiate_type (to, expr, itf_none);
+ expr = instantiate_type (to, expr, tf_none);
if (expr == error_mark_node)
return NULL_TREE;
from = TREE_TYPE (expr);
{
/* [dcl.init.ref]
- If the intializer expression
+ If the initializer expression
-- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
is reference-compatible with "cv2 T2,"
if (conv)
;
else if (expr != NULL_TREE
- && (IS_AGGR_TYPE (non_reference (from))
- || IS_AGGR_TYPE (non_reference (to)))
+ && (IS_AGGR_TYPE (from)
+ || IS_AGGR_TYPE (to))
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
cand = build_user_type_conversion_1
(to, expr, LOOKUP_ONLYCONVERTING);
if (cand)
conv = cand->second_conv;
- if ((! conv || ICS_BAD_FLAG (conv))
- && TREE_CODE (to) == REFERENCE_TYPE
- && (flags & LOOKUP_NO_TEMP_BIND) == 0)
- {
- cand = build_user_type_conversion_1
- (TYPE_MAIN_VARIANT (TREE_TYPE (to)), expr, LOOKUP_ONLYCONVERTING);
- if (cand)
- {
- if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (to)))
- ICS_BAD_FLAG (cand->second_conv) = 1;
- if (!conv || (ICS_BAD_FLAG (conv)
- > ICS_BAD_FLAG (cand->second_conv)))
- conv = build_conv (REF_BIND, to, cand->second_conv);
- }
- }
+
+ /* We used to try to bind a reference to a temporary here, but that
+ is now handled by the recursive call to this function at the end
+ of reference_binding. */
}
return conv;
tree parmnode, argnode;
int viable = 1;
- /* The `this' and `in_chrg' arguments to constructors are not considered
- in overload resolution. */
+ /* The `this', `in_chrg' and VTT arguments to constructors are not
+ considered in overload resolution. */
if (DECL_CONSTRUCTOR_P (fn))
{
- parmlist = TREE_CHAIN (parmlist);
- arglist = TREE_CHAIN (arglist);
- if (DECL_HAS_IN_CHARGE_PARM_P (fn))
- {
- parmlist = TREE_CHAIN (parmlist);
- arglist = TREE_CHAIN (arglist);
- }
+ parmlist = skip_artificial_parms_for (fn, parmlist);
+ arglist = skip_artificial_parms_for (fn, arglist);
}
len = list_length (arglist);
viable = 0;
/* Make sure there are default args for the rest of the parms. */
- else for (; parmnode && parmnode != void_list_node;
- parmnode = TREE_CHAIN (parmnode))
- if (! TREE_PURPOSE (parmnode))
- {
- viable = 0;
- break;
- }
+ else if (!sufficient_parms_p (parmnode))
+ viable = 0;
if (! viable)
goto out;
tree fn, obj, arglist;
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
- tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype));
- int i, len = list_length (arglist) + 1;
- tree convs = make_tree_vec (len);
- tree parmnode = parmlist;
- tree argnode = arglist;
- int viable = 1;
- int flags = LOOKUP_NORMAL;
+ int i, len, viable, flags;
+ tree parmlist, convs, parmnode, argnode;
+
+ for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
+ parmlist = TREE_TYPE (parmlist);
+ parmlist = TYPE_ARG_TYPES (parmlist);
+
+ len = list_length (arglist) + 1;
+ convs = make_tree_vec (len);
+ parmnode = parmlist;
+ argnode = arglist;
+ viable = 1;
+ flags = LOOKUP_NORMAL;
/* Don't bother looking up the same type twice. */
if (candidates && candidates->fn == totype)
if (i < len)
viable = 0;
- for (; parmnode && parmnode != void_list_node;
- parmnode = TREE_CHAIN (parmnode))
- if (! TREE_PURPOSE (parmnode))
- {
- viable = 0;
- break;
- }
+ if (!sufficient_parms_p (parmnode))
+ viable = 0;
return add_candidate (candidates, totype, convs, viable);
}
/* Create any builtin operator overload candidates for the operator in
question given the converted operand types TYPE1 and TYPE2. The other
args are passed through from add_builtin_candidates to
- build_builtin_candidate. */
+ build_builtin_candidate.
+
+ TYPE1 and TYPE2 may not be permissible, and we must filter them.
+ If CODE is requires candidates operands of the same type of the kind
+ of which TYPE1 and TYPE2 are, we add both candidates
+ CODE (TYPE1, TYPE1) and CODE (TYPE2, TYPE2). */
static struct z_candidate *
add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
return candidates;
case POSTINCREMENT_EXPR:
case PREINCREMENT_EXPR:
- if ((ARITHMETIC_TYPE_P (type1) && TREE_CODE (type1) != ENUMERAL_TYPE)
- || TYPE_PTROB_P (type1))
+ if (ARITHMETIC_TYPE_P (type1) || TYPE_PTROB_P (type1))
{
type1 = build_reference_type (type1);
break;
candidate operator functions of the form112)
ptrdiff_t operator-(T, T);
- 16For every pointer type T, there exist candidate operator functions of
- the form
+ 16For every pointer or enumeration type T, there exist candidate operator
+ functions of the form
bool operator<(T, T);
bool operator>(T, T);
bool operator<=(T, T);
type1 = type2;
break;
}
+ /* FALLTHROUGH */
case LT_EXPR:
case GT_EXPR:
case LE_EXPR:
case GE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
- if ((ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
- || (TYPE_PTR_P (type1) && TYPE_PTR_P (type2)))
+ if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
+ break;
+ if (TYPE_PTR_P (type1) && TYPE_PTR_P (type2))
break;
+ if (TREE_CODE (type1) == ENUMERAL_TYPE && TREE_CODE (type2) == ENUMERAL_TYPE)
+ break;
if (TYPE_PTR_P (type1) && null_ptr_cst_p (args[1]))
{
type2 = type1;
return candidates;
default:
- my_friendly_abort (367);
+ abort ();
}
type1 = build_reference_type (type1);
break;
case COND_EXPR:
- /* [over.builtin]
+ /* [over.built]
For every pair of promoted arithmetic types L and R, there
exist candidate operator functions of the form
return candidates;
default:
- my_friendly_abort (367);
+ abort ();
}
- /* If we're dealing with two pointer types, we need candidates
- for both of them. */
+ /* If we're dealing with two pointer types or two enumeral types,
+ we need candidates for both of them. */
if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
|| (TREE_CODE (type1) == POINTER_TYPE
&& TYPE_PTRMEM_P (type1) == TYPE_PTRMEM_P (type2))
|| TYPE_PTRMEMFUNC_P (type1)
- || IS_AGGR_TYPE (type1)))
+ || IS_AGGR_TYPE (type1)
+ || TREE_CODE (type1) == ENUMERAL_TYPE))
{
candidates = build_builtin_candidate
(candidates, fnname, type1, type1, args, argtypes, flags);
2) pointer-pair taking candidates. These are generated for each type
one of the input types converts to.
3) arithmetic candidates. According to the standard, we should generate
- all of these, but I'm trying not to... */
+ all of these, but I'm trying not to...
+
+ Here we generate a superset of the possible candidates for this particular
+ case. That is a subset of the full set the standard defines, plus some
+ other cases which the standard disallows. add_builtin_candidate will
+ filter out the illegal set. */
static struct z_candidate *
add_builtin_candidates (candidates, code, code2, fnname, args, flags)
int flags;
{
int ref1, i;
+ int enum_p = 0;
tree type, argtypes[3];
/* TYPES[i] is the set of possible builtin-operator parameter types
we will consider for the Ith argument. These are represented as
case COMPONENT_REF:
return candidates;
+ case COND_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ enum_p = 1;
+ /* FALLTHROUGH */
+
default:
ref1 = 0;
}
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+ types[i] = tree_cons (NULL_TREE, type, types[i]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- if (code == COND_EXPR && TREE_CODE (type) == ENUMERAL_TYPE)
- types[i] = tree_cons (NULL_TREE, type, types[i]);
+ if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+ types[i] = tree_cons (NULL_TREE, type, types[i]);
if (INTEGRAL_TYPE_P (type))
type = type_promotes_to (type);
}
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
- tree args_without_in_chrg;
+ tree args_without_in_chrg = arglist;
struct z_candidate *cand;
int i;
tree fn;
- /* TEMPLATE_DECLs do not have the in-charge parameter, nor the VTT
- parameter. So, skip it here before attempting to perform
- argument deduction. */
+ /* We don't do deduction on the in-charge parameter, the VTT
+ parameter or 'this'. */
+ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
+ args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+
if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
|| DECL_BASE_CONSTRUCTOR_P (tmpl))
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (tmpl)))
- args_without_in_chrg = tree_cons (NULL_TREE,
- TREE_VALUE (arglist),
- TREE_CHAIN (TREE_CHAIN (arglist)));
- else
- args_without_in_chrg = arglist;
+ args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
- return_type, strict);
+ return_type, strict, -1);
if (i != 0)
return candidates;
if (fn == error_mark_node)
return candidates;
+ /* In [class.copy]:
+
+ A member function template is never instantiated to perform the
+ copy of a class object to an object of its class type.
+
+ It's a little unclear what this means; the standard explicitly
+ does allow a template to be used to copy a class. For example,
+ in:
+
+ struct A {
+ A(A&);
+ template <class T> A(const T&);
+ };
+ const A f ();
+ void g () { A a (f ()); }
+
+ the member template will be used to make the copy. The section
+ quoted above appears in the paragraph that forbids constructors
+ whose only parameter is (a possibly cv-qualified variant of) the
+ class type, and a logical interpretation is that the intent was
+ to forbid the instantiation of member templates which would then
+ have that form. */
+ if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2)
+ {
+ tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
+ if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
+ ctype))
+ return candidates;
+ }
+
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
cand = add_conv_candidate (candidates, fn, obj, arglist);
return 0;
}
+static int
+any_strictly_viable (cands)
+ struct z_candidate *cands;
+{
+ for (; cands; cands = cands->next)
+ if (cands->viable == 1)
+ return 1;
+ return 0;
+}
+
static struct z_candidate *
splice_viable (cands)
struct z_candidate *cands;
if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
{
if (TREE_VEC_LENGTH (candidates->convs) == 3)
- cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
+ error ("%s %D(%T, %T, %T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
else if (TREE_VEC_LENGTH (candidates->convs) == 2)
- cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn,
+ error ("%s %D(%T, %T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
else
- cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
+ error ("%s %D(%T) <built-in>", str, candidates->fn,
TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
}
else if (TYPE_P (candidates->fn))
- cp_error ("%s %T <conversion>", str, candidates->fn);
+ error ("%s %T <conversion>", str, candidates->fn);
else
cp_error_at ("%s %+#D%s", str, candidates->fn,
candidates->viable == -1 ? " <near match>" : "");
tree args = NULL_TREE;
tree templates = NULL_TREE;
+ /* We represent conversion within a hierarchy using RVALUE_CONV and
+ BASE_CONV, as specified by [over.best.ics]; these become plain
+ constructor calls, as specified in [dcl.init]. */
+ my_friendly_assert (!IS_AGGR_TYPE (fromtype) || !IS_AGGR_TYPE (totype)
+ || !DERIVED_FROM_P (totype, fromtype), 20011226);
+
if (IS_AGGR_TYPE (totype))
ctors = lookup_fnfields (TYPE_BINFO (totype),
- (flag_new_abi
- ? complete_ctor_identifier
- : ctor_identifier),
+ complete_ctor_identifier,
0);
- if (IS_AGGR_TYPE (fromtype)
- && (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
+ if (IS_AGGR_TYPE (fromtype))
convs = lookup_conversions (fromtype);
candidates = 0;
t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
args = build_tree_list (NULL_TREE, expr);
- if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)))
- args = tree_cons (NULL_TREE,
- in_charge_arg_for_name (complete_ctor_identifier),
- args);
+ /* We should never try to call the abstract or base constructor
+ from here. */
+ my_friendly_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
+ && !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)),
+ 20011226);
args = tree_cons (NULL_TREE, t, args);
}
for (; ctors; ctors = OVL_NEXT (ctors))
{
tree fns = TREE_VALUE (convs);
int convflags = LOOKUP_NO_CONVERSION;
- tree ics;
/* If we are called to convert to a reference type, we are trying to
find an lvalue binding, so don't even consider temporaries. If
look for a temporary binding. */
if (TREE_CODE (totype) == REFERENCE_TYPE)
convflags |= LOOKUP_NO_TEMP_BIND;
+
+ for (; fns; fns = OVL_NEXT (fns))
+ {
+ tree fn = OVL_CURRENT (fns);
+ struct z_candidate *old_candidates = candidates;
+
+ /* [over.match.funcs] For conversion functions, the function
+ is considered to be a member of the class of the implicit
+ object argument for the purpose of defining the type of
+ the implicit object parameter.
- if (TREE_CODE (OVL_CURRENT (fns)) != TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))), 0, convflags);
- else
- /* We can't compute this yet. */
- ics = error_mark_node;
-
- if (TREE_CODE (totype) == REFERENCE_TYPE && ics && ICS_BAD_FLAG (ics))
- /* ignore the near match. */;
- else if (ics)
- for (; fns; fns = OVL_NEXT (fns))
- {
- tree fn = OVL_CURRENT (fns);
- struct z_candidate *old_candidates = candidates;
-
- /* [over.match.funcs] For conversion functions, the function is
- considered to be a member of the class of the implicit object
- argument for the purpose of defining the type of the implicit
- object parameter.
+ So we pass fromtype as CTYPE to add_*_candidate. */
- So we pass fromtype as CTYPE to add_*_candidate. */
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ {
+ templates = tree_cons (NULL_TREE, fn, templates);
+ candidates =
+ add_template_candidate (candidates, fn, fromtype, NULL_TREE,
+ args, totype, flags,
+ DEDUCE_CONV);
+ }
+ else
+ candidates = add_function_candidate (candidates, fn, fromtype,
+ args, flags);
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- {
- templates = tree_cons (NULL_TREE, fn, templates);
- candidates =
- add_template_candidate (candidates, fn, fromtype, NULL_TREE,
- args, totype, flags,
- DEDUCE_CONV);
- }
- else
- candidates = add_function_candidate (candidates, fn, fromtype,
- args, flags);
+ if (candidates != old_candidates)
+ {
+ tree ics = implicit_conversion
+ (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
+ 0, convflags);
- if (candidates != old_candidates)
- {
- if (TREE_CODE (fn) == TEMPLATE_DECL)
- ics = implicit_conversion
- (totype, TREE_TYPE (TREE_TYPE (candidates->fn)),
- 0, convflags);
-
- candidates->second_conv = ics;
- candidates->basetype_path = TYPE_BINFO (fromtype);
-
- if (ics == NULL_TREE)
- candidates->viable = 0;
- else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
- candidates->viable = -1;
- }
- }
+ candidates->second_conv = ics;
+ candidates->basetype_path = TYPE_BINFO (fromtype);
+
+ if (ics == NULL_TREE)
+ candidates->viable = 0;
+ else if (candidates->viable == 1 && ICS_BAD_FLAG (ics))
+ candidates->viable = -1;
+ }
+ }
}
if (! any_viable (candidates))
if (candidates && ! candidates->next)
/* say why this one won't work or try to be loose */;
else
- cp_error ("no viable candidates");
+ error ("no viable candidates");
}
#endif
{
if (flags & LOOKUP_COMPLAIN)
{
- cp_error ("conversion from `%T' to `%T' is ambiguous",
+ error ("conversion from `%T' to `%T' is ambiguous",
fromtype, totype);
print_z_candidates (candidates);
}
(USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn)
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
- expr, build_expr_ptr_wrapper (cand));
- ICS_USER_FLAG (cand->second_conv) = 1;
+ expr, build_zc_wrapper (cand));
+
+ ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
if (cand->viable == -1)
- ICS_BAD_FLAG (cand->second_conv) = 1;
+ ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1;
return cand;
}
{
if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node;
- return convert_from_reference
- (convert_like_with_context
- (cand->second_conv, expr, cand->fn, 0));
+ return convert_from_reference (convert_like (cand->second_conv, expr));
}
return NULL_TREE;
}
tree t;
for (t = args; t; t = TREE_CHAIN (t))
{
- if (TREE_VALUE (t) == error_mark_node)
+ tree arg = TREE_VALUE (t);
+
+ if (arg == error_mark_node)
return error_mark_node;
- else if (TREE_CODE (TREE_TYPE (TREE_VALUE (t))) == VOID_TYPE)
+ else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
error ("invalid use of void expression");
return error_mark_node;
}
- else if (TREE_CODE (TREE_VALUE (t)) == OFFSET_REF)
- TREE_VALUE (t) = resolve_offset_ref (TREE_VALUE (t));
+ else if (TREE_CODE (arg) == OFFSET_REF)
+ arg = resolve_offset_ref (arg);
+ arg = convert_from_reference (arg);
+ TREE_VALUE (t) = arg;
}
return args;
}
{
if (candidates && ! candidates->next)
return build_function_call (candidates->fn, args);
- cp_error ("no matching function for call to `%D (%A)'",
+ error ("no matching function for call to `%D(%A)'",
DECL_NAME (OVL_FUNCTION (fn)), args);
if (candidates)
print_z_candidates (candidates);
if (cand == 0)
{
- cp_error ("call of overloaded `%D (%A)' is ambiguous",
+ error ("call of overloaded `%D(%A)' is ambiguous",
DECL_NAME (OVL_FUNCTION (fn)), args);
print_z_candidates (candidates);
return error_mark_node;
{
/* It's no good looking for an overloaded operator() on a
pointer-to-member-function. */
- cp_error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
+ error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
return error_mark_node;
}
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
if ((TREE_CODE (totype) == POINTER_TYPE
- || TREE_CODE (totype) == REFERENCE_TYPE)
- && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+ && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+ || (TREE_CODE (totype) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
+ || (TREE_CODE (totype) == REFERENCE_TYPE
+ && TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE
+ && TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE))
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (! any_viable (candidates))
{
- cp_error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
+ error ("no match for call to `(%T) (%A)'", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
if (cand == 0)
{
- cp_error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
+ error ("call of `(%T) (%A)' is ambiguous", TREE_TYPE (obj), args);
print_z_candidates (candidates);
return error_mark_node;
}
tree arg1, arg2, arg3;
const char *problem;
{
- const char * opname;
+ const char *opname;
if (code == MODIFY_EXPR)
opname = assignment_operator_name_info[code2].name;
switch (code)
{
case COND_EXPR:
- cp_error ("%s for `%T ? %T : %T'", problem,
+ error ("%s for `%T ? %T : %T' operator", problem,
error_type (arg1), error_type (arg2), error_type (arg3));
break;
case POSTINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
- cp_error ("%s for `%T%s'", problem, error_type (arg1), opname);
+ error ("%s for `%T %s' operator", problem, error_type (arg1), opname);
break;
case ARRAY_REF:
- cp_error ("%s for `%T[%T]'", problem,
+ error ("%s for `%T [%T]' operator", problem,
error_type (arg1), error_type (arg2));
break;
default:
if (arg2)
- cp_error ("%s for `%T %s %T'", problem,
+ error ("%s for `%T %s %T' operator", problem,
error_type (arg1), opname, error_type (arg2));
else
- cp_error ("%s for `%s%T'", problem, opname, error_type (arg1));
+ error ("%s for `%s %T' operator", problem, opname, error_type (arg1));
}
}
|| TREE_TYPE (arg3) == error_mark_node)
return error_mark_node;
- /* Convert from reference types to ordinary types; no expressions
- really have reference type in C++. */
- arg2 = convert_from_reference (arg2);
- arg3 = convert_from_reference (arg3);
-
/* [expr.cond]
If either the second or the third operand has type (possibly
result_type = void_type_node;
else
{
- cp_error ("`%E' has type `void' and is not a throw-expression",
+ error ("`%E' has type `void' and is not a throw-expression",
VOID_TYPE_P (arg2_type) ? arg2 : arg3);
return error_mark_node;
}
|| (conv2 && TREE_CODE (conv2) == AMBIG_CONV)
|| (conv3 && TREE_CODE (conv3) == AMBIG_CONV))
{
- cp_error ("operands to ?: have different types");
+ error ("operands to ?: have different types");
return error_mark_node;
}
else if (conv2 && !ICS_BAD_FLAG (conv2))
arg3 = decay_conversion (arg3);
arg3_type = TREE_TYPE (arg3);
+ if (arg2 == error_mark_node || arg3 == error_mark_node)
+ return error_mark_node;
+
/* [expr.cond]
After those conversions, one of the following shall hold:
if (TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& TREE_CODE (arg3_type) == ENUMERAL_TYPE)
- cp_warning ("enumeral mismatch in conditional expression: `%T' vs `%T'",
+ warning ("enumeral mismatch in conditional expression: `%T' vs `%T'",
arg2_type, arg3_type);
else if (extra_warnings
&& ((TREE_CODE (arg2_type) == ENUMERAL_TYPE
&& !same_type_p (arg3_type, type_promotes_to (arg2_type)))
|| (TREE_CODE (arg3_type) == ENUMERAL_TYPE
&& !same_type_p (arg2_type, type_promotes_to (arg3_type)))))
- cp_warning ("enumeral and non-enumeral type in conditional expression");
+ warning ("enumeral and non-enumeral type in conditional expression");
arg2 = perform_implicit_conversion (result_type, arg2);
arg3 = perform_implicit_conversion (result_type, arg3);
if (!result_type)
{
- cp_error ("operands to ?: have different types");
+ error ("operands to ?: have different types");
return error_mark_node;
}
enum tree_code code2 = NOP_EXPR;
tree templates = NULL_TREE;
tree conv;
+ bool viable_candidates;
if (arg1 == error_mark_node
|| arg2 == error_mark_node
undeclared_template<1, 5, 72>a; */
if (code == LT_EXPR && TREE_CODE (arg1) == TEMPLATE_DECL)
{
- cp_error ("`%D' must be declared before use", arg1);
+ error ("`%D' must be declared before use", arg1);
return error_mark_node;
}
else
fnname = ansi_opname (code);
+ if (TREE_CODE (arg1) == OFFSET_REF)
+ arg1 = resolve_offset_ref (arg1);
+ arg1 = convert_from_reference (arg1);
+
switch (code)
{
case NEW_EXPR:
case VEC_DELETE_EXPR:
case DELETE_EXPR:
/* Use build_op_new_call and build_op_delete_call instead. */
- my_friendly_abort (981018);
+ abort ();
case CALL_EXPR:
return build_object_call (arg1, arg2);
break;
}
- /* The comma operator can have void args. */
- if (TREE_CODE (arg1) == OFFSET_REF)
- arg1 = resolve_offset_ref (arg1);
- if (arg2 && TREE_CODE (arg2) == OFFSET_REF)
- arg2 = resolve_offset_ref (arg2);
- if (arg3 && TREE_CODE (arg3) == OFFSET_REF)
- arg3 = resolve_offset_ref (arg3);
-
+ if (arg2)
+ {
+ if (TREE_CODE (arg2) == OFFSET_REF)
+ arg2 = resolve_offset_ref (arg2);
+ arg2 = convert_from_reference (arg2);
+ }
+ if (arg3)
+ {
+ if (TREE_CODE (arg3) == OFFSET_REF)
+ arg3 = resolve_offset_ref (arg3);
+ arg3 = convert_from_reference (arg3);
+ }
+
if (code == COND_EXPR)
{
if (arg2 == NULL_TREE
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
arg2 = integer_zero_node;
- if (arg2 && arg3)
- arglist = tree_cons (NULL_TREE, arg1, tree_cons
- (NULL_TREE, arg2, build_tree_list (NULL_TREE, arg3)));
- else if (arg2)
- arglist = tree_cons (NULL_TREE, arg1, build_tree_list (NULL_TREE, arg2));
- else
- arglist = build_tree_list (NULL_TREE, arg1);
+ arglist = NULL_TREE;
+ if (arg3)
+ arglist = tree_cons (NULL_TREE, arg3, arglist);
+ if (arg2)
+ arglist = tree_cons (NULL_TREE, arg2, arglist);
+ arglist = tree_cons (NULL_TREE, arg1, arglist);
fns = lookup_function_nonclass (fnname, arglist);
(candidates, code, code2, fnname, args, flags);
}
- if (! any_viable (candidates))
+ switch (code)
+ {
+ case COMPOUND_EXPR:
+ case ADDR_EXPR:
+ /* For these, the built-in candidates set is empty
+ [over.match.oper]/3. We don't want non-strict matches
+ because exact matches are always possible with built-in
+ operators. The built-in candidate set for COMPONENT_REF
+ would be empty too, but since there are no such built-in
+ operators, we accept non-strict matches for them. */
+ viable_candidates = any_strictly_viable (candidates);
+ break;
+
+ default:
+ viable_candidates = any_viable (candidates);
+ break;
+ }
+
+ if (! viable_candidates)
{
switch (code)
{
/* Look for an `operator++ (int)'. If they didn't have
one, then we fall back to the old way of doing things. */
if (flags & LOOKUP_COMPLAIN)
- cp_pedwarn ("no `%D (int)' declared for postfix `%s', trying prefix operator instead",
+ pedwarn ("no `%D(int)' declared for postfix `%s', trying prefix operator instead",
fnname,
operator_name_info[code].name);
if (code == POSTINCREMENT_EXPR)
&& candidates->next
&& ! candidates->next->next)
{
- cp_warning ("using synthesized `%#D' for copy assignment",
+ warning ("using synthesized `%#D' for copy assignment",
cand->fn);
cp_warning_at (" where cfront would use `%#D'",
cand == candidates
&& (TYPE_MAIN_VARIANT (TREE_TYPE (arg1))
!= TYPE_MAIN_VARIANT (TREE_TYPE (arg2))))
{
- cp_warning ("comparison between `%#T' and `%#T'",
+ warning ("comparison between `%#T' and `%#T'",
TREE_TYPE (arg1), TREE_TYPE (arg2));
}
break;
case MEMBER_REF:
return build_m_component_ref
- (build_indirect_ref (arg1, NULL_PTR), arg2);
+ (build_indirect_ref (arg1, NULL), arg2);
/* The caller will deal with these. */
case ADDR_EXPR:
return NULL_TREE;
default:
- my_friendly_abort (367);
+ abort ();
return NULL_TREE;
}
}
match with the placement new is accepted.
CODE is either DELETE_EXPR or VEC_DELETE_EXPR.
- ADDR is the pointer to be deleted. For placement delete, it is also
- used to determine what the corresponding new looked like.
+ ADDR is the pointer to be deleted.
SIZE is the size of the memory block to be deleted.
FLAGS are the usual overloading flags.
- PLACEMENT is the corresponding placement new call, or 0. */
+ PLACEMENT is the corresponding placement new call, or NULL_TREE. */
tree
build_op_delete_call (code, addr, size, flags, placement)
tree addr, size, placement;
int flags;
{
- tree fn, fns, fnname, fntype, argtypes, args, type;
+ tree fn = NULL_TREE;
+ tree fns, fnname, fntype, argtypes, args, type;
+ int pass;
if (addr == error_mark_node)
return error_mark_node;
type = TREE_TYPE (TREE_TYPE (addr));
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
fnname = ansi_opname (code);
if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL))
if (placement)
{
- /* placement is a CALL_EXPR around an ADDR_EXPR around a function. */
+ tree alloc_fn;
+ tree call_expr;
+ /* Find the allocation function that is being called. */
+ call_expr = placement;
+ /* Sometimes we have a COMPOUND_EXPR, rather than a simple
+ CALL_EXPR. */
+ while (TREE_CODE (call_expr) == COMPOUND_EXPR)
+ call_expr = TREE_OPERAND (call_expr, 1);
/* Extract the function. */
- argtypes = TREE_OPERAND (TREE_OPERAND (placement, 0), 0);
+ alloc_fn = get_callee_fndecl (call_expr);
+ my_friendly_assert (alloc_fn != NULL_TREE, 20020327);
/* Then the second parm type. */
- argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (argtypes)));
-
+ argtypes = TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (alloc_fn)));
/* Also the second argument. */
- args = TREE_CHAIN (TREE_OPERAND (placement, 1));
+ args = TREE_CHAIN (TREE_OPERAND (call_expr, 1));
}
else
{
args = NULL_TREE;
}
- argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
- fntype = build_function_type (void_type_node, argtypes);
-
/* Strip const and volatile from addr. */
- if (type != TYPE_MAIN_VARIANT (type))
- addr = cp_convert (build_pointer_type (TYPE_MAIN_VARIANT (type)), addr);
+ addr = cp_convert (ptr_type_node, addr);
- fn = instantiate_type (fntype, fns, itf_no_attributes);
-
- if (fn != error_mark_node)
+ /* We make two tries at finding a matching `operator delete'. On
+ the first pass, we look for an one-operator (or placement)
+ operator delete. If we're not doing placement delete, then on
+ the second pass we look for a two-argument delete. */
+ for (pass = 0; pass < (placement ? 1 : 2); ++pass)
{
- if (TREE_CODE (fns) == TREE_LIST)
- /* Member functions. */
- enforce_access (type, fn);
- return build_function_call (fn, tree_cons (NULL_TREE, addr, args));
+ if (pass == 0)
+ argtypes = tree_cons (NULL_TREE, ptr_type_node, argtypes);
+ else
+ /* Normal delete; now try to find a match including the size
+ argument. */
+ argtypes = tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, sizetype,
+ void_list_node));
+ fntype = build_function_type (void_type_node, argtypes);
+
+ /* Go through the `operator delete' functions looking for one
+ with a matching type. */
+ for (fn = BASELINK_P (fns) ? BASELINK_FUNCTIONS (fns) : fns;
+ fn;
+ fn = OVL_NEXT (fn))
+ {
+ tree t;
+
+ /* Exception specifications on the `delete' operator do not
+ matter. */
+ t = build_exception_variant (TREE_TYPE (OVL_CURRENT (fn)),
+ NULL_TREE);
+ /* We also don't compare attributes. We're really just
+ trying to check the types of the first two parameters. */
+ if (comptypes (t, fntype, COMPARE_NO_ATTRIBUTES))
+ break;
+ }
+
+ /* If we found a match, we're done. */
+ if (fn)
+ break;
}
- /* If we are doing placement delete we do nothing if we don't find a
- matching op delete. */
- if (placement)
- return NULL_TREE;
+ /* If we have a matching function, call it. */
+ if (fn)
+ {
+ /* Make sure we have the actual function, and not an
+ OVERLOAD. */
+ fn = OVL_CURRENT (fn);
- /* Normal delete; now try to find a match including the size argument. */
- argtypes = tree_cons (NULL_TREE, ptr_type_node,
- tree_cons (NULL_TREE, sizetype, void_list_node));
- fntype = build_function_type (void_type_node, argtypes);
+ /* If the FN is a member function, make sure that it is
+ accessible. */
+ if (DECL_CLASS_SCOPE_P (fn))
+ enforce_access (type, fn);
- fn = instantiate_type (fntype, fns, itf_no_attributes);
+ if (pass == 0)
+ args = tree_cons (NULL_TREE, addr, args);
+ else
+ args = tree_cons (NULL_TREE, addr,
+ build_tree_list (NULL_TREE, size));
- if (fn != error_mark_node)
- {
- if (BASELINK_P (fns))
- /* Member functions. */
- enforce_access (type, fn);
- return build_function_call
- (fn, tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, size)));
+ return build_function_call (fn, args);
}
- /* finish_function passes LOOKUP_SPECULATIVELY if we're in a
- destructor, in which case the error should be deferred
- until someone actually tries to delete one of these. */
- if (flags & LOOKUP_SPECULATIVELY)
+ /* If we are doing placement delete we do nothing if we don't find a
+ matching op delete. */
+ if (placement)
return NULL_TREE;
- cp_error ("no suitable `operator delete' for `%T'", type);
+ error ("no suitable `operator delete' for `%T'", type);
return error_mark_node;
}
cp_error_at ("`%+#D' is protected", decl);
else
cp_error_at ("`%+#D' is inaccessible", decl);
- cp_error ("within this context");
+ error ("within this context");
return 0;
}
/* Perform the conversions in CONVS on the expression EXPR.
FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1
indicates the `this' argument of a method. INNER is non-zero when
- being called to continue a conversion chain. */
+ being called to continue a conversion chain. It is negative when a
+ reference binding will be applied, positive otherwise. */
static tree
convert_like_real (convs, expr, fn, argnum, inner)
int argnum;
int inner;
{
+ int savew, savee;
+
+ tree totype = TREE_TYPE (convs);
+
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
&& TREE_CODE (convs) != AMBIG_CONV
tree t = convs;
for (; t; t = TREE_OPERAND (t, 0))
{
- if (TREE_CODE (t) == USER_CONV)
+ if (TREE_CODE (t) == USER_CONV || !ICS_BAD_FLAG (t))
{
expr = convert_like_real (t, expr, fn, argnum, 1);
break;
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
- return convert_for_initialization
- (NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
- "conversion", fn, argnum);
+ pedwarn ("invalid conversion from `%T' to `%T'", TREE_TYPE (expr), totype);
+ if (fn)
+ pedwarn (" initializing argument %P of `%D'", argnum, fn);
+ return cp_convert (totype, expr);
}
if (!inner)
expr = dubious_conversion_warnings
- (TREE_TYPE (convs), expr, "argument", fn, argnum);
+ (totype, expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
{
struct z_candidate *cand
- = WRAPPER_PTR (TREE_OPERAND (convs, 1));
- tree fn = cand->fn;
+ = WRAPPER_ZC (TREE_OPERAND (convs, 1));
+ tree convfn = cand->fn;
tree args;
- if (DECL_CONSTRUCTOR_P (fn))
+ if (DECL_CONSTRUCTOR_P (convfn))
{
tree t = build_int_2 (0, 0);
- TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
+ TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (convfn));
args = build_tree_list (NULL_TREE, expr);
- if (DECL_HAS_IN_CHARGE_PARM_P (fn))
- args = tree_cons (NULL_TREE, integer_one_node, args);
+ if (DECL_HAS_IN_CHARGE_PARM_P (convfn)
+ || DECL_HAS_VTT_PARM_P (convfn))
+ /* We should never try to call the abstract or base constructor
+ from here. */
+ abort ();
args = tree_cons (NULL_TREE, t, args);
}
else
/* If this is a constructor or a function returning an aggr type,
we need to build up a TARGET_EXPR. */
- if (DECL_CONSTRUCTOR_P (fn))
- expr = build_cplus_new (TREE_TYPE (convs), expr);
+ if (DECL_CONSTRUCTOR_P (convfn))
+ expr = build_cplus_new (totype, expr);
+
+ /* The result of the call is then used to direct-initialize the object
+ that is the destination of the copy-initialization. [dcl.init]
+
+ Note that this step is not reflected in the conversion sequence;
+ it affects the semantics when we actually perform the
+ conversion, but is not considered during overload resolution.
+ If the target is a class, that means call a ctor. */
+ if (IS_AGGR_TYPE (totype)
+ && (inner >= 0 || !lvalue_p (expr)))
+ {
+ savew = warningcount, savee = errorcount;
+ expr = build_new_method_call
+ (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr), TYPE_BINFO (totype),
+ /* Core issue 84, now a DR, says that we don't allow UDCs
+ for these args (which deliberately breaks copy-init of an
+ auto_ptr<Base> from an auto_ptr<Derived>). */
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING|LOOKUP_NO_CONVERSION);
+
+ /* Tell the user where this failing constructor call came from. */
+ if (fn)
+ {
+ if (warningcount > savew)
+ warning
+ (" initializing argument %P of `%D' from result of `%D'",
+ argnum, fn, convfn);
+ else if (errorcount > savee)
+ error
+ (" initializing argument %P of `%D' from result of `%D'",
+ argnum, fn, convfn);
+ }
+ else
+ {
+ if (warningcount > savew)
+ warning (" initializing temporary from result of `%D'",
+ convfn);
+ else if (errorcount > savee)
+ error (" initializing temporary from result of `%D'",
+ convfn);
+ }
+ expr = build_cplus_new (totype, expr);
+ }
return expr;
}
case IDENTITY_CONV:
if (type_unknown_p (expr))
- expr = instantiate_type (TREE_TYPE (convs), expr, itf_complain);
+ expr = instantiate_type (totype, expr, tf_error | tf_warning);
return expr;
case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */
return build_user_type_conversion
- (TREE_TYPE (convs), TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
+ (totype, TREE_OPERAND (convs, 0), LOOKUP_NORMAL);
default:
break;
};
- expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum, 1);
+ expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum,
+ TREE_CODE (convs) == REF_BIND ? -1 : 1);
if (expr == error_mark_node)
return error_mark_node;
switch (TREE_CODE (convs))
{
case RVALUE_CONV:
- if (! IS_AGGR_TYPE (TREE_TYPE (convs)))
+ if (! IS_AGGR_TYPE (totype))
return expr;
/* else fall through */
case BASE_CONV:
{
/* We are going to bind a reference directly to a base-class
subobject of EXPR. */
- tree base_ptr = build_pointer_type (TREE_TYPE (convs));
+ tree base_ptr = build_pointer_type (totype);
/* Build an expression for `*((base*) &expr)'. */
expr = build_unary_op (ADDR_EXPR, expr, 0);
return expr;
}
- {
- tree cvt_expr = build_user_type_conversion
- (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
- if (!cvt_expr)
- {
- /* This can occur if, for example, the EXPR has incomplete
- type. We can't check for that before attempting the
- conversion because the type might be an incomplete
- array type, which is OK if some constructor for the
- destination type takes a pointer argument. */
- if (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
- {
- if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
- incomplete_type_error (expr, TREE_TYPE (expr));
- else
- cp_error ("could not convert `%E' (with incomplete type `%T') to `%T'",
- expr, TREE_TYPE (expr), TREE_TYPE (convs));
- }
- else
- cp_error ("could not convert `%E' to `%T'",
- expr, TREE_TYPE (convs));
- return error_mark_node;
- }
- return cvt_expr;
- }
+ /* Copy-initialization where the cv-unqualified version of the source
+ type is the same class as, or a derived class of, the class of the
+ destination [is treated as direct-initialization]. [dcl.init] */
+ savew = warningcount, savee = errorcount;
+ expr = build_new_method_call (NULL_TREE, complete_ctor_identifier,
+ build_tree_list (NULL_TREE, expr),
+ TYPE_BINFO (totype),
+ LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING);
+ if (fn)
+ {
+ if (warningcount > savew)
+ warning (" initializing argument %P of `%D'", argnum, fn);
+ else if (errorcount > savee)
+ error (" initializing argument %P of `%D'", argnum, fn);
+ }
+ return build_cplus_new (totype, expr);
case REF_BIND:
{
- tree ref_type = TREE_TYPE (convs);
+ tree ref_type = totype;
/* If necessary, create a temporary. */
- if (NEED_TEMPORARY_P (convs))
+ if (NEED_TEMPORARY_P (convs) || !lvalue_p (expr))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
expr = build_target_expr_with_type (expr, type);
case QUAL_CONV:
/* Warn about deprecated conversion if appropriate. */
- string_conv_p (TREE_TYPE (convs), expr, 1);
+ string_conv_p (totype, expr, 1);
break;
default:
break;
}
- return ocp_convert (TREE_TYPE (convs), expr, CONV_IMPLICIT,
+ return ocp_convert (totype, expr, CONV_IMPLICIT,
LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
}
if (arg != error_mark_node && ! pod_type_p (TREE_TYPE (arg)))
{
/* Undefined behaviour [expr.call] 5.2.2/7. */
- cp_warning ("cannot pass objects of non-POD type `%#T' through `...'",
+ warning ("cannot pass objects of non-POD type `%#T' through `...'",
TREE_TYPE (arg));
}
if (! pod_type_p (type))
{
/* Undefined behaviour [expr.call] 5.2.2/7. */
- cp_warning ("cannot receive objects of non-POD type `%#T' through `...'",
+ warning ("cannot receive objects of non-POD type `%#T' through `...'",
type);
}
return build_va_arg (expr, type);
}
-/* TYPE has been given to va_arg. Apply the default conversions which would
- have happened when passed via ellipsis. Return the promoted type, or
- NULL_TREE, if there is no change. */
+/* TYPE has been given to va_arg. Apply the default conversions which
+ would have happened when passed via ellipsis. Return the promoted
+ type, or the passed type if there is no change. */
tree
-convert_type_from_ellipsis (type)
+cxx_type_promotes_to (type)
tree type;
{
tree promote;
-
+
if (TREE_CODE (type) == ARRAY_TYPE)
- promote = build_pointer_type (TREE_TYPE (type));
- else if (TREE_CODE (type) == FUNCTION_TYPE)
- promote = build_pointer_type (type);
- else
- promote = type_promotes_to (type);
+ return build_pointer_type (TREE_TYPE (type));
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ return build_pointer_type (type);
+
+ promote = type_promotes_to (type);
+ if (same_type_p (type, promote))
+ promote = type;
- return same_type_p (type, promote) ? NULL_TREE : promote;
+ return promote;
}
/* ARG is a default argument expression being passed to a parameter of
tree fn;
int parmnum;
{
+ if (TREE_CODE (arg) == DEFAULT_ARG)
+ {
+ /* When processing the default args for a class, we can find that
+ there is an ordering constraint, and we call a function who's
+ default args have not yet been converted. For instance,
+ class A {
+ A (int = 0);
+ void Foo (A const & = A ());
+ };
+ We must process A::A before A::Foo's default arg can be converted.
+ Remember the dependent function, so do_pending_defargs can retry,
+ and check loops. */
+ unprocessed_defarg_fn (fn);
+
+ /* Don't return error_mark node, as we won't be able to distinguish
+ genuine errors from this case, and that would lead to repeated
+ diagnostics. Just make something of the right type. */
+ return build1 (NOP_EXPR, type, integer_zero_node);
+ }
+
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
"default argument", fn, parmnum);
- if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- arg = default_conversion (arg);
+ arg = convert_for_arg_passing (type, arg);
}
return arg;
}
+/* Returns the type which will really be used for passing an argument of
+ type TYPE. */
+
+tree
+type_passed_as (type)
+ tree type;
+{
+ /* Pass classes with copy ctors by invisible reference. */
+ if (TREE_ADDRESSABLE (type))
+ type = build_reference_type (type);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ type = integer_type_node;
+
+ return type;
+}
+
+/* Actually perform the appropriate conversion. */
+
+tree
+convert_for_arg_passing (type, val)
+ tree type, val;
+{
+ /* Pass classes with copy ctors by invisible reference. */
+ if (TREE_ADDRESSABLE (type))
+ val = build1 (ADDR_EXPR, build_reference_type (type), val);
+ else if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (type)
+ && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+ val = default_conversion (val);
+ return val;
+}
+
+/* Convert VALUE for assignment into inlined parameter PARM. */
+
+tree
+cp_convert_parm_for_inlining (parm, value, fn)
+ tree parm, value;
+ tree fn ATTRIBUTE_UNUSED;
+{
+ /* When inlining, we don't need to mess with invisible references, so
+ undo the ADDR_EXPR. */
+ if (TREE_ADDRESSABLE (TREE_TYPE (parm)))
+ value = build_indirect_ref (value, NULL);
+ return value;
+}
+
+/* Subroutine of the various build_*_call functions. Overload resolution
+ has chosen a winning candidate CAND; build up a CALL_EXPR accordingly.
+ ARGS is a TREE_LIST of the unconverted arguments to the call. FLAGS is a
+ bitmask of various LOOKUP_* flags which apply to the call itself. */
+
static tree
build_over_call (cand, args, flags)
struct z_candidate *cand;
/* Give any warnings we noticed during overload resolution. */
if (cand->warnings)
for (val = cand->warnings; val; val = TREE_CHAIN (val))
- joust (cand, WRAPPER_PTR (TREE_VALUE (val)), 1);
+ joust (cand, WRAPPER_ZC (TREE_VALUE (val)), 1);
if (DECL_FUNCTION_MEMBER_P (fn))
enforce_access (cand->basetype_path, fn);
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
+ /* We should never try to call the abstract constructor. */
+ abort ();
+ if (DECL_HAS_VTT_PARM_P (fn))
{
converted_args = tree_cons
(NULL_TREE, TREE_VALUE (arg), converted_args);
tree argtype = TREE_TYPE (TREE_VALUE (arg));
tree t;
if (ICS_BAD_FLAG (TREE_VEC_ELT (convs, i)))
- cp_pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
+ pedwarn ("passing `%T' as `this' argument of `%#D' discards qualifiers",
TREE_TYPE (argtype), fn);
/* [class.mfct.nonstatic]: If a nonstatic member function of a class
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
- t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
+ t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
+ TREE_TYPE (parmtype), ba_ignore, NULL);
+ t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
converted_args = tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
tree type = TREE_VALUE (parm);
conv = TREE_VEC_ELT (convs, i);
- if (ICS_BAD_FLAG (conv))
- {
- tree t = conv;
- val = TREE_VALUE (arg);
+ val = convert_like_with_context
+ (conv, TREE_VALUE (arg), fn, i - is_method);
- for (; t; t = TREE_OPERAND (t, 0))
- {
- if (TREE_CODE (t) == USER_CONV
- || TREE_CODE (t) == AMBIG_CONV)
- {
- val = convert_like_with_context (t, val, fn, i - is_method);
- break;
- }
- else if (TREE_CODE (t) == IDENTITY_CONV)
- break;
- }
- val = convert_for_initialization
- (NULL_TREE, type, val, LOOKUP_NORMAL,
- "argument", fn, i - is_method);
- }
- else
- {
- val = TREE_VALUE (arg);
- val = convert_like_with_context
- (conv, TREE_VALUE (arg), fn, i - is_method);
- }
-
- if (PROMOTE_PROTOTYPES
- && (TREE_CODE (type) == INTEGER_TYPE
- || TREE_CODE (type) == ENUMERAL_TYPE)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- val = default_conversion (val);
+ val = convert_for_arg_passing (type, val);
converted_args = tree_cons (NULL_TREE, val, converted_args);
}
converted_args = nreverse (converted_args);
- if (warn_format && (DECL_NAME (fn) || DECL_ASSEMBLER_NAME (fn)))
- check_function_format (NULL, DECL_NAME (fn), DECL_ASSEMBLER_NAME (fn),
- converted_args);
+ if (warn_format)
+ check_function_format (NULL, TYPE_ATTRIBUTES (TREE_TYPE (fn)),
+ converted_args);
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
&& DECL_COPY_CONSTRUCTOR_P (fn))
{
tree targ;
- arg = TREE_CHAIN (converted_args);
- if (DECL_HAS_IN_CHARGE_PARM_P (fn))
- arg = TREE_CHAIN (arg);
+ arg = skip_artificial_parms_for (fn, converted_args);
arg = TREE_VALUE (arg);
/* Pull out the real argument, disregarding const-correctness. */
else if (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
- else if (! real_lvalue_p (arg)
- || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+ else if ((!real_lvalue_p (arg)
+ || TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn)))
+ /* Empty classes have padding which can be hidden
+ inside an (empty) base of the class. This must not
+ be touched as it might overlay things. When the
+ gcc core learns about empty classes, we can treat it
+ like other classes. */
+ && !(is_empty_class (DECL_CONTEXT (fn))
+ && TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))))
{
tree address;
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (args), 0));
- /* If we're initializing an empty class, then we actually
- have to use a MODIFY_EXPR rather than an INIT_EXPR. The
- reason is that the dummy padding member in the target may
- not actually be allocated if TO is a base class
- subobject. Since we've set TYPE_NONCOPIED_PARTS on the
- padding, a MODIFY_EXPR will preserve its value, which is
- the right thing to do if it's not really padding at all.
-
- It's not safe to just throw away the ARG if we're looking
- at an empty class because the ARG might contain a
- TARGET_EXPR which wants to be bound to TO. If it is not,
- expand_expr will assign a dummy slot for the TARGET_EXPR,
- and we will call a destructor for it, which is wrong,
- because we will also destroy TO, but will never have
- constructed it. */
- val = build (is_empty_class (DECL_CONTEXT (fn))
- ? MODIFY_EXPR : INIT_EXPR,
- DECL_CONTEXT (fn), to, arg);
+ val = build (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
address = build_unary_op (ADDR_EXPR, val, 0);
/* Avoid a warning about this expression, if the address is
never used. */
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
- && copy_args_p (fn)
+ && copy_fn_p (fn)
&& TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0));
arg = build_indirect_ref (TREE_VALUE (TREE_CHAIN (converted_args)), 0);
-
- val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
+ if (is_empty_class (TREE_TYPE (to)))
+ {
+ TREE_USED (arg) = 1;
+
+ val = build (COMPOUND_EXPR, DECL_CONTEXT (fn), arg, to);
+ /* Even though the assignment may not actually result in any
+ code being generated, we do not want to warn about the
+ assignment having no effect. That would be confusing to
+ users who may be performing the assignment as part of a
+ generic algorithm, for example.
+
+ Ideally, the notions of having side-effects and of being
+ useless would be orthogonal. */
+ TREE_SIDE_EFFECTS (val) = 1;
+ TREE_NO_UNUSED_WARNING (val) = 1;
+ }
+ else
+ val = build (MODIFY_EXPR, TREE_TYPE (to), to, arg);
return val;
}
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
tree t, *p = &TREE_VALUE (converted_args);
- tree binfo = get_binfo
- (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
- *p = convert_pointer_to_real (binfo, *p);
+ tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
+ DECL_VIRTUAL_CONTEXT (fn),
+ ba_any, NULL);
+ my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
+
+ *p = build_base_path (PLUS_EXPR, *p, binfo, 1);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
t = build_pointer_type (TREE_TYPE (fn));
- fn = build_vfn_ref (p, build_indirect_ref (*p, 0), DECL_VINDEX (fn));
+ if (DECL_CONTEXT (fn) && TYPE_JAVA_INTERFACE (DECL_CONTEXT (fn)))
+ fn = build_java_interface_fn_ref (fn, *p);
+ else
+ fn = build_vfn_ref (build_indirect_ref (*p, 0), DECL_VINDEX (fn));
TREE_TYPE (fn) = t;
}
else if (DECL_INLINE (fn))
return exp;
}
+ /* Some built-in function calls will be evaluated at
+ compile-time in fold (). */
fn = fold (build_call (fn, converted_args));
- if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
+ if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn;
fn = require_complete_type (fn);
+ if (fn == error_mark_node)
+ return error_mark_node;
if (IS_AGGR_TYPE (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn);
return convert_from_reference (fn);
}
+static GTY(()) tree java_iface_lookup_fn;
+
+/* Make an expression which yields the address of the Java interface
+ method FN. This is achieved by generating a call to libjava's
+ _Jv_LookupInterfaceMethodIdx(). */
+
+static tree
+build_java_interface_fn_ref (fn, instance)
+ tree fn, instance;
+{
+ tree lookup_args, lookup_fn, method, idx;
+ tree klass_ref, iface, iface_ref;
+ int i;
+
+ if (!java_iface_lookup_fn)
+ {
+ tree endlink = build_void_list_node ();
+ tree t = tree_cons (NULL_TREE, ptr_type_node,
+ tree_cons (NULL_TREE, ptr_type_node,
+ 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);
+ }
+
+ /* Look up the pointer to the runtime java.lang.Class object for `instance'.
+ This is the first entry in the vtable. */
+ klass_ref = build_vtbl_ref (build_indirect_ref (instance, 0),
+ integer_zero_node);
+
+ /* Get the java.lang.Class pointer for the interface being called. */
+ iface = DECL_CONTEXT (fn);
+ iface_ref = lookup_field (iface, get_identifier ("class$"), 0, 0);
+ if (!iface_ref || TREE_CODE (iface_ref) != VAR_DECL
+ || DECL_CONTEXT (iface_ref) != iface)
+ {
+ error ("could not find class$ field in java interface type `%T'",
+ iface);
+ return error_mark_node;
+ }
+ iface_ref = build1 (ADDR_EXPR, build_pointer_type (iface), iface_ref);
+
+ /* Determine the itable index of FN. */
+ i = 1;
+ for (method = TYPE_METHODS (iface); method; method = TREE_CHAIN (method))
+ {
+ if (!DECL_VIRTUAL_P (method))
+ continue;
+ if (fn == method)
+ break;
+ i++;
+ }
+ idx = build_int_2 (i, 0);
+
+ lookup_args = tree_cons (NULL_TREE, klass_ref,
+ tree_cons (NULL_TREE, iface_ref,
+ build_tree_list (NULL_TREE, idx)));
+ lookup_fn = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (java_iface_lookup_fn)),
+ java_iface_lookup_fn);
+ return build (CALL_EXPR, ptr_type_node, lookup_fn, lookup_args, NULL_TREE);
+}
+
/* Returns the value to use for the in-charge parameter when making a
call to a function with the indicated NAME. */
/* This function should only be called with one of the names listed
above. */
- my_friendly_abort (20000411);
+ abort ();
return NULL_TREE;
}
tree pretty_name;
tree user_args;
tree templates = NULL_TREE;
+ tree call;
int template_only = 0;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
if (! IS_AGGR_TYPE (basetype))
{
if ((flags & LOOKUP_COMPLAIN) && basetype != error_mark_node)
- cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
+ error ("request for member `%D' in `%E', which is of non-aggregate type `%T'",
name, instance, basetype);
return error_mark_node;
pretty_name = (constructor_p
? constructor_name (basetype) : dtor_identifier);
- if (!flag_new_abi)
- {
- /* Add the in-charge parameter as an implicit first argument. */
- if (!constructor_p
- || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
- args = tree_cons (NULL_TREE,
- in_charge_arg_for_name (name),
- args);
-
- /* We want to call the normal constructor function under the
- old ABI. */
- name = constructor_p ? ctor_identifier : dtor_identifier;
- }
- /* If we're call a subobject constructor or destructor for a
+ /* If we're a call to a constructor or destructor for a
subobject that uses virtual base classes, then we need to
pass down a pointer to a VTT for the subobject. */
- else if ((name == base_ctor_identifier
- || name == base_dtor_identifier)
- && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
+ if ((name == base_ctor_identifier
+ || name == base_dtor_identifier)
+ && TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
tree vtt;
tree sub_vtt;
+ tree basebinfo = basetype_path;
/* If the current function is a complete object constructor
or destructor, then we fetch the VTT directly.
Otherwise, we look it up using the VTT we were given. */
vtt = IDENTIFIER_GLOBAL_VALUE (get_vtt_name (current_class_type));
- vtt = build_unary_op (ADDR_EXPR, vtt, /*noconvert=*/1);
- vtt = build (COND_EXPR, TREE_TYPE (vtt),
- DECL_USE_VTT_PARM (current_function_decl),
- DECL_VTT_PARM (current_function_decl),
+ vtt = decay_conversion (vtt);
+ vtt = build (COND_EXPR, TREE_TYPE (vtt),
+ build (EQ_EXPR, boolean_type_node,
+ current_in_charge_parm, integer_zero_node),
+ current_vtt_parm,
vtt);
-
+ if (TREE_VIA_VIRTUAL (basebinfo))
+ basebinfo = binfo_for_vbase (basetype, current_class_type);
+ my_friendly_assert (BINFO_SUBVTT_INDEX (basebinfo), 20010110);
sub_vtt = build (PLUS_EXPR, TREE_TYPE (vtt), vtt,
- BINFO_SUBVTT_INDEX (basetype_path));
- sub_vtt = build_indirect_ref (sub_vtt, NULL);
+ BINFO_SUBVTT_INDEX (basebinfo));
args = tree_cons (NULL_TREE, sub_vtt, args);
}
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
if (!COMPLETE_TYPE_P (basetype))
- incomplete_type_error (instance_ptr, basetype);
+ cxx_incomplete_type_error (instance_ptr, basetype);
else
- cp_error ("no matching function for call to `%T::%D (%A)%V'",
- basetype, pretty_name, user_args,
- TREE_TYPE (TREE_TYPE (instance_ptr)));
+ error ("no matching function for call to `%T::%D(%A)%#V'",
+ basetype, pretty_name, user_args,
+ TREE_TYPE (TREE_TYPE (instance_ptr)));
print_z_candidates (candidates);
return error_mark_node;
}
if (cand == 0)
{
- cp_error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
+ error ("call of overloaded `%D(%A)' is ambiguous", pretty_name,
user_args);
print_z_candidates (candidates);
return error_mark_node;
|| DECL_DESTRUCTOR_P (current_function_decl))
&& ! (flags & LOOKUP_NONVIRTUAL)
&& value_member (cand->fn, CLASSTYPE_PURE_VIRTUALS (basetype)))
- cp_error ((DECL_CONSTRUCTOR_P (current_function_decl) ?
+ error ((DECL_CONSTRUCTOR_P (current_function_decl) ?
"abstract virtual `%#D' called from constructor"
: "abstract virtual `%#D' called from destructor"),
cand->fn);
if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
&& is_dummy_object (instance_ptr))
{
- cp_error ("cannot call member function `%D' without object", cand->fn);
+ error ("cannot call member function `%D' without object", cand->fn);
return error_mark_node;
}
if (DECL_VINDEX (cand->fn) && ! (flags & LOOKUP_NONVIRTUAL)
- && ((instance == current_class_ref && (dtor_label || ctor_label))
- || resolves_to_fixed_type_p (instance, 0)))
+ && resolves_to_fixed_type_p (instance, 0))
flags |= LOOKUP_NONVIRTUAL;
- return build_over_call
- (cand,
- TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE ? mem_args : args,
- flags);
+ if (TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE)
+ call = build_over_call (cand, mem_args, flags);
+ else
+ {
+ call = build_over_call (cand, args, flags);
+ /* Do evaluate the object parameter in a call to a static member
+ function. */
+ if (TREE_SIDE_EFFECTS (instance))
+ call = build (COMPOUND_EXPR, TREE_TYPE (call), instance, call);
+ }
+
+ return call;
}
/* Returns non-zero iff standard conversion sequence ICS1 is a proper
}
}
-/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE
- to the type the reference originally referred to, and return 1.
- Otherwise, return 0. */
+/* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
+ and return the type to which the reference refers. Otherwise,
+ leave *ICS unchanged and return NULL_TREE. */
-static int
-maybe_handle_ref_bind (ics, target_type)
+static tree
+maybe_handle_ref_bind (ics)
tree* ics;
- tree* target_type;
{
if (TREE_CODE (*ics) == REF_BIND)
{
- *target_type = TREE_TYPE (TREE_TYPE (*ics));
- *ics = TREE_OPERAND (*ics, 0);
- return 1;
+ tree old_ics = *ics;
+ tree type = TREE_TYPE (TREE_TYPE (old_ics));
+ *ics = TREE_OPERAND (old_ics, 0);
+ ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
+ ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
+ return type;
}
-
- return 0;
+
+ return NULL_TREE;
}
/* Compare two implicit conversion sequences according to the rules set out in
tree deref_from_type2 = NULL_TREE;
tree deref_to_type1 = NULL_TREE;
tree deref_to_type2 = NULL_TREE;
+ int rank1, rank2;
/* REF_BINDING is non-zero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the
type referred to by the reference. */
- int ref_binding1;
- int ref_binding2;
tree target_type1;
tree target_type2;
maybe_handle_implicit_object (&ics2);
/* Handle reference parameters. */
- ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1);
- ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2);
+ target_type1 = maybe_handle_ref_bind (&ics1);
+ target_type2 = maybe_handle_ref_bind (&ics2);
/* [over.ics.rank]
--a user-defined conversion sequence (_over.ics.user_) is a
better conversion sequence than an ellipsis conversion sequence
(_over.ics.ellipsis_). */
- if (ICS_RANK (ics1) > ICS_RANK (ics2))
+ rank1 = ICS_RANK (ics1);
+ rank2 = ICS_RANK (ics2);
+
+ if (rank1 > rank2)
return -1;
- else if (ICS_RANK (ics1) < ICS_RANK (ics2))
+ else if (rank1 < rank2)
return 1;
- if (ICS_RANK (ics1) == BAD_RANK)
+ if (rank1 == BAD_RANK)
{
+ /* XXX Isn't this an extension? */
/* Both ICS are bad. We try to make a decision based on what
would have happenned if they'd been good. */
if (ICS_USER_FLAG (ics1) > ICS_USER_FLAG (ics2)
}
}
}
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
+ else if (CLASS_TYPE_P (non_reference (from_type1))
&& same_type_p (from_type1, from_type2))
{
+ tree from = non_reference (from_type1);
+
/* [over.ics.rank]
--binding of an expression of type C to a reference of type
reference of type A&
--conversion of C to B is better than conversion of C to A, */
- if (is_properly_derived_from (from_type1, to_type1)
- && is_properly_derived_from (from_type1, to_type2))
+ if (is_properly_derived_from (from, to_type1)
+ && is_properly_derived_from (from, to_type2))
{
if (is_properly_derived_from (to_type1, to_type2))
return 1;
return -1;
}
}
- else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
+ else if (CLASS_TYPE_P (non_reference (to_type1))
&& same_type_p (to_type1, to_type2))
{
+ tree to = non_reference (to_type1);
+
/* [over.ics.rank]
--binding of an expression of type B to a reference of type
reference of type A&,
--onversion of B to A is better than conversion of C to A */
- if (is_properly_derived_from (from_type1, to_type1)
- && is_properly_derived_from (from_type2, to_type1))
+ if (is_properly_derived_from (from_type1, to)
+ && is_properly_derived_from (from_type2, to))
{
if (is_properly_derived_from (from_type2, from_type1))
return 1;
initialized by S2 refers is more cv-qualified than the type to
which the reference initialized by S1 refers */
- if (ref_binding1 && ref_binding2
+ if (target_type1 && target_type2
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
return comp_cv_qualification (target_type2, target_type1);
|| TREE_CODE (t) == IDENTITY_CONV)
return TREE_TYPE (t);
}
- my_friendly_abort (1823);
+ abort ();
}
/* Note a warning about preferring WINNER to LOSER. We do this by storing
add_warning (winner, loser)
struct z_candidate *winner, *loser;
{
- winner->warnings = tree_cons (NULL_PTR,
- build_expr_ptr_wrapper (loser),
+ winner->warnings = tree_cons (NULL_TREE,
+ build_zc_wrapper (loser),
winner->warnings);
}
--len;
}
else
- my_friendly_abort (42);
+ abort ();
}
for (i = 0; i < len; ++i)
if (warn)
{
- cp_warning ("passing `%T' chooses `%T' over `%T'",
+ warning ("passing `%T' chooses `%T' over `%T'",
type, type1, type2);
- cp_warning (" in call to `%D'", w->fn);
+ warning (" in call to `%D'", w->fn);
}
else
add_warning (w, l);
tree source = source_type (TREE_VEC_ELT (w->convs, 0));
if (! DECL_CONSTRUCTOR_P (w->fn))
source = TREE_TYPE (source);
- cp_warning ("choosing `%D' over `%D'", w->fn, l->fn);
- cp_warning (" for conversion from `%T' to `%T'",
+ warning ("choosing `%D' over `%D'", w->fn, l->fn);
+ warning (" for conversion from `%T' to `%T'",
source, TREE_TYPE (w->second_conv));
- cp_warning (" because conversion sequence for the argument is better");
+ warning (" because conversion sequence for the argument is better");
}
else
add_warning (w, l);
return winner;
/* or, if not that,
- F1 is a non-template function and F2 is a template function */
-
+ F1 is a non-template function and F2 is a template function
+ specialization. */
+
if (! cand1->template && cand2->template)
return 1;
else if (cand1->template && ! cand2->template)
return -1;
- else if (cand1->template && cand2->template)
- winner = more_specialized
- (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
- NULL_TREE);
+
+ /* or, if not that,
+ F1 and F2 are template functions and the function template for F1 is
+ more specialized than the template for F2 according to the partial
+ ordering rules. */
+
+ if (cand1->template && cand2->template)
+ {
+ winner = more_specialized
+ (TI_TEMPLATE (cand1->template), TI_TEMPLATE (cand2->template),
+ DEDUCE_ORDER,
+ /* Tell the deduction code how many real function arguments
+ we saw, not counting the implicit 'this' argument. But,
+ add_function_candidate() suppresses the "this" argument
+ for constructors.
+
+ [temp.func.order]: The presence of unused ellipsis and default
+ arguments has no effect on the partial ordering of function
+ templates. */
+ TREE_VEC_LENGTH (cand1->convs)
+ - (DECL_NONSTATIC_MEMBER_FUNCTION_P (cand1->fn)
+ - DECL_CONSTRUCTOR_P (cand1->fn)));
+ /* HERE */
+ if (winner)
+ return winner;
+ }
/* or, if not that,
the context is an initialization by user-defined conversion (see
sequence than the standard conversion sequence from the return type
of F2 to the destination type. */
- if (! winner && cand1->second_conv)
- winner = compare_ics (cand1->second_conv, cand2->second_conv);
+ if (cand1->second_conv)
+ {
+ winner = compare_ics (cand1->second_conv, cand2->second_conv);
+ if (winner)
+ return winner;
+ }
+
+ /* Check whether we can discard a builtin candidate, either because we
+ have two identical ones or matching builtin and non-builtin candidates.
- /* If the built-in candidates are the same, arbitrarily pick one. */
- if (! winner && cand1->fn == cand2->fn
- && TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+ (Pedantically in the latter case the builtin which matched the user
+ function should not be added to the overload set, but we spot it here.
+
+ [over.match.oper]
+ ... the builtin candidates include ...
+ - do not have the same parameter type list as any non-template
+ non-member candidate. */
+
+ if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE
+ || TREE_CODE (cand2->fn) == IDENTIFIER_NODE)
{
for (i = 0; i < len; ++i)
if (!same_type_p (TREE_TYPE (TREE_VEC_ELT (cand1->convs, i)),
TREE_TYPE (TREE_VEC_ELT (cand2->convs, i))))
break;
if (i == TREE_VEC_LENGTH (cand1->convs))
- return 1;
-
- /* Kludge around broken overloading rules whereby
- Integer a, b; test ? a : b; is ambiguous, since there's a builtin
- that takes references and another that takes values. */
- if (cand1->fn == ansi_opname (COND_EXPR))
{
- tree c1 = TREE_VEC_ELT (cand1->convs, 1);
- tree c2 = TREE_VEC_ELT (cand2->convs, 1);
- tree t1 = strip_top_quals (non_reference (TREE_TYPE (c1)));
- tree t2 = strip_top_quals (non_reference (TREE_TYPE (c2)));
-
- if (same_type_p (t1, t2))
- {
- if (TREE_CODE (c1) == REF_BIND && TREE_CODE (c2) != REF_BIND)
- return 1;
- if (TREE_CODE (c1) != REF_BIND && TREE_CODE (c2) == REF_BIND)
- return -1;
- }
+ if (cand1->fn == cand2->fn)
+ /* Two built-in candidates; arbitrarily pick one. */
+ return 1;
+ else if (TREE_CODE (cand1->fn) == IDENTIFIER_NODE)
+ /* cand1 is built-in; prefer cand2. */
+ return -1;
+ else
+ /* cand2 is built-in; prefer cand1. */
+ return 1;
}
}
/* Extension: If the worst conversion for one candidate is worse than the
worst conversion for the other, take the first. */
- if (! winner && ! pedantic)
+ if (!pedantic)
{
int rank1 = IDENTITY_RANK, rank2 = IDENTITY_RANK;
+ struct z_candidate *w = 0, *l = 0;
for (i = 0; i < len; ++i)
{
if (ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2)) > rank2)
rank2 = ICS_RANK (TREE_VEC_ELT (cand2->convs, i+off2));
}
-
if (rank1 < rank2)
- return 1;
+ winner = 1, w = cand1, l = cand2;
if (rank1 > rank2)
- return -1;
+ winner = -1, w = cand2, l = cand1;
+ if (winner)
+ {
+ if (warn)
+ {
+ pedwarn ("choosing `%D' over `%D'", w->fn, l->fn);
+ pedwarn (
+" because worst conversion for the former is better than worst conversion for the latter");
+ }
+ else
+ add_warning (w, l);
+ return winner;
+ }
}
- return winner;
+ my_friendly_assert (!winner, 20010121);
+ return 0;
}
/* Given a list of candidates for overloading, find the best one, if any.
return (t && ! ICS_BAD_FLAG (t));
}
-/* Convert EXPR to TYPE. Return the converted expression. */
+/* Like can_convert_arg, but allows dubious conversions as well. */
+
+int
+can_convert_arg_bad (to, from, arg)
+ tree to, from, arg;
+{
+ tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
+ return !!t;
+}
+
+/* Convert EXPR to TYPE. Return the converted expression.
+
+ Note that we allow bad conversions here because by the time we get to
+ this point we are committed to doing the conversion. If we end up
+ doing a bad conversion, convert_like will complain. */
tree
perform_implicit_conversion (type, expr)
return error_mark_node;
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
LOOKUP_NORMAL);
- if (!conv || ICS_BAD_FLAG (conv))
+ if (!conv)
{
- cp_error ("could not convert `%E' to `%T'", expr, type);
+ error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
- cp_error ("could not convert `%E' to `%T'", expr, type);
+ error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
return convert_like (conv, expr);
}
+
+#include "gt-cp-call.h"