/* Functions related to invoking methods and overloaded functions.
- Copyright (C) 1987, 92-99, 2000 Free Software Foundation, Inc.
+ Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+ 1999, 2000 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com).
#include "toplev.h"
#include "defaults.h"
#include "expr.h"
-
-#include "obstack.h"
-#define obstack_chunk_alloc xmalloc
-#define obstack_chunk_free free
+#include "ggc.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));
-static tree convert_like 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_object_call PARAMS ((tree, tree));
static struct z_candidate * splice_viable PARAMS ((struct z_candidate *));
static int any_viable PARAMS ((struct z_candidate *));
static struct z_candidate * add_template_candidate
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, int,
+ PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
unification_kind_t));
static struct z_candidate * add_template_candidate_real
- PARAMS ((struct z_candidate *, tree, tree, tree, tree, int,
+ PARAMS ((struct z_candidate *, tree, tree, tree, tree, tree, int,
tree, unification_kind_t));
static struct z_candidate * add_template_conv_candidate
PARAMS ((struct z_candidate *, tree, tree, tree, tree));
static struct z_candidate * add_conv_candidate
PARAMS ((struct z_candidate *, tree, tree, tree));
static struct z_candidate * add_function_candidate
- PARAMS ((struct z_candidate *, tree, tree, int));
+ PARAMS ((struct z_candidate *, tree, tree, tree, int));
static tree implicit_conversion PARAMS ((tree, tree, tree, int));
static tree standard_conversion PARAMS ((tree, tree, tree));
static tree reference_binding PARAMS ((tree, tree, tree, int));
static int maybe_handle_ref_bind PARAMS ((tree*, tree*));
static void maybe_handle_implicit_object PARAMS ((tree*));
static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
- tree, tree, int));
+ tree, tree, int));
static tree source_type PARAMS ((tree));
static void add_warning PARAMS ((struct z_candidate *, struct z_candidate *));
static int reference_related_p PARAMS ((tree, tree));
{
tree field, instance;
- if (name == ctor_identifier || name == dtor_identifier)
+ if (IDENTIFIER_CTOR_OR_DTOR_P (name))
return NULL_TREE;
/* Speed up the common case. */
if (TREE_CODE (name) == TYPE_DECL)
name = TREE_TYPE (name);
- else if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
+ else if (TYPE_P (name))
/* OK */;
else if (TREE_CODE (name) == IDENTIFIER_NODE)
{
(TYPE_PTRMEMFUNC_P) must be handled by our callers. */
tree
-build_call (function, result_type, parms)
- tree function, result_type, parms;
+build_call (function, parms)
+ tree function, parms;
{
int is_constructor = 0;
+ int nothrow;
tree tmp;
tree decl;
+ tree result_type;
function = build_addr_func (function);
return error_mark_node;
}
+ result_type = TREE_TYPE (TREE_TYPE (TREE_TYPE (function)));
+
if (TREE_CODE (function) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL)
decl = TREE_OPERAND (function, 0);
else
decl = NULL_TREE;
+ /* We check both the decl and the type; a function may be known not to
+ throw without being declared throw(). */
+ nothrow = ((decl && TREE_NOTHROW (decl))
+ || TYPE_NOTHROW_P (TREE_TYPE (TREE_TYPE (function))));
+
if (decl && DECL_CONSTRUCTOR_P (decl))
is_constructor = 1;
- if (decl)
- my_friendly_assert (TREE_USED (decl), 990125);
+ if (decl && ! TREE_USED (decl))
+ {
+ /* We invoke build_call directly for several library functions. */
+ if (DECL_ARTIFICIAL (decl))
+ mark_used (decl);
+ else
+ my_friendly_abort (990125);
+ }
/* Don't pass empty class objects by value. This is useful
for tags in STL, which are used to control overload resolution.
TREE_HAS_CONSTRUCTOR (function) = is_constructor;
TREE_TYPE (function) = result_type;
TREE_SIDE_EFFECTS (function) = 1;
+ TREE_NOTHROW (function) = nothrow;
return function;
}
{
tree fns = TREE_VALUE (conversions);
- while (fns)
+ for (; fns; fns = OVL_NEXT (fns))
{
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
{
candidates
= add_template_candidate (candidates,
- f,
+ f, s,
NULL_TREE,
arglist,
build_reference_type (t),
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
candidates
- = add_function_candidate (candidates, f, arglist,
+ = add_function_candidate (candidates, f, s, arglist,
LOOKUP_NORMAL);
if (candidates != old_candidates)
- candidates->basetype_path = TREE_PURPOSE (conversions);
-
- fns = OVL_NEXT (fns);
+ candidates->basetype_path = TYPE_BINFO (s);
}
}
tree fn, convs;
int viable;
{
- /* FIXME: This is a memory leak. Presumably, we should use
- ggc_alloc instead. */
struct z_candidate *cand
- = (struct z_candidate *) expralloc (sizeof (struct z_candidate));
+ = (struct z_candidate *) ggc_alloc_obj (sizeof (struct z_candidate), 1);
cand->fn = fn;
cand->convs = convs;
- cand->second_conv = NULL_TREE;
cand->viable = viable;
- cand->basetype_path = NULL_TREE;
- cand->template = NULL_TREE;
- cand->warnings = NULL_TREE;
cand->next = candidates;
return cand;
/* Create an overload candidate for the function or method FN called with
the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on
- to implicit_conversion. */
+ to implicit_conversion.
+
+ CTYPE, if non-NULL, is the type we want to pretend this function
+ comes from for purposes of overload resolution. */
static struct z_candidate *
-add_function_candidate (candidates, fn, arglist, flags)
+add_function_candidate (candidates, fn, ctype, arglist, flags)
struct z_candidate *candidates;
- tree fn, arglist;
+ tree fn, ctype, arglist;
int flags;
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
{
parmlist = TREE_CHAIN (parmlist);
arglist = TREE_CHAIN (arglist);
- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
{
parmlist = TREE_CHAIN (parmlist);
arglist = TREE_CHAIN (arglist);
tree arg = TREE_VALUE (argnode);
tree argtype = lvalue_type (arg);
tree t;
+ int is_this;
if (parmnode == void_list_node)
break;
+ is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
+ && ! DECL_CONSTRUCTOR_P (fn));
+
if (parmnode)
{
tree parmtype = TREE_VALUE (parmnode);
- /* [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.
+ /* The type of the implicit object parameter ('this') for
+ overload resolution is not always the same as for the
+ function itself; conversion functions are considered to
+ be members of the class being converted, and functions
+ introduced by a using-declaration are considered to be
+ members of the class that uses them.
- Since build_over_call ignores the ICS for the `this' parameter,
- we can just change the parm type. */
- if (DECL_CONV_FN_P (fn) && i == 0)
+ Since build_over_call ignores the ICS for the `this'
+ parameter, we can just change the parm type. */
+ if (ctype && is_this)
{
parmtype
- = build_qualified_type (TREE_TYPE (argtype),
+ = build_qualified_type (ctype,
TYPE_QUALS (TREE_TYPE (parmtype)));
parmtype = build_pointer_type (parmtype);
}
ICS_ELLIPSIS_FLAG (t) = 1;
}
- if (i == 0 && t && TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE
- && ! DECL_CONSTRUCTOR_P (fn))
+ if (t && is_this)
ICS_THIS_FLAG (t) = 1;
TREE_VEC_ELT (convs, i) = t;
is_complete (t)
tree t;
{
- return TYPE_SIZE (complete_type (t)) != NULL_TREE;
+ return COMPLETE_TYPE_P (complete_type (t));
}
/* Returns non-zero if TYPE is a promoted arithmetic type. */
1) bool-taking candidates. These are the same regardless of the input.
2) pointer-pair taking candidates. These are generated for each type
one of the input types converts to.
- 3) arithmetic candidates. According to the WP, we should generate
+ 3) arithmetic candidates. According to the standard, we should generate
all of these, but I'm trying not to... */
static struct z_candidate *
TMPL is the template. EXPLICIT_TARGS are any explicit template
arguments. ARGLIST is the arguments provided at the call-site.
The RETURN_TYPE is the desired type for conversion operators. If
- OBJ is NULL_TREE, FLAGS are as for add_function_candidate. If an
- OBJ is supplied, FLAGS are ignored, and OBJ is as for
+ OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate.
+ If an OBJ is supplied, FLAGS and CTYPE are ignored, and OBJ is as for
add_conv_candidate. */
static struct z_candidate*
-add_template_candidate_real (candidates, tmpl, explicit_targs,
+add_template_candidate_real (candidates, tmpl, ctype, explicit_targs,
arglist, return_type, flags,
obj, strict)
struct z_candidate *candidates;
- tree tmpl, explicit_targs, arglist, return_type;
+ tree tmpl, ctype, explicit_targs, arglist, return_type;
int flags;
tree obj;
unification_kind_t strict;
/* Aha, this is a conversion function. */
cand = add_conv_candidate (candidates, fn, obj, arglist);
else
- cand = add_function_candidate (candidates, fn, arglist, flags);
+ cand = add_function_candidate (candidates, fn, ctype,
+ arglist, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
class is specialized. Then, instantiate_template might return
static struct z_candidate *
-add_template_candidate (candidates, tmpl, explicit_targs,
+add_template_candidate (candidates, tmpl, ctype, explicit_targs,
arglist, return_type, flags, strict)
struct z_candidate *candidates;
- tree tmpl, explicit_targs, arglist, return_type;
+ tree tmpl, ctype, explicit_targs, arglist, return_type;
int flags;
unification_kind_t strict;
{
return
- add_template_candidate_real (candidates, tmpl, explicit_targs,
- arglist, return_type, flags,
+ add_template_candidate_real (candidates, tmpl, ctype,
+ explicit_targs, arglist, return_type, flags,
NULL_TREE, strict);
}
tree tmpl, obj, arglist, return_type;
{
return
- add_template_candidate_real (candidates, tmpl, NULL_TREE, arglist,
- return_type, 0, obj, DEDUCE_CONV);
+ add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
+ arglist, return_type, 0, obj, DEDUCE_CONV);
}
tree templates = NULL_TREE;
if (IS_AGGR_TYPE (totype))
- ctors = lookup_fnfields (TYPE_BINFO (totype), ctor_identifier, 0);
+ ctors = lookup_fnfields (TYPE_BINFO (totype),
+ (flag_new_abi
+ ? complete_ctor_identifier
+ : ctor_identifier),
+ 0);
+
if (IS_AGGR_TYPE (fromtype)
&& (! IS_AGGR_TYPE (totype) || ! DERIVED_FROM_P (totype, fromtype)))
convs = lookup_conversions (fromtype);
if (ctors)
{
- tree t = build_int_2 (0, 0);
+ tree t;
+
+ ctors = TREE_VALUE (ctors);
+
+ t = build_int_2 (0, 0);
TREE_TYPE (t) = build_pointer_type (totype);
args = build_tree_list (NULL_TREE, expr);
- if (TYPE_USES_VIRTUAL_BASECLASSES (totype))
+ if (DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors)))
args = tree_cons (NULL_TREE, integer_one_node, args);
args = tree_cons (NULL_TREE, t, args);
-
- ctors = TREE_VALUE (ctors);
}
for (; ctors; ctors = OVL_NEXT (ctors))
{
{
templates = tree_cons (NULL_TREE, ctor, templates);
candidates =
- add_template_candidate (candidates, ctor,
+ add_template_candidate (candidates, ctor, totype,
NULL_TREE, args, NULL_TREE, flags,
DEDUCE_CALL);
}
else
- candidates = add_function_candidate (candidates, ctor,
+ candidates = add_function_candidate (candidates, ctor, totype,
args, flags);
if (candidates)
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. */
+
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, fn, templates);
candidates =
- add_template_candidate (candidates, fn, NULL_TREE,
+ add_template_candidate (candidates, fn, fromtype, NULL_TREE,
args, totype, flags,
DEDUCE_CONV);
}
else
- candidates = add_function_candidate (candidates, fn,
+ candidates = add_function_candidate (candidates, fn, fromtype,
args, flags);
if (candidates != old_candidates)
0, convflags);
candidates->second_conv = ics;
- candidates->basetype_path = TREE_PURPOSE (convs);
+ candidates->basetype_path = TYPE_BINFO (fromtype);
if (ics == NULL_TREE)
candidates->viable = 0;
{
if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node;
- return convert_from_reference (convert_like (cand->second_conv, expr));
+ return convert_from_reference
+ (convert_like_with_context
+ (cand->second_conv, expr, cand->fn, 0));
}
return NULL_TREE;
}
for (t1 = fn; t1; t1 = OVL_CHAIN (t1))
{
tree t = OVL_FUNCTION (t1);
- struct z_candidate *old_candidates = candidates;
if (TREE_CODE (t) == TEMPLATE_DECL)
{
templates = tree_cons (NULL_TREE, t, templates);
candidates = add_template_candidate
- (candidates, t, explicit_targs, args, NULL_TREE,
+ (candidates, t, NULL_TREE, explicit_targs, args, NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else if (! template_only)
candidates = add_function_candidate
- (candidates, t, args, LOOKUP_NORMAL);
-
- if (candidates != old_candidates)
- candidates->basetype_path = DECL_REAL_CONTEXT (t);
+ (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
{
/* 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", obj);
- cp_error ("without an object; consider using .* or ->*");
+ cp_error ("pointer-to-member function %E cannot be called without an object; consider using .* or ->*", obj);
return error_mark_node;
}
if (fns)
{
- tree base = TREE_PURPOSE (fns);
+ tree base = BINFO_TYPE (TREE_PURPOSE (fns));
mem_args = tree_cons (NULL_TREE, build_this (obj), args);
for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
if (TREE_CODE (fn) == TEMPLATE_DECL)
{
candidates
- = add_template_candidate (candidates, fn, NULL_TREE,
+ = add_template_candidate (candidates, fn, base, NULL_TREE,
mem_args, NULL_TREE,
LOOKUP_NORMAL, DEDUCE_CALL);
}
else
candidates = add_function_candidate
- (candidates, fn, mem_args, LOOKUP_NORMAL);
+ (candidates, fn, base, mem_args, LOOKUP_NORMAL);
if (candidates)
- candidates->basetype_path = base;
+ candidates->basetype_path = TYPE_BINFO (type);
}
}
}
else
candidates = add_conv_candidate (candidates, fn, obj, args);
-
- if (candidates)
- candidates->basetype_path = TREE_PURPOSE (convs);
}
}
&& DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
- obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
+ obj = convert_like_with_context
+ (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
/* FIXME */
return build_function_call (obj, args);
if (!arg2)
{
if (pedantic)
- pedwarn ("ANSI C++ forbids omitting the middle term of a ?: expression");
+ pedwarn ("ISO C++ forbids omitting the middle term of a ?: expression");
arg1 = arg2 = save_expr (arg1);
}
{
templates = tree_cons (NULL_TREE, fn, templates);
candidates
- = add_template_candidate (candidates, fn, NULL_TREE,
+ = add_template_candidate (candidates, fn, NULL_TREE, NULL_TREE,
arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
- candidates = add_function_candidate (candidates, fn, arglist, flags);
+ candidates = add_function_candidate (candidates, fn, NULL_TREE,
+ arglist, flags);
}
if (IS_AGGR_TYPE (TREE_TYPE (arg1)))
if (fns)
{
- tree basetype = TREE_PURPOSE (fns);
+ tree basetype = BINFO_TYPE (TREE_PURPOSE (fns));
mem_arglist = tree_cons (NULL_TREE, build_this (arg1), TREE_CHAIN (arglist));
for (fns = TREE_VALUE (fns); fns; fns = OVL_NEXT (fns))
{
/* A member template. */
templates = tree_cons (NULL_TREE, fn, templates);
candidates
- = add_template_candidate (candidates, fn, NULL_TREE,
+ = add_template_candidate (candidates, fn, basetype, NULL_TREE,
this_arglist, TREE_TYPE (fnname),
flags, DEDUCE_CALL);
}
else
candidates = add_function_candidate
- (candidates, fn, this_arglist, flags);
+ (candidates, fn, basetype, this_arglist, flags);
- if (candidates)
- candidates->basetype_path = basetype;
+ if (candidates)
+ candidates->basetype_path = TYPE_BINFO (TREE_TYPE (arg1));
}
}
case BIT_XOR_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
- return build_binary_op_nodefault (code, arg1, arg2, code);
+ return build_binary_op (code, arg1, arg2);
case CONVERT_EXPR:
case NEGATE_EXPR:
}
}
-/* Build up a call to operator new. This has to be handled differently
- from other operators in the way lookup is handled; first members are
- considered, then globals. CODE is either NEW_EXPR or VEC_NEW_EXPR.
- TYPE is the type to be created. ARGS are any new-placement args.
- FLAGS are the usual overloading flags. */
-
-tree
-build_op_new_call (code, type, args, flags)
- enum tree_code code;
- tree type, args;
- int flags;
-{
- tree fnname = ansi_opname[code];
-
- if (IS_AGGR_TYPE (type) && ! (flags & LOOKUP_GLOBAL)
- && (TYPE_GETS_NEW (type) & (1 << (code == VEC_NEW_EXPR))))
- {
- return build_method_call (build_dummy_object (type),
- fnname, args, NULL_TREE, flags);
- }
- else
- return build_new_function_call
- (lookup_function_nonclass (fnname, args), args);
-}
-
/* Build a call to operator delete. This has to be handled very specially,
because the restrictions on what signatures match are different from all
other call instances. For a normal delete, only a delete taking (void *)
{
if (TREE_CODE (fns) == TREE_LIST)
/* Member functions. */
- enforce_access (TREE_PURPOSE (fns), fn);
+ enforce_access (type, fn);
return build_function_call (fn, tree_cons (NULL_TREE, addr, args));
}
{
if (BASELINK_P (fns))
/* Member functions. */
- enforce_access (TREE_PURPOSE (fns), fn);
+ enforce_access (type, fn);
return build_function_call
(fn, tree_cons (NULL_TREE, addr,
build_tree_list (NULL_TREE, size)));
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
- cp_error ("no suitable operator delete for `%T'", type);
+ cp_error ("no suitable `operator delete' for `%T'", type);
return error_mark_node;
}
return 1;
}
-/* Perform the conversions in CONVS on the expression EXPR. */
+/* 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. */
static tree
-convert_like (convs, expr)
+convert_like_real (convs, expr, fn, argnum, inner)
tree convs, expr;
+ tree fn;
+ int argnum;
+ int inner;
{
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
{
if (TREE_CODE (t) == USER_CONV)
{
- expr = convert_like (t, expr);
+ expr = convert_like_real (t, expr, fn, argnum, 1);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
- return convert_like (t, expr);
+ return convert_like_real (t, expr, fn, argnum, 1);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
return convert_for_initialization
(NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
- "conversion", NULL_TREE, 0);
+ "conversion", fn, argnum);
}
-
+
+ if (!inner)
+ expr = dubious_conversion_warnings
+ (TREE_TYPE (convs), expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
TREE_TYPE (t) = build_pointer_type (DECL_CONTEXT (fn));
args = build_tree_list (NULL_TREE, expr);
- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
args = tree_cons (NULL_TREE, integer_one_node, args);
args = tree_cons (NULL_TREE, t, args);
}
break;
};
- expr = convert_like (TREE_OPERAND (convs, 0), expr);
+ expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum, 1);
if (expr == error_mark_node)
return error_mark_node;
- /* Convert a constant variable to its underlying value, unless we
+ /* Convert a non-array constant variable 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. */
- if (TREE_READONLY_DECL_P (expr) && TREE_CODE (convs) != REF_BIND)
+ if (TREE_READONLY_DECL_P (expr) && TREE_CODE (convs) != REF_BIND
+ && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
expr = decl_constant_value (expr);
switch (TREE_CODE (convs))
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 (TYPE_SIZE (TREE_TYPE (expr)) == 0)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (expr)))
{
if (same_type_p (TREE_TYPE (expr), TREE_TYPE (convs)))
incomplete_type_error (expr, TREE_TYPE (expr));
conversions. Return the converted value. */
tree
-convert_default_arg (type, arg, fn)
+convert_default_arg (type, arg, fn, parmnum)
tree type;
tree arg;
tree fn;
+ int parmnum;
{
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
{
arg = digest_init (type, arg, 0);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
+ "default argument", fn, parmnum);
}
else
{
arg = copy_node (arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
+ "default argument", fn, parmnum);
if (PROMOTE_PROTOTYPES
&& (TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
converted_args = tree_cons (NULL_TREE, TREE_VALUE (arg), converted_args);
arg = TREE_CHAIN (arg);
parm = TREE_CHAIN (parm);
- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
{
converted_args = tree_cons
(NULL_TREE, TREE_VALUE (arg), converted_args);
if (TREE_CODE (t) == USER_CONV
|| TREE_CODE (t) == AMBIG_CONV)
{
- val = convert_like (t, val);
+ val = convert_like_with_context (t, val, fn, i - is_method);
break;
}
else if (TREE_CODE (t) == IDENTITY_CONV)
}
val = convert_for_initialization
(NULL_TREE, type, val, LOOKUP_NORMAL,
- "argument passing", fn, i - is_method);
+ "argument", fn, i - is_method);
}
else
{
- /* Issue warnings about peculiar, but legal, uses of NULL. */
- if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
- && TREE_VALUE (arg) == null_node)
- cp_warning ("converting NULL to non-pointer type");
-
- val = convert_like (conv, TREE_VALUE (arg));
+ val = TREE_VALUE (arg);
+ val = convert_like_with_context
+ (conv, TREE_VALUE (arg), fn, i - is_method);
}
if (PROMOTE_PROTOTYPES
}
/* Default arguments */
- for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
+ for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
converted_args
= tree_cons (NULL_TREE,
convert_default_arg (TREE_VALUE (parm),
TREE_PURPOSE (parm),
- fn),
+ fn, i - is_method),
converted_args);
/* Ellipsis */
if (! flag_elide_constructors)
/* Do things the hard way. */;
- else if (DECL_CONSTRUCTOR_P (fn)
- && TREE_VEC_LENGTH (convs) == 1
- && copy_args_p (fn))
+ else if (TREE_VEC_LENGTH (convs) == 1
+ && DECL_COPY_CONSTRUCTOR_P (fn))
{
tree targ;
arg = TREE_CHAIN (converted_args);
- if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
+ if (DECL_HAS_IN_CHARGE_PARM_P (fn))
arg = TREE_CHAIN (arg);
arg = TREE_VALUE (arg);
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_CLASS_CONTEXT (fn))
+ val = build (is_empty_class (DECL_CONTEXT (fn))
? MODIFY_EXPR : INIT_EXPR,
DECL_CONTEXT (fn), to, arg);
address = build_unary_op (ADDR_EXPR, val, 0);
}
else if (DECL_NAME (fn) == ansi_opname[MODIFY_EXPR]
&& copy_args_p (fn)
- && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CLASS_CONTEXT (fn)))
+ && TYPE_HAS_TRIVIAL_ASSIGN_REF (DECL_CONTEXT (fn)))
{
tree to = stabilize_reference
(build_indirect_ref (TREE_VALUE (converted_args), 0));
return exp;
}
- fn = build_call (fn, TREE_TYPE (TREE_TYPE (TREE_TYPE (fn))), converted_args);
+ fn = build_call (fn, converted_args);
if (TREE_CODE (TREE_TYPE (fn)) == VOID_TYPE)
return fn;
fn = require_complete_type (fn);
return convert_from_reference (fn);
}
+/* Returns the value to use for the in-charge parameter when making a
+ call to a function with the indicated NAME. */
+
+tree
+in_charge_arg_for_name (name)
+ tree name;
+{
+ if (name == base_ctor_identifier
+ || name == base_dtor_identifier)
+ return integer_zero_node;
+ else if (name == complete_ctor_identifier)
+ return integer_one_node;
+ else if (name == complete_dtor_identifier)
+ return integer_two_node;
+ else if (name == deleting_dtor_identifier)
+ return integer_three_node;
+
+ /* This function should only be called with one of the names listed
+ above. */
+ my_friendly_abort (20000411);
+ return NULL_TREE;
+}
+
static tree
build_new_method_call (instance, name, args, basetype_path, flags)
tree instance, name, args, basetype_path;
{
explicit_targs = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
- if (TREE_CODE_CLASS (TREE_CODE (name)) == 'd')
+ if (DECL_P (name))
name = DECL_NAME (name);
else
{
template_only = 1;
}
- /* If there is an extra argument for controlling virtual bases,
- remove it for error reporting. */
- if (flags & LOOKUP_HAS_IN_CHARGE)
- user_args = TREE_CHAIN (args);
-
+ user_args = args;
args = resolve_args (args);
if (args == error_mark_node)
TREE_TYPE (instance_ptr) = build_pointer_type (basetype);
}
- pretty_name
- = (name == ctor_identifier ? constructor_name (basetype) : name);
+ /* Callers should explicitly indicate whether they want to construct
+ the complete object or just the part without virtual bases. */
+ my_friendly_assert (name != ctor_identifier, 20000408);
+ /* Similarly for destructors. */
+ my_friendly_assert (name != dtor_identifier, 20000408);
+
+ if (IDENTIFIER_CTOR_OR_DTOR_P (name))
+ {
+ int constructor_p;
+
+ constructor_p = (name == complete_ctor_identifier
+ || name == base_ctor_identifier);
+ 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;
+ }
+ }
+ else
+ pretty_name = name;
fns = lookup_fnfields (basetype_path, name, 1);
return error_mark_node;
if (fns)
{
+ tree base = BINFO_TYPE (TREE_PURPOSE (fns));
tree fn = TREE_VALUE (fns);
- if (name == ctor_identifier && TYPE_USES_VIRTUAL_BASECLASSES (basetype)
- && ! (flags & LOOKUP_HAS_IN_CHARGE))
- {
- flags |= LOOKUP_HAS_IN_CHARGE;
- args = tree_cons (NULL_TREE, integer_one_node, args);
- }
mem_args = tree_cons (NULL_TREE, instance_ptr, args);
for (; fn; fn = OVL_NEXT (fn))
{
tree this_arglist;
/* We can end up here for copy-init of same or base class. */
- if (name == ctor_identifier
- && (flags & LOOKUP_ONLYCONVERTING)
+ if ((flags & LOOKUP_ONLYCONVERTING)
&& DECL_NONCONVERTING_P (t))
continue;
if (TREE_CODE (TREE_TYPE (t)) == METHOD_TYPE)
/* A member template. */
templates = tree_cons (NULL_TREE, t, templates);
candidates =
- add_template_candidate (candidates, t, explicit_targs,
+ add_template_candidate (candidates, t, base, explicit_targs,
this_arglist,
TREE_TYPE (name), flags, DEDUCE_CALL);
}
else if (! template_only)
- candidates = add_function_candidate (candidates, t,
+ candidates = add_function_candidate (candidates, t, base,
this_arglist, flags);
if (candidates)
- candidates->basetype_path = TREE_PURPOSE (fns);
+ candidates->basetype_path = basetype_path;
}
}
/* XXX will LOOKUP_SPECULATIVELY be needed when this is done? */
if (flags & LOOKUP_SPECULATIVELY)
return NULL_TREE;
- if (TYPE_SIZE (basetype) == 0)
+ if (!COMPLETE_TYPE_P (basetype))
incomplete_type_error (instance_ptr, basetype);
else
cp_error ("no matching function for call to `%T::%D (%A)%V'",
/* for some argument j, ICSj(F1) is a better conversion sequence than
ICSj(F2) */
- /* For comparing static and non-static member functions, we ignore the
- implicit object parameter of the non-static function. The WP says to
- pretend that the static function has an object parm, but that won't
- work with operator overloading. */
+ /* For comparing static and non-static member functions, we ignore
+ the implicit object parameter of the non-static function. The
+ standard says to pretend that the static function has an object
+ parm, but that won't work with operator overloading. */
len = TREE_VEC_LENGTH (cand1->convs);
if (len != TREE_VEC_LENGTH (cand2->convs))
{