mirror of
git://gcc.gnu.org/git/gcc.git
synced 2024-12-19 16:09:45 +08:00
Implement class scope using-declarations for functions.
* class.c (handle_using_decl): Call add_method for used functions. Use IDENTIFIER_CLASS_VALUE to check for conflicts. (add_method): Used functions are hidden by local functions. (check_bases_and_members): Handle using-decls before finalizing CLASSTYPE_METHOD_VEC. * call.c (add_function_candidate): Add ctype parm; if non-zero, override the type of 'this' accordingly. (add_template_candidate, add_template_candidate_real): Add ctype parm. (convert_class_to_reference, build_user_type_conversion_1, build_new_function_call, build_object_call, build_new_op, build_new_method_call): Pass ctype parm. * search.c (lookup_member): Put rval_binfo, not basetype_path, in the baselink. * call.c (convert_class_to_reference, build_user_type_conversion_1, build_new_function_call, build_object_call, build_new_op, build_new_method_call, build_op_delete_call): Don't get basetype_path from a baselink. * typeck.c (build_component_ref): Likewise. * init.c (build_offset_ref): Likewise. (resolve_offset_ref): Don't call enforce_access. Call build_scoped_ref. * typeck2.c (build_scoped_ref): Simplify. Do nothing if it would cause an error or if -pedantic. * class.c (alter_access): Lose binfo parm. From-SVN: r32212
This commit is contained in:
parent
0172e2bc87
commit
aa52c1ffad
@ -1,3 +1,32 @@
|
||||
2000-02-26 Jason Merrill <jason@casey.cygnus.com>
|
||||
|
||||
Implement class scope using-declarations for functions.
|
||||
* class.c (handle_using_decl): Call add_method for used functions.
|
||||
Use IDENTIFIER_CLASS_VALUE to check for conflicts.
|
||||
(add_method): Used functions are hidden by local functions.
|
||||
(check_bases_and_members): Handle using-decls before finalizing
|
||||
CLASSTYPE_METHOD_VEC.
|
||||
* call.c (add_function_candidate): Add ctype parm; if non-zero,
|
||||
override the type of 'this' accordingly.
|
||||
(add_template_candidate, add_template_candidate_real): Add ctype parm.
|
||||
(convert_class_to_reference, build_user_type_conversion_1,
|
||||
build_new_function_call, build_object_call, build_new_op,
|
||||
build_new_method_call): Pass ctype parm.
|
||||
|
||||
* search.c (lookup_member): Put rval_binfo, not basetype_path, in
|
||||
the baselink.
|
||||
* call.c (convert_class_to_reference, build_user_type_conversion_1,
|
||||
build_new_function_call, build_object_call, build_new_op,
|
||||
build_new_method_call, build_op_delete_call): Don't get basetype_path
|
||||
from a baselink.
|
||||
* typeck.c (build_component_ref): Likewise.
|
||||
* init.c (build_offset_ref): Likewise.
|
||||
(resolve_offset_ref): Don't call enforce_access.
|
||||
Call build_scoped_ref.
|
||||
* typeck2.c (build_scoped_ref): Simplify. Do nothing if it
|
||||
would cause an error or if -pedantic.
|
||||
* class.c (alter_access): Lose binfo parm.
|
||||
|
||||
2000-02-26 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* semantics.c (simplify_aggr_init_exprs_p): Don't walk into
|
||||
|
137
gcc/cp/call.c
137
gcc/cp/call.c
@ -61,10 +61,10 @@ 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 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));
|
||||
@ -81,7 +81,7 @@ static struct z_candidate * build_builtin_candidate
|
||||
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));
|
||||
@ -91,7 +91,7 @@ static int is_subseq PARAMS ((tree, tree));
|
||||
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));
|
||||
@ -879,7 +879,7 @@ convert_class_to_reference (t, s, expr)
|
||||
{
|
||||
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));
|
||||
@ -891,7 +891,7 @@ convert_class_to_reference (t, s, expr)
|
||||
{
|
||||
candidates
|
||||
= add_template_candidate (candidates,
|
||||
f,
|
||||
f, s,
|
||||
NULL_TREE,
|
||||
arglist,
|
||||
build_reference_type (t),
|
||||
@ -914,13 +914,11 @@ convert_class_to_reference (t, s, expr)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1235,12 +1233,15 @@ add_candidate (candidates, fn, convs, viable)
|
||||
|
||||
/* 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));
|
||||
@ -1307,25 +1308,31 @@ add_function_candidate (candidates, fn, arglist, flags)
|
||||
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);
|
||||
}
|
||||
@ -1338,8 +1345,7 @@ add_function_candidate (candidates, fn, arglist, flags)
|
||||
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;
|
||||
@ -2090,16 +2096,16 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
|
||||
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;
|
||||
@ -2124,7 +2130,8 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
|
||||
/* 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
|
||||
@ -2152,16 +2159,16 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@ -2172,8 +2179,8 @@ add_template_conv_candidate (candidates, tmpl, obj, arglist, return_type)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
@ -2290,12 +2297,12 @@ build_user_type_conversion_1 (totype, expr, flags)
|
||||
{
|
||||
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)
|
||||
@ -2336,16 +2343,23 @@ build_user_type_conversion_1 (totype, expr, flags)
|
||||
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)
|
||||
@ -2356,7 +2370,7 @@ build_user_type_conversion_1 (totype, expr, flags)
|
||||
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;
|
||||
@ -2491,21 +2505,17 @@ build_new_function_call (fn, args)
|
||||
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))
|
||||
@ -2572,7 +2582,7 @@ build_object_call (obj, args)
|
||||
|
||||
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))
|
||||
@ -2581,16 +2591,16 @@ build_object_call (obj, args)
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2617,9 +2627,6 @@ build_object_call (obj, args)
|
||||
}
|
||||
else
|
||||
candidates = add_conv_candidate (candidates, fn, obj, args);
|
||||
|
||||
if (candidates)
|
||||
candidates->basetype_path = TREE_PURPOSE (convs);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3184,12 +3191,13 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
||||
{
|
||||
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)))
|
||||
@ -3203,7 +3211,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
||||
|
||||
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))
|
||||
{
|
||||
@ -3220,16 +3228,16 @@ build_new_op (code, flags, arg1, arg2, arg3)
|
||||
/* 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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -3547,7 +3555,7 @@ build_op_delete_call (code, addr, size, flags, placement)
|
||||
{
|
||||
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));
|
||||
}
|
||||
|
||||
@ -3567,7 +3575,7 @@ build_op_delete_call (code, addr, size, flags, placement)
|
||||
{
|
||||
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)));
|
||||
@ -4254,6 +4262,7 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
||||
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))
|
||||
@ -4282,16 +4291,16 @@ build_new_method_call (instance, name, args, basetype_path, flags)
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
134
gcc/cp/class.c
134
gcc/cp/class.c
@ -91,7 +91,7 @@ static void add_virtual_function PARAMS ((tree *, tree *, int *, tree, tree));
|
||||
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));
|
||||
@ -1441,8 +1441,7 @@ void
|
||||
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);
|
||||
@ -1558,20 +1557,27 @@ add_method (type, fields, method)
|
||||
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
|
||||
@ -1715,14 +1721,12 @@ delete_duplicate_fields (fields)
|
||||
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;
|
||||
{
|
||||
@ -1746,7 +1750,7 @@ alter_access (t, binfo, fdecl, access)
|
||||
}
|
||||
else
|
||||
{
|
||||
enforce_access (binfo, fdecl);
|
||||
enforce_access (t, fdecl);
|
||||
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
|
||||
return 1;
|
||||
}
|
||||
@ -1768,11 +1772,7 @@ handle_using_decl (using_decl, t)
|
||||
: 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)
|
||||
@ -1793,57 +1793,58 @@ handle_using_decl (using_decl, t)
|
||||
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);
|
||||
}
|
||||
|
||||
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 (is_overloaded_fn (old_value))
|
||||
old_value = OVL_CURRENT (old_value);
|
||||
|
||||
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 (DECL_P (old_value) && DECL_CONTEXT (old_value) == t)
|
||||
/* OK */;
|
||||
else
|
||||
old_value = NULL_TREE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Run through the base clases of T, updating
|
||||
@ -4413,17 +4414,12 @@ check_bases_and_members (t, empty_p)
|
||||
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
|
||||
|
10
gcc/cp/cvt.c
10
gcc/cp/cvt.c
@ -635,15 +635,7 @@ tree
|
||||
convert_pointer_to (binfo, expr)
|
||||
tree binfo, expr;
|
||||
{
|
||||
tree type;
|
||||
|
||||
if (TREE_CODE (binfo) == TREE_VEC)
|
||||
type = BINFO_TYPE (binfo);
|
||||
else if (IS_AGGR_TYPE (binfo))
|
||||
type = binfo;
|
||||
else
|
||||
type = binfo;
|
||||
return convert_pointer_to_real (type, expr);
|
||||
return convert_pointer_to_real (binfo, expr);
|
||||
}
|
||||
|
||||
/* C++ conversions, preference to static cast conversions. */
|
||||
|
@ -1611,8 +1611,7 @@ build_offset_ref (type, name)
|
||||
if (member == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* A lot of this logic is now handled in lookup_field and
|
||||
lookup_fnfield. */
|
||||
/* A lot of this logic is now handled in lookup_member. */
|
||||
if (member && BASELINK_P (member))
|
||||
{
|
||||
/* Go from the TREE_BASELINK to the member function info. */
|
||||
@ -1648,7 +1647,6 @@ build_offset_ref (type, name)
|
||||
t = OVL_CURRENT (t);
|
||||
|
||||
/* unique functions are handled easily. */
|
||||
basebinfo = TREE_PURPOSE (fnfields);
|
||||
if (!enforce_access (basebinfo, t))
|
||||
return error_mark_node;
|
||||
mark_used (t);
|
||||
@ -1776,29 +1774,24 @@ resolve_offset_ref (exp)
|
||||
if (TREE_CODE (member) == FIELD_DECL
|
||||
&& (base == current_class_ref || is_dummy_object (base)))
|
||||
{
|
||||
tree basetype_path;
|
||||
tree expr;
|
||||
|
||||
basetype = DECL_CONTEXT (member);
|
||||
|
||||
/* Try to get to basetype from 'this'; if that doesn't work,
|
||||
nothing will. */
|
||||
base = current_class_ref;
|
||||
|
||||
/* First convert to the intermediate base specified, if appropriate. */
|
||||
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
|
||||
basetype = TYPE_OFFSET_BASETYPE (type);
|
||||
else
|
||||
basetype = DECL_CONTEXT (member);
|
||||
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
|
||||
|
||||
base = current_class_ptr;
|
||||
addr = build_unary_op (ADDR_EXPR, base, 0);
|
||||
addr = convert_pointer_to (basetype, addr);
|
||||
|
||||
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
|
||||
{
|
||||
error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
|
||||
return error_mark_node;
|
||||
}
|
||||
/* Kludge: we need to use basetype_path now, because
|
||||
convert_pointer_to will bash it. */
|
||||
enforce_access (basetype_path, member);
|
||||
addr = convert_pointer_to (basetype, base);
|
||||
if (addr == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
/* Even in the case of illegal access, we form the
|
||||
COMPONENT_REF; that will allow better error recovery than
|
||||
just feeding back error_mark_node. */
|
||||
expr = build (COMPONENT_REF, TREE_TYPE (member),
|
||||
build_indirect_ref (addr, NULL_PTR), member);
|
||||
return convert_from_reference (expr);
|
||||
|
@ -1606,7 +1606,15 @@ lookup_member (xbasetype, name, protect, want_type)
|
||||
|
||||
if (rval && is_overloaded_fn (rval))
|
||||
{
|
||||
rval = tree_cons (basetype_path, rval, NULL_TREE);
|
||||
/* Note that the binfo we put in the baselink is the binfo where
|
||||
we found the functions, which we need for overload
|
||||
resolution, but which should not be passed to enforce_access;
|
||||
rather, enforce_access wants a binfo which refers to the
|
||||
scope in which we started looking for the function. This
|
||||
will generally be the binfo passed into this function as
|
||||
xbasetype. */
|
||||
|
||||
rval = tree_cons (rval_binfo, rval, NULL_TREE);
|
||||
SET_BASELINK_P (rval);
|
||||
}
|
||||
|
||||
|
@ -2151,7 +2151,7 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||
if (DECL_STATIC_FUNCTION_P (TREE_VALUE (fndecls)))
|
||||
{
|
||||
tree fndecl = TREE_VALUE (fndecls);
|
||||
enforce_access (TREE_PURPOSE (fndecls), fndecl);
|
||||
enforce_access (basetype_path, fndecl);
|
||||
mark_used (fndecl);
|
||||
return fndecl;
|
||||
}
|
||||
@ -2221,7 +2221,8 @@ build_component_ref (datum, component, basetype_path, protect)
|
||||
else
|
||||
addr = convert_pointer_to (base, addr);
|
||||
datum = build_indirect_ref (addr, NULL_PTR);
|
||||
my_friendly_assert (datum != error_mark_node, 311);
|
||||
if (datum == error_mark_node)
|
||||
return error_mark_node;
|
||||
}
|
||||
basetype = base;
|
||||
|
||||
|
@ -1031,7 +1031,11 @@ process_init_constructor (type, init, elts)
|
||||
|
||||
x.A::ii refers to the ii member of the L part of
|
||||
the A part of the C object named by X. In this case,
|
||||
DATUM would be x, and BASETYPE would be A. */
|
||||
DATUM would be x, and BASETYPE would be A.
|
||||
|
||||
Note that this is nonconformant; the standard specifies that first
|
||||
we look up ii in A, then convert x to an L& and pull out the ii part.
|
||||
But narrowing seems to be standard practice, so let's do it anyway. */
|
||||
|
||||
tree
|
||||
build_scoped_ref (datum, basetype)
|
||||
@ -1044,43 +1048,15 @@ build_scoped_ref (datum, basetype)
|
||||
if (datum == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||
type = TREE_TYPE (type);
|
||||
/* Don't do this if it would cause an error or if we're being pedantic. */
|
||||
if (! ACCESSIBLY_UNIQUELY_DERIVED_P (basetype, type)
|
||||
|| pedantic)
|
||||
return datum;
|
||||
|
||||
type = TYPE_MAIN_VARIANT (type);
|
||||
ref = build_unary_op (ADDR_EXPR, datum, 0);
|
||||
ref = convert_pointer_to (basetype, ref);
|
||||
|
||||
/* This is an easy conversion. */
|
||||
if (is_aggr_type (basetype, 1))
|
||||
{
|
||||
tree binfo = TYPE_BINFO (basetype);
|
||||
if (binfo != TYPE_BINFO (type))
|
||||
{
|
||||
binfo = get_binfo (binfo, type, 1);
|
||||
if (binfo == error_mark_node)
|
||||
return error_mark_node;
|
||||
if (binfo == 0)
|
||||
return error_not_base_type (basetype, type);
|
||||
}
|
||||
|
||||
switch (TREE_CODE (datum))
|
||||
{
|
||||
case NOP_EXPR:
|
||||
case CONVERT_EXPR:
|
||||
case FLOAT_EXPR:
|
||||
case FIX_TRUNC_EXPR:
|
||||
case FIX_FLOOR_EXPR:
|
||||
case FIX_ROUND_EXPR:
|
||||
case FIX_CEIL_EXPR:
|
||||
ref = convert_pointer_to (binfo,
|
||||
build_unary_op (ADDR_EXPR, TREE_OPERAND (datum, 0), 0));
|
||||
break;
|
||||
default:
|
||||
ref = convert_pointer_to (binfo,
|
||||
build_unary_op (ADDR_EXPR, datum, 0));
|
||||
}
|
||||
return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
|
||||
}
|
||||
return error_mark_node;
|
||||
return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
|
||||
}
|
||||
|
||||
/* Build a reference to an object specified by the C++ `->' operator.
|
||||
|
Loading…
Reference in New Issue
Block a user