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 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);
}
}
/* 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));
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;
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);
}
{
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;
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 = CP_DECL_CONTEXT (t);
+ (candidates, t, NULL_TREE, args, LOOKUP_NORMAL);
}
if (! any_viable (candidates))
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);
}
}
{
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));
}
}
{
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)));
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))
/* 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;
}
}
static tree delete_duplicate_fields_1 PARAMS ((tree, tree));
static void delete_duplicate_fields PARAMS ((tree));
static void finish_struct_bits PARAMS ((tree));
-static int alter_access PARAMS ((tree, tree, tree, tree));
+static int alter_access PARAMS ((tree, tree, tree));
static void handle_using_decl PARAMS ((tree, tree));
static int overrides PARAMS ((tree, tree));
static int strictly_overrides PARAMS ((tree, tree));
add_method (type, fields, method)
tree type, *fields, method;
{
- /* Setting the DECL_CONTEXT here is probably redundant. */
- DECL_CONTEXT (method) = type;
+ int using = (DECL_CONTEXT (method) != type);
if (fields && *fields)
*fields = build_overload (method, *fields);
same name and the same parameter types cannot be
overloaded if any of them is a static member
function declaration. */
- if (DECL_STATIC_FUNCTION_P (fn)
- != DECL_STATIC_FUNCTION_P (method))
+ if ((DECL_STATIC_FUNCTION_P (fn)
+ != DECL_STATIC_FUNCTION_P (method))
+ || using)
{
tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
if (! DECL_STATIC_FUNCTION_P (fn))
parms1 = TREE_CHAIN (parms1);
- else
+ if (! DECL_STATIC_FUNCTION_P (method))
parms2 = TREE_CHAIN (parms2);
if (compparms (parms1, parms2))
- cp_error ("`%#D' and `%#D' cannot be overloaded",
- fn, method);
+ {
+ if (using)
+ /* Defer to the local function. */
+ return;
+ else
+ cp_error ("`%#D' and `%#D' cannot be overloaded",
+ fn, method);
+ }
}
/* Since this is an ordinary function in a
TREE_CHAIN (x) = delete_duplicate_fields_1 (x, TREE_CHAIN (x));
}
-/* Change the access of FDECL to ACCESS in T. The access to FDECL is
- along the path given by BINFO. Return 1 if change was legit,
- otherwise return 0. */
+/* Change the access of FDECL to ACCESS in T. Return 1 if change was
+ legit, otherwise return 0. */
static int
-alter_access (t, binfo, fdecl, access)
+alter_access (t, fdecl, access)
tree t;
- tree binfo;
tree fdecl;
tree access;
{
}
else
{
- enforce_access (binfo, fdecl);
+ enforce_access (t, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
: access_public_node;
tree fdecl, binfo;
tree flist = NULL_TREE;
- tree fields = TYPE_FIELDS (t);
- tree method_vec = CLASSTYPE_METHOD_VEC (t);
- tree tmp;
- int i;
- int n_methods;
+ tree old_value;
binfo = binfo_or_else (ctype, t);
if (! binfo)
return;
}
- /* Functions are represented as TREE_LIST, with the purpose
- being the type and the value the functions. Other members
- come as themselves. */
- if (TREE_CODE (fdecl) == TREE_LIST)
+ if (BASELINK_P (fdecl))
/* Ignore base type this came from. */
fdecl = TREE_VALUE (fdecl);
- if (TREE_CODE (fdecl) == OVERLOAD)
+ old_value = IDENTIFIER_CLASS_VALUE (name);
+ if (old_value)
{
- /* We later iterate over all functions. */
- flist = fdecl;
- fdecl = OVL_FUNCTION (flist);
+ if (is_overloaded_fn (old_value))
+ old_value = OVL_CURRENT (old_value);
+
+ if (DECL_P (old_value) && DECL_CONTEXT (old_value) == t)
+ /* OK */;
+ else
+ old_value = NULL_TREE;
}
-
- name = DECL_NAME (fdecl);
- n_methods = method_vec ? TREE_VEC_LENGTH (method_vec) : 0;
- for (i = 2; i < n_methods && TREE_VEC_ELT (method_vec, i); i++)
- if (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i)))
- == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local method `%#D' with same name",
- OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
- return;
- }
- if (! DECL_LANG_SPECIFIC (fdecl))
- /* We don't currently handle DECL_ACCESS for TYPE_DECLs; just return. */
- return;
-
- for (tmp = fields; tmp; tmp = TREE_CHAIN (tmp))
- if (DECL_NAME (tmp) == name)
- {
- cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
- cp_error_at (" because of local field `%#D' with same name", tmp);
- return;
- }
-
- /* Make type T see field decl FDECL with access ACCESS.*/
- if (flist)
+ if (is_overloaded_fn (fdecl))
+ flist = fdecl;
+ else if (! DECL_LANG_SPECIFIC (fdecl))
+ my_friendly_abort (20000221);
+
+ if (! old_value)
+ ;
+ else if (is_overloaded_fn (old_value))
{
- while (flist)
+ if (flist)
+ /* It's OK to use functions from a base when there are functions with
+ the same name already present in the current class. */;
+ else
{
- if (alter_access (t, binfo, OVL_FUNCTION (flist),
- access) == 0)
- return;
- flist = OVL_CHAIN (flist);
+ cp_error ("`%D' invalid in `%#T'", using_decl, t);
+ cp_error_at (" because of local method `%#D' with same name",
+ OVL_CURRENT (old_value));
+ return;
}
}
else
- alter_access (t, binfo, fdecl, access);
+ {
+ cp_error ("`%D' invalid in `%#T'", using_decl, t);
+ cp_error_at (" because of local field `%#D' with same name", old_value);
+ return;
+ }
+
+ /* Make type T see field decl FDECL with access ACCESS.*/
+ if (flist)
+ for (; flist; flist = OVL_NEXT (flist))
+ {
+ add_method (t, 0, OVL_CURRENT (flist));
+ alter_access (t, OVL_CURRENT (flist), access);
+ }
+ else
+ alter_access (t, fdecl, access);
}
\f
/* Run through the base clases of T, updating
cant_have_const_ctor,
no_const_asn_ref);
+ /* Process the using-declarations. */
+ for (; access_decls; access_decls = TREE_CHAIN (access_decls))
+ handle_using_decl (TREE_VALUE (access_decls), t);
+
/* Build and sort the CLASSTYPE_METHOD_VEC. */
finish_struct_methods (t);
-
- /* Process the access-declarations. We wait until now to do this
- because handle_using_decls requires that the CLASSTYPE_METHOD_VEC
- be set up correctly. */
- while (access_decls)
- {
- handle_using_decl (TREE_VALUE (access_decls), t);
- access_decls = TREE_CHAIN (access_decls);
- }
}
/* If T needs a pointer to its virtual function table, set TYPE_VFIELD