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:
Jason Merrill 2000-02-27 06:54:04 +00:00 committed by Jason Merrill
parent 0172e2bc87
commit aa52c1ffad
8 changed files with 205 additions and 201 deletions

View File

@ -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

View File

@ -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));
@ -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;
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;
}
}

View File

@ -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,21 +1557,28 @@ 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)
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))
{
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
non-template class, it's mangled name can be used
@ -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. */
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;
}
if (is_overloaded_fn (fdecl))
flist = fdecl;
fdecl = OVL_FUNCTION (flist);
}
else if (! DECL_LANG_SPECIFIC (fdecl))
my_friendly_abort (20000221);
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)
if (! old_value)
;
else if (is_overloaded_fn (old_value))
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
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
{
cp_error ("`%D' invalid in `%#T'", using_decl, t);
cp_error_at (" because of local method `%#D' with same name",
OVL_CURRENT (TREE_VEC_ELT (method_vec, i)));
OVL_CURRENT (old_value));
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)
}
else
{
cp_error ("cannot adjust access to `%#D' in `%#T'", fdecl, t);
cp_error_at (" because of local field `%#D' with same name", tmp);
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))
{
while (flist)
{
if (alter_access (t, binfo, OVL_FUNCTION (flist),
access) == 0)
return;
flist = OVL_CHAIN (flist);
}
add_method (t, 0, OVL_CURRENT (flist));
alter_access (t, OVL_CURRENT (flist), access);
}
else
alter_access (t, binfo, fdecl, access);
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

View File

@ -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. */

View File

@ -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;
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
basetype = TYPE_OFFSET_BASETYPE (type);
else
basetype = DECL_CONTEXT (member);
base = current_class_ptr;
/* Try to get to basetype from 'this'; if that doesn't work,
nothing will. */
base = current_class_ref;
if (get_base_distance (basetype, TREE_TYPE (TREE_TYPE (base)), 0, &basetype_path) < 0)
{
error_not_base_type (basetype, TREE_TYPE (TREE_TYPE (base)));
/* First convert to the intermediate base specified, if appropriate. */
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
addr = build_unary_op (ADDR_EXPR, base, 0);
addr = convert_pointer_to (basetype, addr);
if (addr == error_mark_node)
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);
/* 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);

View File

@ -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);
}

View File

@ -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;

View File

@ -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,44 +1048,16 @@ 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;
}
/* Build a reference to an object specified by the C++ `->' operator.
Usually this just involves dereferencing the object, but if the