/* Breadth-first and depth-first routines for
searching multiple-inheritance lattice for GNU C++.
- Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+ Copyright (C) 1987, 89, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA. */
-/* High-level class interface. */
+/* High-level class interface. */
#include "config.h"
#include "tree.h"
#include "stack.h"
/* Obstack used for remembering decision points of breadth-first. */
+
static struct obstack search_obstack;
/* Methods for pushing and popping objects to and from obstacks. */
+
struct stack_level *
push_stack_level (obstack, tp, size)
struct obstack *obstack;
static tree vbase_init_result;
/* Allocate a level of searching. */
+
static struct search_level *
push_search_level (stack, obstack)
struct stack_level *stack;
}
/* Discard a level of search allocation. */
+
static struct search_level *
pop_search_level (obstack)
struct stack_level *obstack;
}
\f
/* Search memoization. */
+
struct type_level
{
struct stack_level base;
static tree closed_envelopes = NULL_TREE;
/* Allocate a level of type memoization context. */
+
static struct type_level *
push_type_level (stack, obstack)
struct stack_level *stack;
/* Make something that looks like a TREE_LIST, but
do it on the type_obstack_entries obstack. */
+
static tree
my_tree_cons (purpose, value, chain)
tree purpose, value, chain;
\f
/* Memoizing machinery to make searches for multiple inheritance
reasonably efficient. */
+
#define MEMOIZE_HASHSIZE 8
typedef struct memoized_entry
{
my_new_memoized_entry (chain)
struct memoized_entry *chain;
{
- struct memoized_entry *p =
- (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
- sizeof (struct memoized_entry));
+ struct memoized_entry *p
+ = (struct memoized_entry *)obstack_alloc (&type_obstack_entries,
+ sizeof (struct memoized_entry));
bzero ((char *) p, sizeof (struct memoized_entry));
MEMOIZED_CHAIN (p) = chain;
MEMOIZED_UID (p) = ++my_memoized_entry_counter;
}
/* Clears the deferred pop from pop_memoized_context, if any. */
+
static void
clear_memoized_cache ()
{
tree type, name;
int function_p;
{
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
tree entry, *prev_entry;
/* Since we allocate from the type_obstack, we must pop any deferred
my_friendly_abort (88);
}
if (function_p)
- prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
else
- prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
entry = my_tree_cons (name, NULL_TREE, *prev_entry);
*prev_entry = entry;
be NULL_TREE if we are not in a class's scope.
USE_OLD, if nonzero tries to use previous context. */
+
void
push_memoized_context (type, use_old)
tree type;
If we wanted to, we could not use pop_search_level, since
poping that level allows the data we have collected to
be clobbered; a stack of obstacks would be needed. */
+
void
pop_memoized_context (use_old)
int use_old;
/* 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. DEPTH should be NULL_PTR. */
+ virtual bases. */
+
static tree
-get_vbase (parent, binfo, depth)
+get_vbase_1 (parent, binfo, depth)
tree parent, binfo;
unsigned int *depth;
{
int i, n_baselinks;
tree rval = NULL_TREE;
- if (depth == 0)
- {
- unsigned int d = (unsigned int)-1;
- return get_vbase (parent, binfo, &d);
- }
-
if (BINFO_TYPE (binfo) == parent && TREE_VIA_VIRTUAL (binfo))
{
*depth = 0;
if (*depth == 0)
break;
- nrval = get_vbase (parent, base_binfo, depth);
+ nrval = get_vbase_1 (parent, base_binfo, depth);
if (nrval)
rval = nrval;
}
return rval;
}
+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
+
+static tree
convert_pointer_to_vbase (type, expr)
tree type;
tree expr;
{
- tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))), NULL_PTR);
+ tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))));
return convert_pointer_to_real (vb, expr);
}
}
/* This is the newer depth first get_base_distance routine. */
+
static int
get_base_distance_recursive (binfo, depth, is_private, rval,
rval_private_ptr, new_binfo_ptr, parent, path_ptr,
tree base_binfo = TREE_VEC_ELT (binfos, i);
/* Find any specific instance of a virtual base, when searching with
- a binfo... */
+ a binfo... */
if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC)
{
int via_private
int was;
/* When searching for a non-virtual, we cannot mark
- virtually found binfos. */
+ virtually found binfos. */
if (! this_virtual)
SET_BINFO_MARKED (base_binfo);
protect, via_virtual_ptr,
this_virtual,
current_scope_in_chain);
- /* watch for updates; only update if path is good. */
+ /* watch for updates; only update if path is good. */
if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was)
BINFO_INHERITANCE_CHAIN (base_binfo) = binfo;
if (rval == -2 && *via_virtual_ptr == 0)
type = BINFO_TYPE (binfo);
else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
{
- type = binfo;
+ type = complete_type (binfo);
binfo = TYPE_BINFO (type);
if (path_ptr)
if (rval && protect && rval_private)
return -3;
- /* find real virtual base classes. */
+ /* find real virtual base classes. */
if (rval == -1 && TREE_CODE (parent) == TREE_VEC
&& parent == binfo_member (BINFO_TYPE (parent),
CLASSTYPE_VBASECLASSES (type)))
/* Do a 1-level search for NAME as a member of TYPE. The caller must
figure out whether it can access this field. (Since it is only one
level, this is reasonable.) */
+
static tree
lookup_field_1 (type, name)
tree type, name;
/* There are a number of cases we need to be aware of here:
current_class_type current_function_decl
- * global NULL NULL
- * fn-local NULL SET
- * class-local SET NULL
- * class->fn SET SET
- * fn->class SET SET
+ global NULL NULL
+ fn-local NULL SET
+ class-local SET NULL
+ class->fn SET SET
+ fn->class SET SET
Those last two make life interesting. If we're in a function which is
itself inside a class, we need decls to go into the fn's decls (our
second case below). But if we're in a class and the class itself is
inside a function, we need decls to go into the decls for the class. To
- achieve this last goal, we must see if, when both current_class_decl and
+ achieve this last goal, we must see if, when both current_class_ptr and
current_function_decl are set, the class was declared inside that
function. If so, we know to put the decls into the class's scope. */
lexical scope because it is protected.
access_private_node means that the field cannot be accessed by the current
- lexical scope because it is private. */
+ lexical scope because it is private. */
#if 0
#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node
/* Replaces static decl above. */
tree previous_scope;
#endif
- int static_mem =
- ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
- || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
+ int static_mem
+ = ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field))
+ || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field)));
if (! flag_access_control)
return access_public_node;
{
if (current_class_type
&& static_mem
- && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
+ && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type))
PUBLIC_RETURN;
else
PROTECTED_RETURN;
found as a base class and sub-object of the object denoted by
BINFO. This routine relies upon binfos not being shared, except
for binfos for virtual bases. */
+
static int
is_subobject_of_p (parent, binfo)
tree parent, binfo;
correspond to ANSI working paper Sept 17, 1992 10p4. The two
binfos given are the binfos corresponding to the particular places
the FIELD_DECLs are found. This routine relies upon binfos not
- being shared, except for virtual bases. */
+ being shared, except for virtual bases. */
+
static int
hides (hider_binfo, hidee_binfo)
tree hider_binfo, hidee_binfo;
part is always true is the second part is true.
When hider and hidee are the same (two ways to get to the exact
- same member) we consider either one as hiding the other. */
+ same member) we consider either one as hiding the other. */
return is_subobject_of_p (hidee_binfo, hider_binfo);
}
/* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */
+
static int
lookup_fnfields_here (type, name)
tree type, name;
{
- int index = lookup_fnfields_1 (type, name);
+ int idx = lookup_fnfields_1 (type, name);
tree fndecls;
/* ctors and dtors are always only in the right class. */
- if (index <= 1)
- return index;
- fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ if (idx <= 1)
+ return idx;
+ fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
while (fndecls)
{
if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls))
== TYPE_MAIN_VARIANT (type))
- return index;
+ return idx;
fndecls = TREE_CHAIN (fndecls);
}
return -1;
It was not clear what should happen if WANT_TYPE is set, and an
ambiguity is found. At least one use (lookup_name) to not see
the error. */
+
tree
lookup_field (xbasetype, name, protect, want_type)
register tree xbasetype, name;
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
#if 0
/* We cannot search for constructor/destructor names like this. */
name = constructor_name (name);
#endif
+ if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype)
+ && IDENTIFIER_CLASS_VALUE (name))
+ {
+ tree field = IDENTIFIER_CLASS_VALUE (name);
+ if (TREE_CODE (field) != FUNCTION_DECL
+ && ! (want_type && TREE_CODE (field) != TYPE_DECL))
+ return field;
+ }
+
if (TREE_CODE (xbasetype) == TREE_VEC)
{
type = BINFO_TYPE (xbasetype);
if (CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path);
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
else if (rval_binfo && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
+ rval_binfo. */
if (nval)
{
rval = nval;
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
}
rval_binfo = binfo;
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for member `%D' is ambiguous";
protect += 2;
break;
}
/* Try to find NAME inside a nested class. */
+
tree
lookup_nested_field (name, complain)
tree name;
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
+
static int
lookup_fnfields_1 (type, name)
tree type, name;
which gives the following information (in a list):
TREE_TYPE: list of basetypes needed to get to...
- TREE_VALUE: list of all functions in of given type
+ TREE_VALUE: list of all functions in a given type
which have name NAME.
No access information is computed by this function,
As a special case, is COMPLAIN is -1, we don't complain, and we
don't return error_mark_node, but rather the complete list of
virtuals. This is used by get_virtuals_named_this. */
+
tree
lookup_fnfields (basetype_path, name, complain)
tree basetype_path, name;
/* Set this to nonzero if we don't know how to compute
accurate error messages for access control. */
- int index = MEMOIZED_HASH_FN (name);
+ int idx = MEMOIZED_HASH_FN (name);
if (complain == -1)
{
binfo_h = binfo;
type = complete_type (BINFO_TYPE (basetype_path));
- /* The memoization code is in need of maintenance. */
+ /* The memoization code is in need of maintenance. */
if (!find_all && CLASSTYPE_MTABLE_ENTRY (type))
{
- tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index);
+ tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);
while (tem && TREE_PURPOSE (tem) != name)
{
else
entry = 0;
- index = lookup_fnfields_here (type, name);
- if (index >= 0 || lookup_field_1 (type, name))
+ idx = lookup_fnfields_here (type, name);
+ if (idx >= 0 || lookup_field_1 (type, name))
{
rval_binfo = basetype_path;
rval_binfo_h = rval_binfo;
}
- if (index >= 0)
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rvals = my_tree_cons (basetype_path, rval, rvals);
if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
if (entry)
{
TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path);
}
- /* The ambiguity check relies upon breadth first searching. */
+ /* The ambiguity check relies upon breadth first searching. */
search_stack = push_search_level (search_stack, &search_obstack);
binfo = basetype_path;
{
tree binfos = BINFO_BASETYPES (binfo);
int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- int index;
+ int idx;
/* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
and we do find NAME in TYPE, verify that such a second
sighting is in fact valid. */
- index = lookup_fnfields_here (type, name);
+ idx = lookup_fnfields_here (type, name);
- if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
+ if (idx >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all))
{
if (rval_binfo && !find_all && hides (rval_binfo_h, binfo_h))
{
/* This is ok, the member found is in rval_binfo, not
- here (binfo). */
+ here (binfo). */
}
else if (rval_binfo==NULL_TREE || find_all || hides (binfo_h, rval_binfo_h))
{
/* This is ok, the member found is here (binfo), not in
- rval_binfo. */
- if (index >= 0)
+ rval_binfo. */
+ if (idx >= 0)
{
- rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
/* Note, rvals can only be previously set if find_all is
true. */
rvals = my_tree_cons (basetype_path, rval, rvals);
if (TYPE_BINFO_BASETYPES (type)
&& CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
}
else
{
- /* Undo finding it before, as something else hides it. */
+ /* Undo finding it before, as something else hides it. */
rval = NULL_TREE;
rvals = NULL_TREE;
}
}
else
{
- /* This is ambiguous. */
+ /* This is ambiguous. */
errstr = "request for method `%D' is ambiguous";
rvals = error_mark_node;
break;
/* Search a multiple inheritance hierarchy by breadth-first search.
- TYPE is an aggregate type, possibly in a multiple-inheritance hierarchy.
+ BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy.
TESTFN is a function, which, if true, means that our condition has been met,
and its return value should be returned.
QFN, if non-NULL, is a predicate dictating whether the type should
DTORP is nonzero if we are looking for a destructor. Destructors
need special treatment because they do not match by name. */
+
tree
get_matching_virtual (binfo, fndecl, dtorp)
tree binfo, fndecl;
/* Return the list of virtual functions which are abstract in type
TYPE that come from non virtual base classes. See
expand_direct_vtbls_init for the style of search we do. */
+
static tree
get_abstract_virtuals_1 (binfo, do_self, abstract_virtuals)
tree binfo;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo));
if (! TREE_VIA_VIRTUAL (base_binfo))
abstract_virtuals
= get_abstract_virtuals_1 (base_binfo, is_not_base_vtable,
/* Return the list of virtual functions which are abstract in type TYPE.
This information is cached, and so must be built on a
non-temporary obstack. */
+
tree
get_abstract_virtuals (type)
tree type;
tree vbases;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type);
- /* First get all from non-virtual bases. */
+ /* First get all from non-virtual bases. */
abstract_virtuals
= get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals);
tree type_as_binfo_list;
tree type, name;
{
- int head = 0, tail = 0, index;
+ int head = 0, tail = 0, idx;
tree rval = 0, nval = 0;
tree basetypes = type_as_binfo_list;
tree binfo = TYPE_BINFO (type);
basetypes = search_stack->first[head++];
binfo = TREE_VALUE (basetypes);
type = BINFO_TYPE (binfo);
- index = lookup_fnfields_1 (type, name);
- if (index >= 0)
+ idx = lookup_fnfields_1 (type, name);
+ if (idx >= 0)
{
- nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index);
+ nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval);
if (TYPE_BINFO_BASETYPES (type) == 0)
goto dont_queue;
else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1)
{
if (CLASSTYPE_BASELINK_VEC (type))
- TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index);
+ TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), idx);
goto dont_queue;
}
}
/* This routine converts a pointer to be a pointer of an immediate
base class. The normal convert_pointer_to routine would diagnose
the conversion as ambiguous, under MI code that has the base class
- as an ambiguous base class. */
+ as an ambiguous base class. */
+
static tree
convert_pointer_to_single_level (to_type, expr)
tree to_type, expr;
This routine has to remember the path it walked up, when
dfs_init_vbase_pointers is the work function, as otherwise there
- would be no record. */
+ would be no record. */
+
static void
dfs_walk (binfo, fn, qfn)
tree binfo;
CLASSTYPE_DEBUG_REQUESTED (t) = 1;
- /* If interface info is known, the value of (?@@?) is correct. */
- if (methods == 0
- || CLASSTYPE_INTERFACE_KNOWN (t)
+ if (methods == 0)
+ return;
+
+ /* If interface info is known, either we've already emitted the debug
+ info or we don't need to. */
+ if (CLASSTYPE_INTERFACE_KNOWN (t)
|| (write_virtuals == 2 && TYPE_VIRTUAL_P (t)))
return;
virtual base class, given the global pointer vbase_decl_ptr.
We use the global vbase_types. ICK! */
+
static void
dfs_find_vbases (binfo)
tree binfo;
/* Sometimes this needs to clear both VTABLE_PATH and NEW_VTABLE. Other
times, just NEW_VTABLE, but optimizer should make both with equal
efficiency (though it does not currently). */
+
static void
dfs_clear_vbase_slots (binfo)
tree binfo;
We know that if there is more than one place (binfo) the fndecl that the
declared, they all refer to the same binfo. See get_class_offset_1 for
the check that ensures this. */
+
static tree
virtual_context (fndecl, t, vbase)
tree fndecl, t, vbase;
offset information for the virtual bases, so the offsets are only
calculated once. The offsets are computed by where we think the
vbase should be (as noted by the CLASSTYPE_SEARCH_SLOT) minus where
- the vbase really is. */
+ the vbase really is. */
+
static void
expand_upcast_fixups (binfo, addr, orig_addr, vbase, vbase_addr, t,
vbase_offsets)
&& current_fndecl != abort_fndecl
&& (vc=virtual_context (current_fndecl, t, vbase)) != vbase)
{
- /* This may in fact need a runtime fixup. */
- tree idx = DECL_VINDEX (current_fndecl);
+ /* This may in fact need a runtime fixup. */
+ tree idx = build_int_2 (n, 0);
tree vtbl = BINFO_VTABLE (binfo);
tree nvtbl = lookup_name (DECL_NAME (vtbl), 0);
tree aref, ref, naref;
nvtbl, vtbl);
TREE_SIDE_EFFECTS (init) = 1;
expand_expr_stmt (init);
- /* Update the vtable pointers as necessary. */
+ /* Update the vtable pointers as necessary. */
ref = build_vfield_ref (build_indirect_ref (addr, NULL_PTR), DECL_CONTEXT (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))));
expand_expr_stmt (build_modify_expr (ref, NOP_EXPR,
build_unary_op (ADDR_EXPR, nvtbl, 0)));
/* Fixup upcast offsets for all direct vtables. Patterned after
expand_direct_vtbls_init. */
+
static void
fixup_virtual_upcast_offsets (real_binfo, binfo, init_self, can_elide, addr, orig_addr, type, vbase, vbase_offsets)
tree real_binfo, binfo;
{
tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);
tree base_binfo = TREE_VEC_ELT (binfos, i);
- int is_not_base_vtable =
- i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
+ int is_not_base_vtable
+ = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));
if (! TREE_VIA_VIRTUAL (real_base_binfo))
fixup_virtual_upcast_offsets (real_base_binfo, base_binfo,
is_not_base_vtable, can_elide, addr,
addr = convert_pointer_to_vbase (TREE_TYPE (vbases), vbase_decl_ptr);
- /* Do all vtables from this virtual base. */
+ /* Do all vtables from this virtual base. */
/* This assumes that virtual bases can never serve as parent
binfos. (in the CLASSTPE_VFIELD_PARENT sense) */
expand_direct_vtbls_init (vbases, TYPE_BINFO (BINFO_TYPE (vbases)),
1, 0, addr);
- /* Now we adjust the offsets for virtual functions that cross
- virtual boundaries on an implicit upcast on vf call so that
- the layout of the most complete type is used, instead of
- assuming the layout of the virtual bases from our current type. */
+ /* Now we adjust the offsets for virtual functions that
+ cross virtual boundaries on an implicit upcast on vf call
+ so that the layout of the most complete type is used,
+ instead of assuming the layout of the virtual bases from
+ our current type. */
if (flag_vtable_thunks)
{
/* We don't have dynamic thunks yet!
- So for now, just fail silently. */
+ So for now, just fail silently. */
}
else
{
}
/* get a list of virtual base classes in dfs order. */
+
tree
get_vbase_types (type)
tree type;
}
#endif
+ dfs_walk (binfo, dfs_number, unnumberedp);
+
mi_size = CLASSTYPE_N_SUPERCLASSES (type) + CLASSTYPE_N_VBASECLASSES (type);
+ if (mi_size < (cid-1))
+ mi_size = cid-1;
mi_matrix = (char *)xmalloc ((mi_size + 1) * (mi_size + 1));
mi_type = type;
bzero (mi_matrix, (mi_size + 1) * (mi_size + 1));
- dfs_walk (binfo, dfs_number, unnumberedp);
dfs_walk (binfo, dfs_record_inheritance, unmarkedp);
dfs_walk (binfo, dfs_unmark, markedp);
}
tree type;
{
tree field;
+
+ if (current_template_parms)
+ return;
+
+ /* We can't do the TYPE_DECL_SUPPRESS_DEBUG thing with DWARF, which
+ does not support name references between translation units. Well, we
+ could, but that would mean putting global labels in the debug output
+ before each exported type and each of its functions and static data
+ members. */
+ if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
+ return;
+
dfs_walk (TYPE_BINFO (type), dfs_debug_mark, dfs_debug_unmarkedp);
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
{
tree name = DECL_NAME (decl);
int dont_add = 0;
- /* virtual base names are always unique. */
+ /* virtual base names are always unique. */
if (VBASE_NAME_P (name))
*values = NULL_TREE;
else
dont_add = 1;
}
- else if (context && TYPE_DERIVES_FROM (context, type))
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now, we'll end
+ up subtracting from the address of MI_MATRIX, putting us off
+ in la la land. */
+ else if (context
+ && CLASSTYPE_CID (context)
+ && TYPE_DERIVES_FROM (context, type))
{
/* Don't add in *values to list */
*values = NULL_TREE;
? DECL_CLASS_CONTEXT (value)
: DECL_CONTEXT (value);
- if (context && TYPE_DERIVES_FROM (context, type))
+ /* If we don't check CLASSTYPE_CID on CONTEXT right now, we'll end
+ up subtracting from the address of MI_MATRIX, putting us off
+ in la la land. */
+ if (context
+ && CLASSTYPE_CID (context)
+ && TYPE_DERIVES_FROM (context, type))
{
/* remove *tmp from list */
*tmp = TREE_CHAIN (*tmp);
}
/* Consolidate unique (by name) member functions. */
+
static void
dfs_compress_decls (binfo)
tree binfo;
with `error_mark_node' so that if they are encountered
without explicit qualification, we can emit an error
message. */
+
void
push_class_decls (type)
tree type;
}
/* Here's a subroutine we need because C lacks lambdas. */
+
static void
dfs_unuse_fields (binfo)
tree binfo;
tree tmp = TREE_VEC_ELT (method_vec, i);
if (! IDENTIFIER_TYPENAME_P (DECL_NAME (tmp)))
break;
- conversions = tree_cons (DECL_NAME (tmp), TREE_TYPE (TREE_TYPE (tmp)),
- conversions);
+ conversions = tree_cons (binfo, tmp, conversions);
}
+ SET_BINFO_MARKED (binfo);
}
tree
tree type;
{
conversions = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), add_conversions, 0);
+ if (TYPE_SIZE (type))
+ {
+ dfs_walk (TYPE_BINFO (type), add_conversions, unmarkedp);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
+ }
return conversions;
}
+
+/* Subroutine of get_template_base. */
+
+static tree
+get_template_base_recursive (binfo, rval, template, via_virtual)
+ tree binfo, template, rval;
+ int via_virtual;
+{
+ tree binfos;
+ int i, n_baselinks;
+ tree type = BINFO_TYPE (binfo);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ {
+ if (rval == NULL_TREE || rval == type)
+ return type;
+ else
+ return error_mark_node;
+ }
+
+ 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);
+
+ /* Find any specific instance of a virtual base, when searching with
+ a binfo... */
+ if (BINFO_MARKED (base_binfo) == 0)
+ {
+ int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo);
+
+ /* When searching for a non-virtual, we cannot mark
+ virtually found binfos. */
+ if (! this_virtual)
+ SET_BINFO_MARKED (base_binfo);
+
+ rval = get_template_base_recursive
+ (base_binfo, rval, template, this_virtual);
+ if (rval == error_mark_node)
+ return rval;
+ }
+ }
+
+ return rval;
+}
+
+/* Given a class template TEMPLATE and a class type or binfo node BINFO,
+ find the unique base type in BINFO that is an instance of TEMPLATE.
+ If there are more than one, return error_mark_node. Used by unify. */
+
+tree
+get_template_base (template, binfo)
+ register tree template, binfo;
+{
+ tree type, rval;
+
+ if (TREE_CODE (binfo) == TREE_VEC)
+ type = BINFO_TYPE (binfo);
+ else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo)))
+ {
+ type = complete_type (binfo);
+ binfo = TYPE_BINFO (type);
+ }
+ else
+ my_friendly_abort (92);
+
+ if (CLASSTYPE_TEMPLATE_INFO (type)
+ && CLASSTYPE_TI_TEMPLATE (type) == template)
+ return type;
+
+ rval = get_template_base_recursive (binfo, NULL_TREE, template, 0);
+ dfs_walk (binfo, dfs_unmark, markedp);
+
+ return rval;
+}