This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [C++ PATCH] fix 3145
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: Mark Mitchell <mark at codesourcery dot com>
- Cc: "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>
- Date: Thu, 22 Nov 2001 12:45:14 +0000
- Subject: Re: [C++ PATCH] fix 3145
- Organization: Codesourcery LLC
- References: <70600000.1006366891@gandalf.codesourcery.com>
Mark Mitchell wrote:
>
> I'm not sure I quite understand the interface. Maybe this is the
> right comment, or at least something close:
>
> /* Convert EXPR (an expression whose type is `A' or `A*'
> for some class type `A') to the base subobject `B' given by
> BINFO. The expression returned will be of type `B' or `B*', matching
> the form provided in EXPR. If CODE is PLUS_EXPR, `A' is derived
> from `B'; if it is MINUS_EXPR `B' is derived from `A'. (In the latter
> case, there must be no virtual bases along the path from `A' to
> `B'.) NONNULL is true if EXPR is known to be non-NULL. */
How's this?
! /* Convert to or from a base subobject. EXPR is an expression of type
! `A' or `A*', an expression of type `B' or `B*' is returned. To
! convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for
! the B base instance within A. To convert base A to derived B, CODE
! is MINUS_EXPR and BINFO is the binfo for the A instance within B.
! In this latter case, A must not be a morally virtual base of B.
! NONNULL is true if EXPR is known to be non-NULL (this is only
! needed when EXPR is of pointer type). CV qualifiers are preserved
! from EXPR. */
BTW, the CODE parameter could be inferred from BINFO, I just kept a
similar interface to that which build_vbase_path had. For derived->base
(PLUS_EXPR), TYPE_BINFO (BINFO) will not be the type of EXPR, for
base->derived (MINUS_EXPR) it will be. The nop case where we're
converting from A to A results in no code, so it doesn't matter what CODE
we pick.) I could make that change, but the more verbose way adds that
extra consistency check.
> ! /* If EXPR is NULL, then we don't need to do any arithmetic
> ! to convert it:
> !
> ! [conv.ptr]
> !
> ! The null pointer value is converted to the null pointer
> ! value of the destination type. */
> ! && !integer_zerop (expr))
>
> Where did this check go in the new code? Or is it no longer necessary?
It is no longer necessary, (A*)(B*)0 does indeed result in no code.
+ /* Worker for lookup_base. BINFO is the binfo we are searching at,
+ BASE is the RECORD_TYPE we are searching for. ACCESS is the
+ required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
+ IS_VIRTUAL indicate how BINFO was reached from the start of the
+ search. WITHIN_CURRENT_SCOPE is true if we met the current scope,
+ or friend thereof (this allows us to determine whether a protected
+ base is accessible or not). IS_NON_PUBLIC indicates whether BINFO
+ is accessible and IS_VIRTUAL indicates if it is morally virtual.
+
+ If BINFO is of the required type, then *BINFO_PTR is examined to
+ compare with any other instance of BASE we might have already
+ discovered. *BINFO_PTR is initialized and a base_kind return value
+ indicates what kind of base was located.
+
+ Otherwise BINFO's bases are searched. */
+
+ static base_kind
+ lookup_base_r (binfo, base, access, within_current_scope,
ok?
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2001-11-22 Nathan Sidwell <nathan@codesourcery.com>
PR g++/3145
* class.c (build_vbase_pointer): Remove.
(build_vbase_path): Remove.
(build_base_path): New function.
* cp-tree.h (base_access, base_kind): New enumerations.
(build_base_path): Declare.
(convert_pointer_to_real): Remove.
(convert_pointer_to): Remove.
(lookup_base): Declare.
(convert_pointer_to_vbase): Remove.
* call.c (build_scoped_method_call): Use lookup_base &
build_base_path instead of convert_pointer_to_real,
get_base_distance & get_binfo.
(build_over_call): Likewise.
* cvt.c (cp_convert_to_pointer): Likewise.
(convert_to_pointer_force): Likewise.
(build_up_reference): Likewise.
(convert_pointer_to_real): Remove.
(convert_pointer_to): Remove.
* init.c (dfs_initialize_vtbl_ptrs): Use build_base_path
instead of convert_pointer_to_vbase & build_vbase_path.
(emit_base_init): Use build_base_path instead of
convert_pointer_to_real.
(expand_virtual_init): Lose unrequired conversions.
(resolve_offset_ref): Use lookup_base and build_base_path
instead of convert_pointer_to.
*rtti.c (build_dynamic_cast_1): Use lookup_base &
build_base_path instead of get_base_distance & build_vbase_path.
*search.c (get_vbase_1): Remove.
(get_vbase): Remove.
(convert_pointer_to_vbase): Remove.
(lookup_base_recursive): New function.
(lookup_base): New function.
* typeck.c (require_complete_type): Use lookup_base &
build_base_path instead of convert_pointer_to.
(build_component_ref): Likewise.
(build_x_function_call): Likewise.
(get_member_function_from_ptrfunc): Likewise.
(build_component_addr): Likewise.
* typeck2.c (build_scoped_ref): Likewise.
Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.287
diff -c -3 -p -r1.287 call.c
*** call.c 2001/11/20 09:00:31 1.287
--- call.c 2001/11/22 12:02:47
*************** build_scoped_method_call (exp, basetype,
*** 298,304 ****
if (! binfo)
{
! binfo = get_binfo (basetype, type, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (! binfo)
--- 298,304 ----
if (! binfo)
{
! binfo = lookup_base (type, basetype, ba_check, NULL);
if (binfo == error_mark_node)
return error_mark_node;
if (! binfo)
*************** build_scoped_method_call (exp, basetype,
*** 308,316 ****
if (binfo)
{
if (TREE_CODE (exp) == INDIRECT_REF)
! decl = build_indirect_ref
! (convert_pointer_to_real
! (binfo, build_unary_op (ADDR_EXPR, exp, 0)), NULL);
else
decl = build_scoped_ref (exp, basetype);
--- 308,319 ----
if (binfo)
{
if (TREE_CODE (exp) == INDIRECT_REF)
! {
! decl = build_base_path (PLUS_EXPR,
! build_unary_op (ADDR_EXPR, exp, 0),
! binfo, 1);
! decl = build_indirect_ref (decl, NULL);
! }
else
decl = build_scoped_ref (exp, basetype);
*************** build_over_call (cand, args, flags)
*** 4157,4163 ****
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
! t = convert_pointer_to_real (TREE_TYPE (parmtype), TREE_VALUE (arg));
converted_args = tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
--- 4160,4168 ----
So we can assume that anything passed as 'this' is non-null, and
optimize accordingly. */
my_friendly_assert (TREE_CODE (parmtype) == POINTER_TYPE, 19990811);
! t = lookup_base (TREE_TYPE (TREE_TYPE (TREE_VALUE (arg))),
! TREE_TYPE (parmtype), ba_ignore, NULL);
! t = build_base_path (PLUS_EXPR, TREE_VALUE (arg), t, 1);
converted_args = tree_cons (NULL_TREE, t, converted_args);
parm = TREE_CHAIN (parm);
arg = TREE_CHAIN (arg);
*************** build_over_call (cand, args, flags)
*** 4307,4315 ****
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
tree t, *p = &TREE_VALUE (converted_args);
! tree binfo = get_binfo
! (DECL_VIRTUAL_CONTEXT (fn), TREE_TYPE (TREE_TYPE (*p)), 0);
! *p = convert_pointer_to_real (binfo, *p);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
t = build_pointer_type (TREE_TYPE (fn));
--- 4312,4323 ----
if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
{
tree t, *p = &TREE_VALUE (converted_args);
! tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (*p)),
! DECL_VIRTUAL_CONTEXT (fn),
! ba_any, NULL);
! my_friendly_assert (binfo && binfo != error_mark_node, 20010730);
!
! *p = build_base_path (PLUS_EXPR, *p, binfo, 1);
if (TREE_SIDE_EFFECTS (*p))
*p = save_expr (*p);
t = build_pointer_type (TREE_TYPE (fn));
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.416
diff -c -3 -p -r1.416 class.c
*** class.c 2001/11/09 23:08:36 1.416
--- class.c 2001/11/22 12:02:50
*************** varray_type local_classes;
*** 106,112 ****
static tree get_vfield_name PARAMS ((tree));
static void finish_struct_anon PARAMS ((tree));
- static tree build_vbase_pointer PARAMS ((tree, tree));
static tree build_vtable_entry PARAMS ((tree, tree, tree));
static tree get_vtable_name PARAMS ((tree));
static tree get_basefndecls PARAMS ((tree, tree));
--- 106,111 ----
*************** int n_build_method_call = 0;
*** 236,425 ****
int n_inner_fields_searched = 0;
#endif
! /* Virtual base class layout. */
- /* Returns a pointer to the virtual base class of EXP that has the
- indicated TYPE. EXP is of class type, not a pointer type. */
-
- static tree
- build_vbase_pointer (exp, type)
- tree exp, type;
- {
- tree vbase;
- tree vbase_ptr;
-
- /* Find the shared copy of TYPE; that's where the vtable offset is
- recorded. */
- vbase = binfo_for_vbase (type, TREE_TYPE (exp));
- /* Find the virtual function table pointer. */
- vbase_ptr = build_vfield_ref (exp, TREE_TYPE (exp));
- /* Compute the location where the offset will lie. */
- vbase_ptr = build (PLUS_EXPR,
- TREE_TYPE (vbase_ptr),
- vbase_ptr,
- BINFO_VPTR_FIELD (vbase));
- vbase_ptr = build1 (NOP_EXPR,
- build_pointer_type (ptrdiff_type_node),
- vbase_ptr);
- /* Add the contents of this location to EXP. */
- return build (PLUS_EXPR,
- build_pointer_type (type),
- build_unary_op (ADDR_EXPR, exp, /*noconvert=*/0),
- build1 (INDIRECT_REF, ptrdiff_type_node, vbase_ptr));
- }
-
- /* Build multi-level access to EXPR using hierarchy path PATH.
- CODE is PLUS_EXPR if we are going with the grain,
- and MINUS_EXPR if we are not (in which case, we cannot traverse
- virtual baseclass links).
-
- TYPE is the type we want this path to have on exit.
-
- NONNULL is non-zero if we know (for any reason) that EXPR is
- not, in fact, zero. */
-
tree
! build_vbase_path (code, type, expr, path, nonnull)
enum tree_code code;
! tree type, expr, path;
int nonnull;
{
! register int changed = 0;
! tree last = NULL_TREE, last_virtual = NULL_TREE;
int fixed_type_p;
! tree null_expr = 0, nonnull_expr;
! tree basetype;
! tree offset = integer_zero_node;
! if (BINFO_INHERITANCE_CHAIN (path) == NULL_TREE)
! return build1 (NOP_EXPR, type, expr);
- /* We could do better if we had additional logic to convert back to the
- unconverted type (the static type of the complete object), and then
- convert back to the type we want. Until that is done, we only optimize
- if the complete type is the same type as expr has. */
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
if (fixed_type_p < 0)
/* Virtual base layout is not fixed, even in ctors and dtors. */
fixed_type_p = 0;
-
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
! nonnull_expr = expr;
!
! path = reverse_path (path);
!
! basetype = BINFO_TYPE (path);
!
! while (path)
{
! if (TREE_VIA_VIRTUAL (TREE_VALUE (path)))
! {
! last_virtual = BINFO_TYPE (TREE_VALUE (path));
! if (code == PLUS_EXPR)
! {
! changed = ! fixed_type_p;
!
! if (changed)
! {
! tree ind;
!
! /* We already check for ambiguous things in the caller, just
! find a path. */
! if (last)
! {
! tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0);
! nonnull_expr = convert_pointer_to_real (binfo, nonnull_expr);
! }
! ind = build_indirect_ref (nonnull_expr, NULL);
! nonnull_expr = build_vbase_pointer (ind, last_virtual);
! if (nonnull == 0
! && TREE_CODE (type) == POINTER_TYPE
! && null_expr == NULL_TREE)
! {
! null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);
! expr = build (COND_EXPR, build_pointer_type (last_virtual),
! build (EQ_EXPR, boolean_type_node, expr,
! integer_zero_node),
! null_expr, nonnull_expr);
! }
! }
! /* else we'll figure out the offset below. */
! /* Happens in the case of parse errors. */
! if (nonnull_expr == error_mark_node)
! return error_mark_node;
! }
! else
! {
! cp_error ("cannot cast up from virtual baseclass `%T'",
! last_virtual);
! return error_mark_node;
! }
! }
! last = TREE_VALUE (path);
! path = TREE_CHAIN (path);
}
- /* LAST is now the last basetype assoc on the path. */
! /* A pointer to a virtual base member of a non-null object
! is non-null. Therefore, we only need to test for zeroness once.
! Make EXPR the canonical expression to deal with here. */
! if (null_expr)
! {
! TREE_OPERAND (expr, 2) = nonnull_expr;
! TREE_TYPE (expr) = TREE_TYPE (TREE_OPERAND (expr, 1))
! = TREE_TYPE (nonnull_expr);
! }
! else
! expr = nonnull_expr;
! /* If we go through any virtual base pointers, make sure that
! casts to BASETYPE from the last virtual base class use
! the right value for BASETYPE. */
! if (changed)
! {
! tree intype = TREE_TYPE (TREE_TYPE (expr));
!
! if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last))
! offset
! = BINFO_OFFSET (get_binfo (last, TYPE_MAIN_VARIANT (intype), 0));
! }
else
! offset = BINFO_OFFSET (last);
!
! if (! integer_zerop (offset))
! {
! /* Bash types to make the backend happy. */
! offset = cp_convert (type, offset);
!
! /* If expr might be 0, we need to preserve that zeroness. */
! if (nonnull == 0)
! {
! if (null_expr)
! TREE_TYPE (null_expr) = type;
! else
! null_expr = build1 (NOP_EXPR, type, integer_zero_node);
! if (TREE_SIDE_EFFECTS (expr))
! expr = save_expr (expr);
!
! return build (COND_EXPR, type,
! build (EQ_EXPR, boolean_type_node, expr, integer_zero_node),
! null_expr,
! build (code, type, expr, offset));
! }
! else return build (code, type, expr, offset);
! }
! /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may
! be used multiple times in initialization of multiple inheritance. */
! if (null_expr)
! {
! TREE_TYPE (expr) = type;
! return expr;
! }
! else
! return build1 (NOP_EXPR, type, expr);
}
--- 235,356 ----
int n_inner_fields_searched = 0;
#endif
! /* Convert to or from a base subobject. EXPR is an expression of type
! `A' or `A*', an expression of type `B' or `B*' is returned. To
! convert A to a base B, CODE is PLUS_EXPR and BINFO is the binfo for
! the B base instance within A. To convert base A to derived B, CODE
! is MINUS_EXPR and BINFO is the binfo for the A instance within B.
! In this latter case, A must not be a morally virtual base of B.
! NONNULL is true if EXPR is known to be non-NULL (this is only
! needed when EXPR is of pointer type). CV qualifiers are preserved
! from EXPR. */
tree
! build_base_path (code, expr, binfo, nonnull)
enum tree_code code;
! tree expr;
! tree binfo;
int nonnull;
{
! tree v_binfo = NULL_TREE;
! tree t;
! tree probe;
! tree offset;
! tree target_type;
! tree null_test = NULL;
! tree ptr_target_type;
int fixed_type_p;
! int want_pointer = TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE;
! if (expr == error_mark_node || binfo == error_mark_node || !binfo)
! return error_mark_node;
!
! for (probe = binfo; probe;
! t = probe, probe = BINFO_INHERITANCE_CHAIN (probe))
! if (!v_binfo && TREE_VIA_VIRTUAL (probe))
! v_binfo = probe;
!
! probe = TYPE_MAIN_VARIANT (TREE_TYPE (expr));
! if (want_pointer)
! probe = TYPE_MAIN_VARIANT (TREE_TYPE (probe));
!
! my_friendly_assert (code == MINUS_EXPR
! ? same_type_p (BINFO_TYPE (binfo), probe)
! : code == PLUS_EXPR
! ? same_type_p (BINFO_TYPE (t), probe)
! : false, 20010723);
!
! if (code == MINUS_EXPR && v_binfo)
! {
! cp_error ("cannot convert from base `%T' to derived type `%T' via virtual base `%T'",
! BINFO_TYPE (binfo), BINFO_TYPE (t), BINFO_TYPE (v_binfo));
! return error_mark_node;
! }
fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);
if (fixed_type_p < 0)
/* Virtual base layout is not fixed, even in ctors and dtors. */
fixed_type_p = 0;
if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))
expr = save_expr (expr);
!
! if (!want_pointer)
! expr = build_unary_op (ADDR_EXPR, expr, 0);
! else if (!nonnull)
! null_test = build (EQ_EXPR, boolean_type_node, expr, integer_zero_node);
!
! offset = BINFO_OFFSET (binfo);
!
! if (v_binfo && !fixed_type_p)
{
! /* Going via virtual base V_BINFO. We need the static offset
! from V_BINFO to BINFO, and the dynamic offset from T to
! V_BINFO. That offset is an entry in T's vtable. */
! tree v_offset = build_vfield_ref (build_indirect_ref (expr, NULL),
! TREE_TYPE (TREE_TYPE (expr)));
!
! v_binfo = binfo_for_vbase (BINFO_TYPE (v_binfo), BINFO_TYPE (t));
!
! v_offset = build (PLUS_EXPR, TREE_TYPE (v_offset),
! v_offset, BINFO_VPTR_FIELD (v_binfo));
! v_offset = build1 (NOP_EXPR,
! build_pointer_type (ptrdiff_type_node),
! v_offset);
! v_offset = build_indirect_ref (v_offset, NULL);
!
! offset = cp_convert (ptrdiff_type_node,
! size_diffop (offset, BINFO_OFFSET (v_binfo)));
! if (!integer_zerop (offset))
! offset = build (code, ptrdiff_type_node, v_offset, offset);
! else
! offset = v_offset;
}
! target_type = code == PLUS_EXPR ? BINFO_TYPE (binfo) : BINFO_TYPE (t);
!
! target_type = cp_build_qualified_type
! (target_type, CP_TYPE_QUALS (TREE_TYPE (TREE_TYPE (expr))));
! ptr_target_type = build_pointer_type (target_type);
! if (want_pointer)
! target_type = ptr_target_type;
!
! expr = build1 (NOP_EXPR, ptr_target_type, expr);
! if (!integer_zerop (offset))
! expr = build (code, ptr_target_type, expr, offset);
else
! null_test = NULL;
!
! if (!want_pointer)
! expr = build_indirect_ref (expr, NULL);
! if (null_test)
! expr = build (COND_EXPR, target_type, null_test,
! build1 (NOP_EXPR, target_type, integer_zero_node),
! expr);
!
! return expr;
}
*************** fixed_type_or_null (instance, nonnull, c
*** 5468,5478 ****
}
}
! /* Return non-zero if the dynamic type of INSTANCE is known, and equivalent
! to the static type. We also handle the case where INSTANCE is really
! a pointer. Return negative if this is a ctor/dtor. There the dynamic type
! is known, but this might not be the most derived base of the original object,
! and hence virtual bases may not be layed out according to this type.
Used to determine whether the virtual function table is needed
or not.
--- 5399,5410 ----
}
}
! /* Return non-zero if the dynamic type of INSTANCE is known, and
! equivalent to the static type. We also handle the case where
! INSTANCE is really a pointer. Return negative if this is a
! ctor/dtor. There the dynamic type is known, but this might not be
! the most derived base of the original object, and hence virtual
! bases may not be layed out according to this type.
Used to determine whether the virtual function table is needed
or not.
Index: cp/cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.655
diff -c -3 -p -r1.655 cp-tree.h
*** cp-tree.h 2001/11/16 19:17:32 1.655
--- cp-tree.h 2001/11/22 12:02:51
*************** typedef enum instantiate_type_flags {
*** 3022,3027 ****
--- 3022,3050 ----
itf_ptrmem_ok = 1 << 2, /* pointers to member ok (internal use) */
} instantiate_type_flags;
+ /* The kind of checking we can do looking in a class heirarchy. */
+ typedef enum base_access {
+ ba_any = -2, /* Do not check access, allow an ambiguous base,
+ prefer a non-virtual base */
+ ba_ignore = -1, /* Do not check access */
+ ba_check = 0, /* Check access */
+ ba_not_special /* Do not consider special privilege
+ current_class_type might give. */
+ } base_access;
+
+ /* The kind of base we can find, looking in a class heirarchy.
+ values <0 indicate we failed. */
+ typedef enum base_kind {
+ bk_inaccessible = -3, /* The base is inaccessible */
+ bk_ambig = -2, /* The base is ambiguous */
+ bk_not_base = -1, /* It is not a base */
+ bk_same_type = 0, /* It is the same type */
+ bk_proper_base = 1, /* It is a proper base */
+ bk_via_virtual = 2 /* It is a proper base, but via a virtual
+ path. This might not be the canonical
+ binfo. */
+ } base_kind;
+
/* Nonzero means allow Microsoft extensions without a pedwarn. */
extern int flag_ms_extensions;
*************** extern tree strip_top_quals
*** 3512,3517 ****
--- 3535,3541 ----
extern tree perform_implicit_conversion PARAMS ((tree, tree));
/* in class.c */
+ extern tree build_base_path PARAMS ((enum tree_code, tree, tree, int));
extern tree build_vbase_path PARAMS ((enum tree_code, tree, tree, tree, int));
extern tree build_vtbl_ref PARAMS ((tree, tree));
extern tree build_vfn_ref PARAMS ((tree, tree));
*************** extern tree get_primary_binfo
*** 3558,3565 ****
extern tree convert_to_reference PARAMS ((tree, tree, int, int, tree));
extern tree convert_from_reference PARAMS ((tree));
extern tree convert_lvalue PARAMS ((tree, tree));
- extern tree convert_pointer_to_real PARAMS ((tree, tree));
- extern tree convert_pointer_to PARAMS ((tree, tree));
extern tree ocp_convert PARAMS ((tree, tree, int, int));
extern tree cp_convert PARAMS ((tree, tree));
extern tree convert_to_void PARAMS ((tree, const char */*implicit context*/));
--- 3582,3587 ----
*************** extern int tinfo_decl_p
*** 3984,3989 ****
--- 4006,4012 ----
extern int emit_tinfo_decl PARAMS((tree *, void *));
/* in search.c */
+ extern tree lookup_base PARAMS ((tree, tree, base_access, base_kind *));
extern int types_overlap_p PARAMS ((tree, tree));
extern tree get_vbase PARAMS ((tree, tree));
extern tree get_binfo PARAMS ((tree, tree, int));
*************** extern tree dfs_marked_real_bases_queue_
*** 4034,4040 ****
extern tree dfs_skip_vbases PARAMS ((tree, void *));
extern tree marked_vtable_pathp PARAMS ((tree, void *));
extern tree unmarked_vtable_pathp PARAMS ((tree, void *));
- extern tree convert_pointer_to_vbase PARAMS ((tree, tree));
extern tree find_vbase_instance PARAMS ((tree, tree));
extern tree binfo_for_vbase PARAMS ((tree, tree));
extern tree binfo_via_virtual PARAMS ((tree, tree));
--- 4057,4062 ----
Index: cp/cvt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cvt.c,v
retrieving revision 1.106
diff -c -3 -p -r1.106 cvt.c
*** cvt.c 2001/11/15 15:09:35 1.106
--- cvt.c 2001/11/22 12:02:51
*************** cp_convert_to_pointer (type, expr, force
*** 141,184 ****
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (type))
&& IS_AGGR_TYPE (TREE_TYPE (intype))
! && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE
! /* If EXPR is NULL, then we don't need to do any arithmetic
! to convert it:
!
! [conv.ptr]
!
! The null pointer value is converted to the null pointer
! value of the destination type. */
! && !integer_zerop (expr))
{
enum tree_code code = PLUS_EXPR;
! tree binfo = get_binfo (TREE_TYPE (type), TREE_TYPE (intype), 1);
! if (binfo == error_mark_node)
! return error_mark_node;
! if (binfo == NULL_TREE)
{
! binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 1);
! if (binfo == error_mark_node)
! return error_mark_node;
code = MINUS_EXPR;
}
if (binfo)
{
! if (TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (type))
! || TYPE_USES_VIRTUAL_BASECLASSES (TREE_TYPE (intype))
! || ! BINFO_OFFSET_ZEROP (binfo))
{
! /* Need to get the path we took. */
! tree path;
!
! if (code == PLUS_EXPR)
! get_base_distance (TREE_TYPE (type), TREE_TYPE (intype),
! 0, &path);
! else
! get_base_distance (TREE_TYPE (intype), TREE_TYPE (type),
! 0, &path);
! return build_vbase_path (code, type, expr, path, 0);
}
}
}
--- 141,175 ----
&& TREE_CODE (TREE_TYPE (type)) == RECORD_TYPE
&& IS_AGGR_TYPE (TREE_TYPE (type))
&& IS_AGGR_TYPE (TREE_TYPE (intype))
! && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
! tree binfo;
!
! /* Try derived to base conversion. */
! binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
! ba_check, NULL);
! if (!binfo)
{
! /* Try base to derived conversion. */
! binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
! ba_check, NULL);
code = MINUS_EXPR;
}
+ if (binfo == error_mark_node)
+ return error_mark_node;
if (binfo)
{
! expr = build_base_path (code, expr, binfo, 0);
! /* Add any qualifier conversions. */
! if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
! TREE_TYPE (type)))
{
! expr = build1 (NOP_EXPR, type, expr);
! TREE_CONSTANT (expr) =
! TREE_CONSTANT (TREE_OPERAND (expr, 0));
}
+ return expr;
}
}
*************** cp_convert_to_pointer (type, expr, force
*** 187,222 ****
tree b1;
tree b2;
tree binfo;
! tree virt_binfo;
! enum tree_code code;
b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
! binfo = get_binfo (b2, b1, 1);
!
! if (binfo == NULL_TREE)
{
! binfo = get_binfo (b1, b2, 1);
code = MINUS_EXPR;
}
- else
- code = PLUS_EXPR;
-
if (binfo == error_mark_node)
return error_mark_node;
! virt_binfo = binfo_from_vbase (binfo);
! if (virt_binfo)
{
if (force)
! cp_warning ("pointer to member cast via virtual base `%T' of `%T'",
! BINFO_TYPE (virt_binfo),
! BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
else
{
! cp_error ("pointer to member cast via virtual base `%T' of `%T'",
! BINFO_TYPE (virt_binfo),
! BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo)));
return error_mark_node;
}
/* This is a reinterpret cast, whose result is unspecified.
--- 178,206 ----
tree b1;
tree b2;
tree binfo;
! enum tree_code code = PLUS_EXPR;
! base_kind bk;
b1 = TYPE_OFFSET_BASETYPE (TREE_TYPE (type));
b2 = TYPE_OFFSET_BASETYPE (TREE_TYPE (intype));
! binfo = lookup_base (b1, b2, ba_check, &bk);
! if (!binfo)
{
! binfo = lookup_base (b2, b1, ba_check, &bk);
code = MINUS_EXPR;
}
if (binfo == error_mark_node)
return error_mark_node;
! if (bk == bk_via_virtual)
{
if (force)
! cp_warning ("pointer to member cast from `%T' to `%T' is via virtual base",
! TREE_TYPE (intype), TREE_TYPE (type));
else
{
! cp_error ("pointer to member cast from `%T' to `%T' is via virtual base",
! TREE_TYPE (intype), TREE_TYPE (type));
return error_mark_node;
}
/* This is a reinterpret cast, whose result is unspecified.
*************** convert_to_pointer_force (type, expr)
*** 319,352 ****
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
! tree path;
! int distance = get_base_distance (TREE_TYPE (type),
! TREE_TYPE (intype), 0, &path);
! if (distance == -2)
{
! cp_error ("type `%T' is ambiguous base of `%T'",
! TREE_TYPE (type),
! TREE_TYPE (intype));
! return error_mark_node;
}
! if (distance == -1)
{
! distance = get_base_distance (TREE_TYPE (intype),
! TREE_TYPE (type), 0, &path);
! if (distance == -2)
! {
! cp_error ("type `%T' is ambiguous base of `%T'",
! TREE_TYPE (intype),
! TREE_TYPE (type));
! return error_mark_node;
! }
! if (distance < 0)
! /* Doesn't need any special help from us. */
! return build1 (NOP_EXPR, type, expr);
!
! code = MINUS_EXPR;
}
! return build_vbase_path (code, type, expr, path, 0);
}
}
--- 303,334 ----
&& TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE)
{
enum tree_code code = PLUS_EXPR;
! tree binfo;
!
! binfo = lookup_base (TREE_TYPE (intype), TREE_TYPE (type),
! ba_ignore, NULL);
! if (!binfo)
{
! binfo = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
! ba_ignore, NULL);
! code = MINUS_EXPR;
}
! if (binfo == error_mark_node)
! return error_mark_node;
! if (binfo)
{
! expr = build_base_path (code, expr, binfo, 0);
! /* Add any qualifier conversions. */
! if (!same_type_p (TREE_TYPE (TREE_TYPE (expr)),
! TREE_TYPE (type)))
! {
! expr = build1 (NOP_EXPR, type, expr);
! TREE_CONSTANT (expr) =
! TREE_CONSTANT (TREE_OPERAND (expr, 0));
! }
! return expr;
}
!
}
}
*************** build_up_reference (type, arg, flags, de
*** 420,431 ****
&& IS_AGGR_TYPE (target_type))
{
/* We go through get_binfo for the access control. */
! tree binfo = get_binfo (target_type, argtype, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype);
! rval = convert_pointer_to_real (binfo, rval);
}
else
rval
--- 402,413 ----
&& IS_AGGR_TYPE (target_type))
{
/* We go through get_binfo for the access control. */
! tree binfo = lookup_base (argtype, target_type, ba_check, NULL);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == NULL_TREE)
return error_not_base_type (target_type, argtype);
! rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
}
else
rval
*************** convert_lvalue (totype, expr)
*** 624,710 ****
expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL,
NULL_TREE);
return convert_from_reference (expr);
- }
-
- /* Call this when we know (for any reason) that expr is not, in fact,
- zero. This routine is like convert_pointer_to, but it pays
- attention to which specific instance of what type we want to
- convert to. This routine should eventually become
- convert_to_pointer after all references to convert_to_pointer
- are removed. */
-
- tree
- convert_pointer_to_real (binfo, expr)
- tree binfo, expr;
- {
- register tree intype = TREE_TYPE (expr);
- tree ptr_type;
- tree type, rval;
-
- if (intype == error_mark_node)
- return error_mark_node;
-
- if (TREE_CODE (binfo) == TREE_VEC)
- type = BINFO_TYPE (binfo);
- else if (IS_AGGR_TYPE (binfo))
- {
- type = binfo;
- }
- else
- {
- type = binfo;
- binfo = NULL_TREE;
- }
-
- ptr_type = cp_build_qualified_type (type,
- CP_TYPE_QUALS (TREE_TYPE (intype)));
- ptr_type = build_pointer_type (ptr_type);
- if (same_type_p (ptr_type, TYPE_MAIN_VARIANT (intype)))
- return expr;
-
- my_friendly_assert (!integer_zerop (expr), 191);
-
- intype = TYPE_MAIN_VARIANT (TREE_TYPE (intype));
- if (TREE_CODE (type) == RECORD_TYPE
- && TREE_CODE (intype) == RECORD_TYPE
- && type != intype)
- {
- tree path;
- int distance
- = get_base_distance (binfo, intype, 0, &path);
-
- /* This function shouldn't be called with unqualified arguments
- but if it is, give them an error message that they can read. */
- if (distance < 0)
- {
- cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",
- intype, type);
-
- if (distance == -2)
- cp_error ("because `%T' is an ambiguous base class", type);
- return error_mark_node;
- }
-
- return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1);
- }
- rval = build1 (NOP_EXPR, ptr_type,
- TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr);
- TREE_CONSTANT (rval) = TREE_CONSTANT (expr);
- return rval;
- }
-
- /* Call this when we know (for any reason) that expr is
- not, in fact, zero. This routine gets a type out of the first
- argument and uses it to search for the type to convert to. If there
- is more than one instance of that type in the expr, the conversion is
- ambiguous. This routine should eventually go away, and all
- callers should use convert_to_pointer_real. */
-
- tree
- convert_pointer_to (binfo, expr)
- tree binfo, expr;
- {
- return convert_pointer_to_real (binfo, expr);
}
/* C++ conversions, preference to static cast conversions. */
--- 606,611 ----
Index: cp/init.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/init.c,v
retrieving revision 1.250
diff -c -3 -p -r1.250 init.c
*** init.c 2001/11/15 10:03:37 1.250
--- init.c 2001/11/22 12:02:53
*************** finish_init_stmts (stmt_expr, compound_s
*** 130,136 ****
/* Constructors */
! /* Called from initialize_vtbl_ptrs via dfs_walk. */
static tree
dfs_initialize_vtbl_ptrs (binfo, data)
--- 130,138 ----
/* Constructors */
! /* Called from initialize_vtbl_ptrs via dfs_walk. BINFO is the base
! which we want to initialize the vtable pointer for, DATA is
! TREE_LIST whose TREE_VALUE is the this ptr expression. */
static tree
dfs_initialize_vtbl_ptrs (binfo, data)
*************** dfs_initialize_vtbl_ptrs (binfo, data)
*** 142,157 ****
{
tree base_ptr = TREE_VALUE ((tree) data);
! if (TREE_VIA_VIRTUAL (binfo))
! base_ptr = convert_pointer_to_vbase (BINFO_TYPE (binfo),
! base_ptr);
! else
! base_ptr
! = build_vbase_path (PLUS_EXPR,
! build_pointer_type (BINFO_TYPE (binfo)),
! base_ptr,
! binfo,
! /*nonnull=*/1);
expand_virtual_init (binfo, base_ptr);
}
--- 144,150 ----
{
tree base_ptr = TREE_VALUE ((tree) data);
! base_ptr = build_base_path (PLUS_EXPR, base_ptr, binfo, /*nonnull=*/1);
expand_virtual_init (binfo, base_ptr);
}
*************** emit_base_init (mem_init_list, base_init
*** 711,717 ****
if (init != void_list_node)
{
! member = convert_pointer_to_real (base_binfo, current_class_ptr);
expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL), init,
LOOKUP_NORMAL);
--- 704,711 ----
if (init != void_list_node)
{
! member = build_base_path (PLUS_EXPR, current_class_ptr,
! base_binfo, 1);
expand_aggr_init_1 (base_binfo, NULL_TREE,
build_indirect_ref (member, NULL), init,
LOOKUP_NORMAL);
*************** static void
*** 802,816 ****
expand_virtual_init (binfo, decl)
tree binfo, decl;
{
- tree type = BINFO_TYPE (binfo);
tree vtbl, vtbl_ptr;
- tree vtype, vtype_binfo;
tree vtt_index;
- /* Compute the location of the vtable. */
- vtype = DECL_CONTEXT (TYPE_VFIELD (type));
- vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);
-
/* Compute the initializer for vptr. */
vtbl = build_vtbl_address (binfo);
--- 796,804 ----
*************** expand_virtual_init (binfo, decl)
*** 842,851 ****
}
/* Compute the location of the vtpr. */
! decl = convert_pointer_to_real (vtype_binfo, decl);
! vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL), vtype);
! if (vtbl_ptr == error_mark_node)
! return;
/* Assign the vtable to the vptr. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
--- 830,838 ----
}
/* Compute the location of the vtpr. */
! vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL),
! TREE_TYPE (binfo));
! my_friendly_assert (vtbl_ptr != error_mark_node, 20010730);
/* Assign the vtable to the vptr. */
vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);
*************** resolve_offset_ref (exp)
*** 1842,1855 ****
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;
expr = build (COMPONENT_REF, TREE_TYPE (member),
! build_indirect_ref (addr, NULL), member);
return convert_from_reference (expr);
}
--- 1829,1842 ----
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type));
! basetype = lookup_base (TREE_TYPE (base), basetype, ba_check, NULL);
! expr = build_base_path (PLUS_EXPR, base, basetype, 1);
!
! if (expr == error_mark_node)
return error_mark_node;
expr = build (COMPONENT_REF, TREE_TYPE (member),
! expr, member);
return convert_from_reference (expr);
}
*************** resolve_offset_ref (exp)
*** 1872,1878 ****
}
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
! addr = convert_pointer_to (basetype, addr);
member = cp_convert (ptrdiff_type_node, member);
return build1 (INDIRECT_REF, type,
--- 1859,1868 ----
}
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
! basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)),
! basetype, ba_check, NULL);
! addr = build_base_path (PLUS_EXPR, addr, basetype, 1);
!
member = cp_convert (ptrdiff_type_node, member);
return build1 (INDIRECT_REF, type,
Index: cp/rtti.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/rtti.c,v
retrieving revision 1.124
diff -c -3 -p -r1.124 rtti.c
*** rtti.c 2001/10/03 15:18:25 1.124
--- rtti.c 2001/11/22 12:02:53
*************** build_dynamic_cast_1 (type, expr)
*** 472,499 ****
/* If *type is an unambiguous accessible base class of *exprtype,
convert statically. */
{
! int distance;
! tree path;
! distance = get_base_distance (TREE_TYPE (type), TREE_TYPE (exprtype), 1,
! &path);
! if (distance == -2)
{
! cp_error ("dynamic_cast from `%T' to ambiguous base class `%T'",
! TREE_TYPE (exprtype), TREE_TYPE (type));
! return error_mark_node;
! }
! if (distance == -3)
! {
! cp_error ("dynamic_cast from `%T' to private base class `%T'",
! TREE_TYPE (exprtype), TREE_TYPE (type));
! return error_mark_node;
! }
!
! if (distance >= 0)
! {
! expr = build_vbase_path (PLUS_EXPR, type, expr, path, 0);
if (TREE_CODE (exprtype) == POINTER_TYPE)
expr = non_lvalue (expr);
return expr;
--- 472,486 ----
/* If *type is an unambiguous accessible base class of *exprtype,
convert statically. */
{
! tree binfo;
! binfo = lookup_base (TREE_TYPE (exprtype), TREE_TYPE (type),
! ba_not_special, NULL);
! if (binfo)
{
! expr = build_base_path (PLUS_EXPR, convert_from_reference (expr),
! binfo, 0);
if (TREE_CODE (exprtype) == POINTER_TYPE)
expr = non_lvalue (expr);
return expr;
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/search.c,v
retrieving revision 1.216
diff -c -3 -p -r1.216 search.c
*** search.c 2001/11/15 15:09:39 1.216
--- search.c 2001/11/22 12:02:54
*************** struct vbase_info
*** 83,89 ****
tree inits;
};
- static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
static tree lookup_field_1 PARAMS ((tree, tree));
static int is_subobject_of_p PARAMS ((tree, tree, tree));
static tree dfs_check_overlap PARAMS ((tree, void *));
--- 83,88 ----
*************** static tree dfs_no_overlap_yet PARAMS ((
*** 91,96 ****
--- 90,98 ----
static int get_base_distance_recursive
PARAMS ((tree, int, int, int, int *, tree *, tree,
int, int *, int, int));
+ static base_kind lookup_base_r
+ PARAMS ((tree, tree, base_access,
+ int, int, int, tree *));
static int dynamic_cast_base_recurse PARAMS ((tree, tree, int, tree *));
static tree marked_pushdecls_p PARAMS ((tree, void *));
static tree unmarked_pushdecls_p PARAMS ((tree, void *));
*************** static int n_contexts_saved;
*** 169,244 ****
#endif /* GATHER_STATISTICS */
- /* Get a virtual binfo that is found inside BINFO's hierarchy that is
- the same type as the type given in PARENT. To be optimal, we want
- the first one that is found by going through the least number of
- virtual bases.
-
- This uses a clever algorithm that updates *depth when we find the vbase,
- and cuts off other paths of search when they reach that depth. */
-
- static tree
- get_vbase_1 (parent, binfo, depth)
- tree parent, binfo;
- unsigned int *depth;
- {
- tree binfos;
- int i, n_baselinks;
- tree rval = NULL_TREE;
- int virtualp = TREE_VIA_VIRTUAL (binfo) != 0;
-
- *depth -= virtualp;
- if (virtualp && BINFO_TYPE (binfo) == parent)
- {
- *depth = 0;
- return binfo;
- }
-
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Process base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree nrval;
-
- if (*depth == 0)
- break;
-
- nrval = get_vbase_1 (parent, base_binfo, depth);
- if (nrval)
- rval = nrval;
- }
- *depth += virtualp;
- return rval;
- }
-
- /* Return the shortest path to vbase PARENT within BINFO, ignoring
- access and ambiguity. */
-
- tree
- get_vbase (parent, binfo)
- tree parent;
- tree binfo;
- {
- unsigned int d = (unsigned int)-1;
- return get_vbase_1 (parent, binfo, &d);
- }
-
- /* Convert EXPR to a virtual base class of type TYPE. We know that
- EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that
- the type of what expr points to has a virtual base of type TYPE. */
-
- tree
- convert_pointer_to_vbase (type, expr)
- tree type;
- tree expr;
- {
- tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))));
- return convert_pointer_to_real (vb, expr);
- }
-
/* Check whether the type given in BINFO is derived from PARENT. If
it isn't, return 0. If it is, but the derivation is MI-ambiguous
AND protect != 0, emit an error message and return error_mark_node.
--- 171,176 ----
*************** get_base_distance_recursive (binfo, dept
*** 406,414 ****
If PROTECT is greater than 1, ignore any special access the current
scope might have when determining whether PARENT is inaccessible.
- PARENT can also be a binfo, in which case that exact parent is found
- and no other. convert_pointer_to_real uses this functionality.
-
If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone. */
int
--- 338,343 ----
*************** get_base_distance (parent, binfo, protec
*** 471,476 ****
--- 400,592 ----
if (path_ptr)
*path_ptr = new_binfo;
return rval;
+ }
+
+ /* Worker for lookup_base. BINFO is the binfo we are searching at,
+ BASE is the RECORD_TYPE we are searching for. ACCESS is the
+ required access checks. WITHIN_CURRENT_SCOPE, IS_NON_PUBLIC and
+ IS_VIRTUAL indicate how BINFO was reached from the start of the
+ search. WITHIN_CURRENT_SCOPE is true if we met the current scope,
+ or friend thereof (this allows us to determine whether a protected
+ base is accessible or not). IS_NON_PUBLIC indicates whether BINFO
+ is accessible and IS_VIRTUAL indicates if it is morally virtual.
+
+ If BINFO is of the required type, then *BINFO_PTR is examined to
+ compare with any other instance of BASE we might have already
+ discovered. *BINFO_PTR is initialized and a base_kind return value
+ indicates what kind of base was located.
+
+ Otherwise BINFO's bases are searched. */
+
+ static base_kind
+ lookup_base_r (binfo, base, access, within_current_scope,
+ is_non_public, is_virtual, binfo_ptr)
+ tree binfo, base;
+ base_access access;
+ int within_current_scope;
+ int is_non_public; /* inside a non-public part */
+ int is_virtual; /* inside a virtual part */
+ tree *binfo_ptr;
+ {
+ int i;
+ tree bases;
+ base_kind found = bk_not_base;
+
+ if (access == ba_check
+ && !within_current_scope
+ && is_friend (BINFO_TYPE (binfo), current_scope ()))
+ {
+ within_current_scope = 1;
+ is_non_public = 0;
+ }
+
+ if (same_type_p (BINFO_TYPE (binfo), base))
+ {
+ /* We have found a base. Check against what we have found
+ already. */
+ found = bk_same_type;
+ if (is_virtual)
+ found = bk_via_virtual;
+ if (is_non_public)
+ found = bk_inaccessible;
+
+ if (!*binfo_ptr)
+ *binfo_ptr = binfo;
+ else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo),
+ BINFO_OFFSET (*binfo_ptr)))
+ {
+ if (access != ba_any)
+ *binfo_ptr = NULL;
+ else if (found != is_virtual)
+ /* Prefer a non-virtual base. */
+ *binfo_ptr = binfo;
+ found = bk_ambig;
+ }
+ else if (found == bk_via_virtual)
+ *binfo_ptr = binfo;
+
+ return found;
+ }
+
+ bases = BINFO_BASETYPES (binfo);
+ if (!bases)
+ return bk_not_base;
+
+ for (i = TREE_VEC_LENGTH (bases); i--;)
+ {
+ tree base_binfo = TREE_VEC_ELT (bases, i);
+ int this_non_public = is_non_public;
+ int this_virtual = is_virtual;
+
+ if (access <= ba_ignore)
+ ; /* no change */
+ else if (TREE_VIA_PUBLIC (base_binfo))
+ ; /* no change */
+ else if (access == ba_not_special)
+ this_non_public = 1;
+ else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
+ ; /* no change */
+ else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
+ ; /* no change */
+ else
+ this_non_public = 1;
+
+ if (TREE_VIA_VIRTUAL (base_binfo))
+ this_virtual = 1;
+
+ base_kind bk = lookup_base_r (base_binfo, base,
+ access, within_current_scope,
+ this_non_public, this_virtual,
+ binfo_ptr);
+
+ switch (bk)
+ {
+ case bk_ambig:
+ if (access != ba_any)
+ return bk;
+ found = bk;
+ break;
+
+ case bk_inaccessible:
+ if (found == bk_not_base)
+ found = bk;
+ my_friendly_assert (found == bk_via_virtual
+ || found == bk_inaccessible, 20010723);
+
+ break;
+
+ case bk_same_type:
+ bk = bk_proper_base;
+ /* FALLTHROUGH */
+ case bk_proper_base:
+ my_friendly_assert (found == bk_not_base, 20010723);
+ found = bk;
+ break;
+
+ case bk_via_virtual:
+ my_friendly_assert (found == bk_not_base
+ || found == bk_via_virtual
+ || found == bk_inaccessible, 20010723);
+ found = bk;
+ break;
+
+ case bk_not_base:
+ break;
+ }
+ }
+ return found;
+ }
+
+ /* Lookup BASE in the hierarchy dominated by T. Do access checking as
+ ACCESS specifies. Return the binfo we discover (which might not be
+ canonical). If KIND_PTR is non-NULL, fill with information about
+ what kind of base we discoveded.
+
+ Issue an error message if an inaccessible or ambiguous base is
+ discovered, and return error_mark_node. */
+
+ tree
+ lookup_base (t, base, access, kind_ptr)
+ tree t, base;
+ base_access access;
+ base_kind *kind_ptr;
+ {
+ tree binfo = NULL; /* The binfo we've found so far. */
+ base_kind bk;
+
+ if (t == error_mark_node || base == error_mark_node)
+ {
+ if (kind_ptr)
+ *kind_ptr = bk_not_base;
+ return error_mark_node;
+ }
+
+ t = TYPE_MAIN_VARIANT (t);
+ base = TYPE_MAIN_VARIANT (base);
+
+ bk = lookup_base_r (TYPE_BINFO (t), base, access, 0, 0, 0, &binfo);
+
+ switch (bk)
+ {
+ case bk_inaccessible:
+ cp_error ("`%T' is an inaccessible base of `%T'", base, t);
+ binfo = error_mark_node;
+ break;
+ case bk_ambig:
+ if (access != ba_any)
+ {
+ cp_error ("`%T' is an ambiguous base of `%T'", base, t);
+ binfo = error_mark_node;
+ }
+ break;
+
+ default:;
+ }
+
+ if (kind_ptr)
+ *kind_ptr = bk;
+
+ return binfo;
}
/* Worker function for get_dynamic_cast_base_type. */
Index: cp/typeck.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck.c,v
retrieving revision 1.370
diff -c -3 -p -r1.370 typeck.c
*** typeck.c 2001/11/20 05:09:33 1.370
--- typeck.c 2001/11/22 12:02:56
*************** require_complete_type (value)
*** 116,123 ****
{
tree base, member = TREE_OPERAND (value, 1);
tree basetype = TYPE_OFFSET_BASETYPE (type);
my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
! base = convert_pointer_to (basetype, current_class_ptr);
value = build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (base, NULL), member);
return require_complete_type (value);
--- 116,126 ----
{
tree base, member = TREE_OPERAND (value, 1);
tree basetype = TYPE_OFFSET_BASETYPE (type);
+
my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305);
! basetype = lookup_base (current_class_type, basetype, ba_check, NULL);
! base = build_base_path (PLUS_EXPR, current_class_ptr, basetype, 1);
!
value = build (COMPONENT_REF, TREE_TYPE (member),
build_indirect_ref (base, NULL), member);
return require_complete_type (value);
*************** build_component_ref (datum, component, b
*** 2208,2221 ****
/* Handle base classes here... */
if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
{
! tree addr = build_unary_op (ADDR_EXPR, datum, 0);
! if (integer_zerop (addr))
{
error ("invalid reference to NULL ptr, use ptr-to-member instead");
return error_mark_node;
}
! addr = convert_pointer_to (base, addr);
! datum = build_indirect_ref (addr, NULL);
if (datum == error_mark_node)
return error_mark_node;
}
--- 2211,2225 ----
/* Handle base classes here... */
if (base != basetype && TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (basetype))
{
! tree binfo = lookup_base (TREE_TYPE (datum), base, ba_check, NULL);
!
! if (TREE_CODE (datum) == INDIRECT_REF
! && integer_zerop (TREE_OPERAND (datum, 0)))
{
error ("invalid reference to NULL ptr, use ptr-to-member instead");
return error_mark_node;
}
! datum = build_base_path (PLUS_EXPR, datum, binfo, 1);
if (datum == error_mark_node)
return error_mark_node;
}
*************** build_x_function_call (function, params,
*** 2806,2813 ****
if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
{
decl = build_unary_op (ADDR_EXPR, decl, 0);
! decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl);
}
else
decl = build_c_cast (ctypeptr, decl);
--- 2810,2820 ----
if (TREE_CODE (TREE_TYPE (decl)) != POINTER_TYPE
&& ! TYPE_PTRMEMFUNC_P (TREE_TYPE (decl)))
{
+ tree binfo = lookup_base (TREE_TYPE (decl), TREE_TYPE (ctypeptr),
+ ba_check, NULL);
+
decl = build_unary_op (ADDR_EXPR, decl, 0);
! decl = build_base_path (PLUS_EXPR, decl, binfo, 1);
}
else
decl = build_c_cast (ctypeptr, decl);
*************** get_member_function_from_ptrfunc (instan
*** 2826,2834 ****
tree function;
{
if (TREE_CODE (function) == OFFSET_REF)
! {
! function = TREE_OPERAND (function, 1);
! }
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
--- 2833,2839 ----
tree function;
{
if (TREE_CODE (function) == OFFSET_REF)
! function = TREE_OPERAND (function, 1);
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function)))
{
*************** get_member_function_from_ptrfunc (instan
*** 2857,2870 ****
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
! /* Convert down to the right base, before using the instance. */
! instance = convert_pointer_to_real (basetype, instance_ptr);
if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
e3 = PFN_FROM_PTRMEMFUNC (function);
!
! vtbl = convert_pointer_to (ptr_type_node, instance);
delta = cp_convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier,
NULL_TREE, 0));
--- 2862,2879 ----
fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function));
basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype));
! /* Convert down to the right base, before using the instance. */
! instance = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype,
! ba_check, NULL);
! instance = build_base_path (PLUS_EXPR, instance_ptr, instance, 1);
if (instance == error_mark_node && instance_ptr != error_mark_node)
return instance;
e3 = PFN_FROM_PTRMEMFUNC (function);
!
! vtbl = build1 (NOP_EXPR, build_pointer_type (ptr_type_node), instance);
! TREE_CONSTANT (vtbl) = TREE_CONSTANT (instance);
!
delta = cp_convert (ptrdiff_type_node,
build_component_ref (function, delta_identifier,
NULL_TREE, 0));
*************** build_component_addr (arg, argtype)
*** 4229,4236 ****
/* Can't convert directly to ARGTYPE, since that
may have the same pointer type as one of our
baseclasses. */
! rval = build1 (NOP_EXPR, argtype,
! convert_pointer_to (basetype, rval));
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
}
else
--- 4238,4248 ----
/* Can't convert directly to ARGTYPE, since that
may have the same pointer type as one of our
baseclasses. */
! tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), basetype,
! ba_check, NULL);
!
! rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
! rval = build1 (NOP_EXPR, argtype, rval);
TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0));
}
else
Index: cp/typeck2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/typeck2.c,v
retrieving revision 1.105
diff -c -3 -p -r1.105 typeck2.c
*** typeck2.c 2001/10/12 09:06:32 1.105
--- typeck2.c 2001/11/22 12:02:56
*************** build_scoped_ref (datum, basetype)
*** 997,1008 ****
tree basetype;
{
tree ref;
if (datum == error_mark_node)
return error_mark_node;
ref = build_unary_op (ADDR_EXPR, datum, 0);
! ref = convert_pointer_to (basetype, ref);
return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
}
--- 997,1013 ----
tree basetype;
{
tree ref;
+ tree binfo;
if (datum == error_mark_node)
return error_mark_node;
+ binfo = lookup_base (TREE_TYPE (datum), basetype, ba_check, NULL);
+ if (!binfo)
+ return error_not_base_type (TREE_TYPE (datum), basetype);
+
ref = build_unary_op (ADDR_EXPR, datum, 0);
! ref = build_base_path (PLUS_EXPR, ref, binfo, 1);
return build_indirect_ref (ref, "(compiler error in build_scoped_ref)");
}