summaryrefslogtreecommitdiff
path: root/gcc/cp/search.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/search.c')
-rw-r--r--gcc/cp/search.c797
1 files changed, 277 insertions, 520 deletions
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 395464e0ef9..8fd1ee52e72 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -82,18 +82,15 @@ struct vbase_info
};
static tree lookup_field_1 (tree, tree);
-static int is_subobject_of_p (tree, tree, tree);
-static int is_subobject_of_p_1 (tree, tree, tree);
static tree dfs_check_overlap (tree, void *);
-static tree dfs_no_overlap_yet (tree, void *);
+static tree dfs_no_overlap_yet (tree, int, void *);
static base_kind lookup_base_r (tree, tree, base_access,
bool, bool, bool, tree *);
static int dynamic_cast_base_recurse (tree, tree, bool, tree *);
-static tree marked_pushdecls_p (tree, void *);
-static tree unmarked_pushdecls_p (tree, void *);
-static tree dfs_debug_unmarkedp (tree, void *);
+static tree marked_pushdecls_p (tree, int, void *);
+static tree unmarked_pushdecls_p (tree, int, void *);
+static tree dfs_debug_unmarkedp (tree, int, void *);
static tree dfs_debug_mark (tree, void *);
-static tree dfs_get_vbase_types (tree, void *);
static tree dfs_push_type_decls (tree, void *);
static tree dfs_push_decls (tree, void *);
static tree dfs_unuse_fields (tree, void *);
@@ -104,28 +101,19 @@ static struct search_level *push_search_level (struct stack_level *,
static struct search_level *pop_search_level (struct stack_level *);
static void grow_bfs_bases (tree **, size_t *, size_t *);
static tree bfs_walk (tree, tree (*) (tree, void *),
- tree (*) (tree, void *), void *);
-static tree lookup_field_queue_p (tree, void *);
+ tree (*) (tree, int, void *), void *);
+static tree lookup_field_queue_p (tree, int, void *);
static int shared_member_p (tree);
static tree lookup_field_r (tree, void *);
-static tree canonical_binfo (tree);
-static tree shared_marked_p (tree, void *);
-static tree shared_unmarked_p (tree, void *);
-static int dependent_base_p (tree);
-static tree dfs_accessible_queue_p (tree, void *);
+static tree dfs_accessible_queue_p (tree, int, void *);
static tree dfs_accessible_p (tree, void *);
static tree dfs_access_in_type (tree, void *);
static access_kind access_in_type (tree, tree);
-static tree dfs_canonical_queue (tree, void *);
-static tree dfs_assert_unmarked_p (tree, void *);
-static void assert_canonical_unmarked (tree);
static int protected_accessible_p (tree, tree, tree);
static int friend_accessible_p (tree, tree, tree);
static void setup_class_bindings (tree, int);
static int template_self_reference_p (tree, tree);
-static tree dfs_find_vbase_instance (tree, void *);
static tree dfs_get_pure_virtuals (tree, void *);
-static tree dfs_build_inheritance_graph_order (tree, void *);
/* Allocate a level of searching. */
@@ -183,7 +171,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
tree *binfo_ptr)
{
int i;
- tree bases;
+ tree bases, accesses;
base_kind found = bk_not_base;
if (access == ba_check
@@ -207,8 +195,7 @@ lookup_base_r (tree binfo, tree base, base_access access,
if (!*binfo_ptr)
*binfo_ptr = binfo;
- else if (!is_virtual || !tree_int_cst_equal (BINFO_OFFSET (binfo),
- BINFO_OFFSET (*binfo_ptr)))
+ else if (binfo != *binfo_ptr)
{
if (access != ba_any)
*binfo_ptr = NULL;
@@ -222,23 +209,26 @@ lookup_base_r (tree binfo, tree base, base_access access,
}
bases = BINFO_BASETYPES (binfo);
+ accesses = BINFO_BASEACCESSES (binfo);
if (!bases)
return bk_not_base;
for (i = TREE_VEC_LENGTH (bases); i--;)
{
tree base_binfo = TREE_VEC_ELT (bases, i);
+ tree base_access = TREE_VEC_ELT (accesses, i);
+
int this_non_public = is_non_public;
int this_virtual = is_virtual;
base_kind bk;
if (access <= ba_ignore)
; /* no change */
- else if (TREE_VIA_PUBLIC (base_binfo))
+ else if (base_access == access_public_node)
; /* no change */
else if (access == ba_not_special)
this_non_public = 1;
- else if (TREE_VIA_PROTECTED (base_binfo) && within_current_scope)
+ else if (base_access == access_protected_node && within_current_scope)
; /* no change */
else if (is_friend (BINFO_TYPE (binfo), current_scope ()))
; /* no change */
@@ -290,9 +280,9 @@ lookup_base_r (tree binfo, tree base, base_access access,
}
/* 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 discovered.
+ ACCESS specifies. Return the binfo we discover. If KIND_PTR is
+ non-NULL, fill with information about what kind of base we
+ discovered.
If the base is inaccessible, or ambiguous, and the ba_quiet bit is
not set in ACCESS, then an error is issued and error_mark_node is
@@ -365,7 +355,7 @@ static int
dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
tree *offset_ptr)
{
- tree binfos;
+ tree binfos, accesses;
int i, n_baselinks;
int worst = -2;
@@ -381,13 +371,15 @@ dynamic_cast_base_recurse (tree subtype, tree binfo, bool is_via_virtual,
}
binfos = BINFO_BASETYPES (binfo);
+ accesses = BINFO_BASEACCESSES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
+ tree base_access = TREE_VEC_ELT (accesses, i);
int rval;
- if (!TREE_VIA_PUBLIC (base_binfo))
+ if (base_access != access_public_node)
continue;
rval = dynamic_cast_base_recurse
(subtype, base_binfo,
@@ -603,74 +595,17 @@ context_for_name_lookup (tree decl)
return context;
}
-/* Return a canonical BINFO if BINFO is a virtual base, or just BINFO
- otherwise. */
-
-static tree
-canonical_binfo (tree binfo)
-{
- return (TREE_VIA_VIRTUAL (binfo)
- ? TYPE_BINFO (BINFO_TYPE (binfo)) : binfo);
-}
-
-/* A queue function that simply ensures that we walk into the
- canonical versions of virtual bases. */
-
-static tree
-dfs_canonical_queue (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- return canonical_binfo (binfo);
-}
-
-/* Called via dfs_walk from assert_canonical_unmarked. */
-
-static tree
-dfs_assert_unmarked_p (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- my_friendly_assert (!BINFO_MARKED (binfo), 0);
- return NULL_TREE;
-}
-
-/* Asserts that all the nodes below BINFO (using the canonical
- versions of virtual bases) are unmarked. */
-
-static void
-assert_canonical_unmarked (tree binfo)
-{
- dfs_walk (binfo, dfs_assert_unmarked_p, dfs_canonical_queue, 0);
-}
-
-/* If BINFO is marked, return a canonical version of BINFO.
- Otherwise, return NULL_TREE. */
-
-static tree
-shared_marked_p (tree binfo, void *data)
-{
- binfo = canonical_binfo (binfo);
- return markedp (binfo, data);
-}
-
-/* If BINFO is not marked, return a canonical version of BINFO.
- Otherwise, return NULL_TREE. */
-
-static tree
-shared_unmarked_p (tree binfo, void *data)
-{
- binfo = canonical_binfo (binfo);
- return unmarkedp (binfo, data);
-}
-
/* The accessibility routines use BINFO_ACCESS for scratch space
during the computation of the accssibility of some declaration. */
#define BINFO_ACCESS(NODE) \
- ((access_kind) ((TREE_LANG_FLAG_1 (NODE) << 1) | TREE_LANG_FLAG_6 (NODE)))
+ ((access_kind) ((TREE_PUBLIC (NODE) << 1) | TREE_PRIVATE (NODE)))
/* Set the access associated with NODE to ACCESS. */
#define SET_BINFO_ACCESS(NODE, ACCESS) \
- ((TREE_LANG_FLAG_1 (NODE) = ((ACCESS) & 2) != 0), \
- (TREE_LANG_FLAG_6 (NODE) = ((ACCESS) & 1) != 0))
+ ((TREE_PUBLIC (NODE) = ((ACCESS) & 2) != 0), \
+ (TREE_PRIVATE (NODE) = ((ACCESS) & 1) != 0))
/* Called from access_in_type via dfs_walk. Calculate the access to
DATA (which is really a DECL) in BINFO. */
@@ -702,51 +637,59 @@ dfs_access_in_type (tree binfo, void *data)
if (DECL_LANG_SPECIFIC (decl) && !DECL_DISCRIMINATOR_P (decl))
{
tree decl_access = purpose_member (type, DECL_ACCESS (decl));
+
if (decl_access)
- access = ((access_kind)
- TREE_INT_CST_LOW (TREE_VALUE (decl_access)));
+ {
+ decl_access = TREE_VALUE (decl_access);
+
+ if (decl_access == access_public_node)
+ access = ak_public;
+ else if (decl_access == access_protected_node)
+ access = ak_protected;
+ else if (decl_access == access_private_node)
+ access = ak_private;
+ else
+ my_friendly_assert (false, 20030217);
+ }
}
if (!access)
{
int i;
int n_baselinks;
- tree binfos;
+ tree binfos, accesses;
/* Otherwise, scan our baseclasses, and pick the most favorable
access. */
binfos = BINFO_BASETYPES (binfo);
+ accesses = BINFO_BASEACCESSES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
for (i = 0; i < n_baselinks; ++i)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
- access_kind base_access
- = BINFO_ACCESS (canonical_binfo (base_binfo));
+ tree base_access = TREE_VEC_ELT (accesses, i);
+ access_kind base_access_now = BINFO_ACCESS (base_binfo);
- if (base_access == ak_none || base_access == ak_private)
+ if (base_access_now == ak_none || base_access_now == ak_private)
/* If it was not accessible in the base, or only
accessible as a private member, we can't access it
all. */
- base_access = ak_none;
- else if (TREE_VIA_PROTECTED (base_binfo))
- /* Public and protected members in the base are
+ base_access_now = ak_none;
+ else if (base_access == access_protected_node)
+ /* Public and protected members in the base become
protected here. */
- base_access = ak_protected;
- else if (!TREE_VIA_PUBLIC (base_binfo))
- /* Public and protected members in the base are
+ base_access_now = ak_protected;
+ else if (base_access == access_private_node)
+ /* Public and protected members in the base become
private here. */
- base_access = ak_private;
+ base_access_now = ak_private;
/* See if the new access, via this base, gives more
access than our previous best access. */
- if (base_access != ak_none
- && (base_access == ak_public
- || (base_access == ak_protected
- && access != ak_public)
- || (base_access == ak_private
- && access == ak_none)))
+ if (base_access_now != ak_none
+ && (access == ak_none || base_access_now < access))
{
- access = base_access;
+ access = base_access_now;
/* If the new access is public, we can't do better. */
if (access == ak_public)
@@ -761,7 +704,7 @@ dfs_access_in_type (tree binfo, void *data)
/* Mark TYPE as visited so that if we reach it again we do not
duplicate our efforts here. */
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
return NULL_TREE;
}
@@ -784,9 +727,8 @@ access_in_type (tree type, tree decl)
The algorithm we use is to make a post-order depth-first traversal
of the base-class hierarchy. As we come up the tree, we annotate
each node with the most lenient access. */
- dfs_walk_real (binfo, 0, dfs_access_in_type, shared_unmarked_p, decl);
- dfs_walk (binfo, dfs_unmark, shared_marked_p, 0);
- assert_canonical_unmarked (binfo);
+ dfs_walk_real (binfo, 0, dfs_access_in_type, unmarkedp, decl);
+ dfs_walk (binfo, dfs_unmark, markedp, 0);
return BINFO_ACCESS (binfo);
}
@@ -794,19 +736,20 @@ access_in_type (tree type, tree decl)
/* Called from dfs_accessible_p via dfs_walk. */
static tree
-dfs_accessible_queue_p (tree binfo, void *data ATTRIBUTE_UNUSED)
+dfs_accessible_queue_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
if (BINFO_MARKED (binfo))
return NULL_TREE;
/* If this class is inherited via private or protected inheritance,
- then we can't see it, unless we are a friend of the subclass. */
- if (!TREE_VIA_PUBLIC (binfo)
- && !is_friend (BINFO_TYPE (BINFO_INHERITANCE_CHAIN (binfo)),
- current_scope ()))
+ then we can't see it, unless we are a friend of the derived class. */
+ if (BINFO_BASEACCESS (derived, ix) != access_public_node
+ && !is_friend (BINFO_TYPE (derived), current_scope ()))
return NULL_TREE;
- return canonical_binfo (binfo);
+ return binfo;
}
/* Called from dfs_accessible_p via dfs_walk. */
@@ -817,7 +760,7 @@ dfs_accessible_p (tree binfo, void *data)
int protected_ok = data != 0;
access_kind access;
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
access = BINFO_ACCESS (binfo);
if (access == ak_public || (access == ak_protected && protected_ok))
return binfo;
@@ -1015,75 +958,11 @@ accessible_p (tree type, tree decl)
/* Clear any mark bits. Note that we have to walk the whole tree
here, since we have aborted the previous walk from some point
deep in the tree. */
- dfs_walk (binfo, dfs_unmark, dfs_canonical_queue, 0);
- assert_canonical_unmarked (binfo);
+ dfs_walk (binfo, dfs_unmark, 0, 0);
return t != NULL_TREE;
}
-/* Recursive helper funciton for is_subobject_of_p; see that routine
- for documentation of the parameters. */
-
-static int
-is_subobject_of_p_1 (tree parent, tree binfo, tree most_derived)
-{
- tree binfos;
- int i, n_baselinks;
-
- if (parent == binfo)
- return 1;
-
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
- /* Iterate through the base types. */
- for (i = 0; i < n_baselinks; i++)
- {
- tree base_binfo = TREE_VEC_ELT (binfos, i);
- tree base_type;
-
- base_type = TREE_TYPE (base_binfo);
- if (!CLASS_TYPE_P (base_type))
- /* If we see a TEMPLATE_TYPE_PARM, or some such, as a base
- class there's no way to descend into it. */
- continue;
-
- /* Avoid walking into the same virtual base more than once. */
- if (TREE_VIA_VIRTUAL (base_binfo))
- {
- if (CLASSTYPE_MARKED4 (base_type))
- continue;
- SET_CLASSTYPE_MARKED4 (base_type);
- base_binfo = binfo_for_vbase (base_type, most_derived);
- }
-
- if (is_subobject_of_p_1 (parent, base_binfo, most_derived))
- return 1;
- }
- return 0;
-}
-
-/* Routine to see if the sub-object denoted by the binfo PARENT can be
- found as a base class and sub-object of the object denoted by
- BINFO. MOST_DERIVED is the most derived type of the hierarchy being
- searched. */
-
-static int
-is_subobject_of_p (tree parent, tree binfo, tree most_derived)
-{
- int result;
- tree vbase;
-
- result = is_subobject_of_p_1 (parent, binfo, most_derived);
- /* Clear the mark bits on virtual bases. */
- for (vbase = CLASSTYPE_VBASECLASSES (most_derived);
- vbase;
- vbase = TREE_CHAIN (vbase))
- CLEAR_CLASSTYPE_MARKED4 (TREE_TYPE (TREE_VALUE (vbase)));
-
- return result;
-}
-
struct lookup_field_info {
/* The type in which we're looking. */
tree type;
@@ -1098,8 +977,6 @@ struct lookup_field_info {
tree ambiguous;
/* If nonzero, we are looking for types, not data members. */
int want_type;
- /* If nonzero, RVAL was found by looking through a dependent base. */
- int from_dep_base_p;
/* If something went wrong, a message indicating what. */
const char *errstr;
};
@@ -1110,8 +987,9 @@ struct lookup_field_info {
lookup_field via breadth_first_search. */
static tree
-lookup_field_queue_p (tree binfo, void *data)
+lookup_field_queue_p (tree derived, int ix, void *data)
{
+ tree binfo = BINFO_BASETYPE (derived, ix);
struct lookup_field_info *lfi = (struct lookup_field_info *) data;
/* Don't look for constructors or destructors in base classes. */
@@ -1120,11 +998,13 @@ lookup_field_queue_p (tree binfo, void *data)
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
- binfo = CANONICAL_BINFO (binfo, lfi->type);
- if (!lfi->from_dep_base_p && lfi->rval_binfo
- && is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+ if (lfi->rval_binfo && original_binfo (binfo, lfi->rval_binfo))
return NULL_TREE;
+ /* If this is a dependent base, don't look in it. */
+ if (BINFO_DEPENDENT_BASE_P (binfo))
+ return NULL_TREE;
+
return binfo;
}
@@ -1187,7 +1067,6 @@ lookup_field_r (tree binfo, void *data)
struct lookup_field_info *lfi = (struct lookup_field_info *) data;
tree type = BINFO_TYPE (binfo);
tree nval = NULL_TREE;
- int from_dep_base_p;
/* First, look for a function. There can't be a function and a data
member with the same name, and if there's a function and a type
@@ -1241,40 +1120,14 @@ lookup_field_r (tree binfo, void *data)
&& template_self_reference_p (type, nval))
return NULL_TREE;
- from_dep_base_p = dependent_base_p (binfo);
- if (lfi->from_dep_base_p && !from_dep_base_p)
- {
- /* If the new declaration is not found via a dependent base, and
- the old one was, then we must prefer the new one. We weren't
- really supposed to be able to find the old one, so we don't
- want to be affected by a specialization. Consider:
-
- struct B { typedef int I; };
- template <typename T> struct D1 : virtual public B {};
- template <typename T> struct D :
- public D1, virtual pubic B { I i; };
-
- The `I' in `D<T>' is unambigousuly `B::I', regardless of how
- D1 is specialized. */
- lfi->from_dep_base_p = 0;
- lfi->rval = NULL_TREE;
- lfi->rval_binfo = NULL_TREE;
- lfi->ambiguous = NULL_TREE;
- lfi->errstr = 0;
- }
- else if (lfi->rval_binfo && !lfi->from_dep_base_p && from_dep_base_p)
- /* Similarly, if the old declaration was not found via a dependent
- base, and the new one is, ignore the new one. */
- return NULL_TREE;
-
/* If the lookup already found a match, and the new value doesn't
hide the old one, we might have an ambiguity. */
- if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type))
+ if (lfi->rval_binfo && !original_binfo (lfi->rval_binfo, binfo))
{
if (nval == lfi->rval && shared_member_p (nval))
/* The two things are really the same. */
;
- else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
+ else if (original_binfo (binfo, lfi->rval_binfo))
/* The previous value hides the new one. */
;
else
@@ -1298,18 +1151,7 @@ lookup_field_r (tree binfo, void *data)
}
else
{
- if (from_dep_base_p && TREE_CODE (nval) == TYPE_DECL
- /* We need to return a member template class so we can
- define partial specializations. Is there a better
- way? */
- && !DECL_CLASS_TEMPLATE_P (nval))
- /* The thing we're looking for isn't a type, so the implicit
- typename extension doesn't apply, so we just pretend we
- didn't find anything. */
- return NULL_TREE;
-
lfi->rval = nval;
- lfi->from_dep_base_p = from_dep_base_p;
lfi->rval_binfo = binfo;
}
@@ -1443,11 +1285,6 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
rval = error_mark_node;
}
- /* If the thing we found was found via the implicit typename
- extension, build the typename type. */
- if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval))
- abort ();
-
if (rval && is_overloaded_fn (rval))
rval = build_baselink (rval_binfo, basetype_path, rval,
(IDENTIFIER_TYPENAME_P (name)
@@ -1679,8 +1516,10 @@ grow_bfs_bases (tree **basep, size_t *sizep, size_t *headp)
use do-while for the inner loop. */
static tree
-bfs_walk (tree binfo, tree (*fn) (tree, void *),
- tree (*qfn) (tree, void *), void *data)
+bfs_walk (tree binfo,
+ tree (*fn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
tree rval = NULL_TREE;
@@ -1698,54 +1537,50 @@ bfs_walk (tree binfo, tree (*fn) (tree, void *),
return rval;
/* If it has no base types, we are also done. */
- if (BINFO_BASETYPES (binfo) == 0
- || TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 0)
+ if (!BINFO_BASETYPES (binfo))
return 0;
/* Otherwise, initialize the queue with its basetypes vector
and proceed. */
head = tail = 0;
- bfs_bases[tail++] = BINFO_BASETYPES (binfo);
+ bfs_bases[tail++] = binfo;
- do
+ while (head != tail)
{
- int i, n_baselinks;
- tree binfos;
-
- binfos = bfs_bases[head++];
+ int n_bases, ix;
+ tree binfo = bfs_bases[head++];
if (head == bfs_bases_size)
head = 0;
- i = 0;
- n_baselinks = TREE_VEC_LENGTH (binfos);
- do
- {
- binfo = TREE_VEC_ELT (binfos, i);
- i++;
-
- if (qfn)
- binfo = qfn (binfo, data);
- if (!binfo)
- continue;
+ /* Is this the one we're looking for? If so, we're done. */
+ rval = fn (binfo, data);
+ if (rval)
+ goto done;
- rval = fn (binfo, data);
- if (rval)
- goto done;
+ n_bases = BINFO_N_BASETYPES (binfo);
+ if (n_bases)
+ {
+ for (ix = 0; ix != n_bases; ix++)
+ {
+ tree base_binfo;
- if (BINFO_BASETYPES (binfo) == 0
- || TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 0)
- continue;
+ if (qfn)
+ base_binfo = (*qfn) (binfo, ix, data);
+ else
+ base_binfo = BINFO_BASETYPE (binfo, ix);
- bfs_bases[tail++] = BINFO_BASETYPES (binfo);
- if (tail == bfs_bases_size)
- tail = 0;
- if (tail == head)
- grow_bfs_bases (&bfs_bases, &bfs_bases_size, &head);
+ if (base_binfo)
+ {
+ bfs_bases[tail++] = base_binfo;
+ if (tail == bfs_bases_size)
+ tail = 0;
+ if (tail == head)
+ grow_bfs_bases (&bfs_bases, &bfs_bases_size, &head);
+ }
+ }
}
- while (i < n_baselinks);
}
- while (head != tail);
done:
if (bfs_bases != bfs_bases_initial)
@@ -1758,13 +1593,12 @@ bfs_walk (tree binfo, tree (*fn) (tree, void *),
in postorder. */
tree
-dfs_walk_real (tree binfo,
- tree (*prefn) (tree, void *), tree (*postfn) (tree, void *),
- tree (*qfn) (tree, void *), void *data)
+dfs_walk_real (tree binfo,
+ tree (*prefn) (tree, void *),
+ tree (*postfn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
- int i;
- int n_baselinks;
- tree binfos;
tree rval = NULL_TREE;
/* Call the pre-order walking function. */
@@ -1776,20 +1610,24 @@ dfs_walk_real (tree binfo,
}
/* Process the basetypes. */
- binfos = BINFO_BASETYPES (binfo);
- n_baselinks = BINFO_N_BASETYPES (binfo);
- for (i = 0; i < n_baselinks; i++)
+ if (BINFO_BASETYPES (binfo))
{
- tree base_binfo = TREE_VEC_ELT (binfos, i);
-
- if (qfn)
- base_binfo = (*qfn) (base_binfo, data);
-
- if (base_binfo)
+ int i, n = TREE_VEC_LENGTH (BINFO_BASETYPES (binfo));
+ for (i = 0; i != n; i++)
{
- rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
- if (rval)
- return rval;
+ tree base_binfo;
+
+ if (qfn)
+ base_binfo = (*qfn) (binfo, i, data);
+ else
+ base_binfo = BINFO_BASETYPE (binfo, i);
+
+ if (base_binfo)
+ {
+ rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data);
+ if (rval)
+ return rval;
+ }
}
}
@@ -1804,8 +1642,10 @@ dfs_walk_real (tree binfo,
performed. */
tree
-dfs_walk (tree binfo, tree (*fn) (tree, void *),
- tree (*qfn) (tree, void *), void *data)
+dfs_walk (tree binfo,
+ tree (*fn) (tree, void *),
+ tree (*qfn) (tree, int, void *),
+ void *data)
{
return dfs_walk_real (binfo, 0, fn, qfn, data);
}
@@ -2007,59 +1847,6 @@ look_for_overrides_r (tree type, tree fndecl)
return look_for_overrides (type, fndecl);
}
-/* A queue function to use with dfs_walk that only walks into
- canonical bases. DATA should be the type of the complete object,
- or a TREE_LIST whose TREE_PURPOSE is the type of the complete
- object. By using this function as a queue function, you will walk
- over exactly those BINFOs that actually exist in the complete
- object, including those for virtual base classes. If you
- SET_BINFO_MARKED for each binfo you process, you are further
- guaranteed that you will walk into each virtual base class exactly
- once. */
-
-tree
-dfs_unmarked_real_bases_queue_p (tree binfo, void *data)
-{
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree type = (tree) data;
-
- if (TREE_CODE (type) == TREE_LIST)
- type = TREE_PURPOSE (type);
- binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
- }
- return unmarkedp (binfo, NULL);
-}
-
-/* Like dfs_unmarked_real_bases_queue_p but walks only into things
- that are marked, rather than unmarked. */
-
-tree
-dfs_marked_real_bases_queue_p (tree binfo, void *data)
-{
- if (TREE_VIA_VIRTUAL (binfo))
- {
- tree type = (tree) data;
-
- if (TREE_CODE (type) == TREE_LIST)
- type = TREE_PURPOSE (type);
- binfo = binfo_for_vbase (BINFO_TYPE (binfo), type);
- }
- return markedp (binfo, NULL);
-}
-
-/* A queue function that skips all virtual bases (and their
- bases). */
-
-tree
-dfs_skip_vbases (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- if (TREE_VIA_VIRTUAL (binfo))
- return NULL_TREE;
-
- return binfo;
-}
-
/* Called via dfs_walk from dfs_get_pure_virtuals. */
static tree
@@ -2083,7 +1870,7 @@ dfs_get_pure_virtuals (tree binfo, void *data)
CLASSTYPE_PURE_VIRTUALS (type));
}
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 1;
return NULL_TREE;
}
@@ -2104,10 +1891,8 @@ get_pure_virtuals (tree type)
(A primary base is not interesting because the derived class of
which it is a primary base will contain vtable entries for the
pure virtuals in the base class. */
- dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals,
- dfs_unmarked_real_bases_queue_p, type);
- dfs_walk (TYPE_BINFO (type), dfs_unmark,
- dfs_marked_real_bases_queue_p, type);
+ dfs_walk (TYPE_BINFO (type), dfs_get_pure_virtuals, unmarkedp, type);
+ dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, type);
/* Put the pure virtuals in dfs order. */
CLASSTYPE_PURE_VIRTUALS (type) = nreverse (CLASSTYPE_PURE_VIRTUALS (type));
@@ -2132,42 +1917,36 @@ get_pure_virtuals (tree type)
/* DEPTH-FIRST SEARCH ROUTINES. */
tree
-markedp (tree binfo, void *data ATTRIBUTE_UNUSED)
+markedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
return BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
tree
-unmarkedp (tree binfo, void *data ATTRIBUTE_UNUSED)
+unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-tree
-marked_vtable_pathp (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- return BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
-}
-
-tree
-unmarked_vtable_pathp (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- return !BINFO_VTABLE_PATH_MARKED (binfo) ? binfo : NULL_TREE;
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
+ return !BINFO_MARKED (binfo) ? binfo : NULL_TREE;
}
static tree
-marked_pushdecls_p (tree binfo, void *data ATTRIBUTE_UNUSED)
+marked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- return (CLASS_TYPE_P (BINFO_TYPE (binfo))
- && !dependent_base_p (binfo)
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
+ return (!BINFO_DEPENDENT_BASE_P (binfo)
&& BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
}
static tree
-unmarked_pushdecls_p (tree binfo, void *data ATTRIBUTE_UNUSED)
+unmarked_pushdecls_p (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
{
- return (CLASS_TYPE_P (BINFO_TYPE (binfo))
- && !dependent_base_p (binfo)
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
+ return (!BINFO_DEPENDENT_BASE_P (binfo)
&& !BINFO_PUSHDECLS_MARKED (binfo)) ? binfo : NULL_TREE;
}
@@ -2177,99 +1956,11 @@ unmarked_pushdecls_p (tree binfo, void *data ATTRIBUTE_UNUSED)
tree
dfs_unmark (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
- CLEAR_BINFO_MARKED (binfo);
- return NULL_TREE;
-}
-
-/* get virtual base class types.
- This adds type to the vbase_types list in reverse dfs order.
- Ordering is very important, so don't change it. */
-
-static tree
-dfs_get_vbase_types (tree binfo, void *data)
-{
- tree type = (tree) data;
-
- if (TREE_VIA_VIRTUAL (binfo))
- CLASSTYPE_VBASECLASSES (type)
- = tree_cons (BINFO_TYPE (binfo),
- binfo,
- CLASSTYPE_VBASECLASSES (type));
- SET_BINFO_MARKED (binfo);
- return NULL_TREE;
-}
-
-/* Called via dfs_walk from mark_primary_bases. Builds the
- inheritance graph order list of BINFOs. */
-
-static tree
-dfs_build_inheritance_graph_order (tree binfo, void *data)
{
- tree *last_binfo = (tree *) data;
-
- if (*last_binfo)
- TREE_CHAIN (*last_binfo) = binfo;
- *last_binfo = binfo;
- SET_BINFO_MARKED (binfo);
+ BINFO_MARKED (binfo) = 0;
return NULL_TREE;
}
-/* Set CLASSTYPE_VBASECLASSES for TYPE. */
-
-void
-get_vbase_types (tree type)
-{
- tree last_binfo;
-
- CLASSTYPE_VBASECLASSES (type) = NULL_TREE;
- dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp, type);
- /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
- reverse it so that we get normal dfs ordering. */
- CLASSTYPE_VBASECLASSES (type) = nreverse (CLASSTYPE_VBASECLASSES (type));
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, 0);
- /* Thread the BINFOs in inheritance-graph order. */
- last_binfo = NULL;
- dfs_walk_real (TYPE_BINFO (type),
- dfs_build_inheritance_graph_order,
- NULL,
- unmarkedp,
- &last_binfo);
- dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp, NULL);
-}
-
-/* Called from find_vbase_instance via dfs_walk. */
-
-static tree
-dfs_find_vbase_instance (tree binfo, void *data)
-{
- tree base = TREE_VALUE ((tree) data);
-
- if (BINFO_PRIMARY_P (binfo)
- && same_type_p (BINFO_TYPE (binfo), base))
- return binfo;
-
- return NULL_TREE;
-}
-
-/* Find the real occurrence of the virtual BASE (a class type) in the
- hierarchy dominated by TYPE. */
-
-tree
-find_vbase_instance (tree base, tree type)
-{
- tree instance;
-
- instance = binfo_for_vbase (base, type);
- if (!BINFO_PRIMARY_P (instance))
- return instance;
-
- return dfs_walk (TYPE_BINFO (type),
- dfs_find_vbase_instance,
- NULL,
- build_tree_list (type, base));
-}
-
/* Debug info for C++ classes can get very large; try to avoid
emitting it everywhere.
@@ -2334,8 +2025,10 @@ dfs_debug_mark (tree binfo, void *data ATTRIBUTE_UNUSED)
info for this base class. */
static tree
-dfs_debug_unmarkedp (tree binfo, void *data ATTRIBUTE_UNUSED)
-{
+dfs_debug_unmarkedp (tree derived, int ix, void *data ATTRIBUTE_UNUSED)
+{
+ tree binfo = BINFO_BASETYPE (derived, ix);
+
return (!CLASSTYPE_DEBUG_REQUESTED (BINFO_TYPE (binfo))
? binfo : NULL_TREE);
}
@@ -2361,22 +2054,6 @@ note_debug_info_needed (tree type)
/* Subroutines of push_class_decls (). */
-/* Returns 1 iff BINFO is a base we shouldn't really be able to see into,
- because it (or one of the intermediate bases) depends on template parms. */
-
-static int
-dependent_base_p (tree binfo)
-{
- for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
- {
- if (currently_open_class (TREE_TYPE (binfo)))
- break;
- if (dependent_type_p (TREE_TYPE (binfo)))
- return 1;
- }
- return 0;
-}
-
static void
setup_class_bindings (tree name, int type_binding_p)
{
@@ -2449,7 +2126,7 @@ dfs_push_type_decls (tree binfo, void *data ATTRIBUTE_UNUSED)
/* We can't just use BINFO_MARKED because envelope_add_decl uses
DERIVED_FROM_P, which calls get_base_distance. */
- SET_BINFO_PUSHDECLS_MARKED (binfo);
+ BINFO_PUSHDECLS_MARKED (binfo) = 1;
return NULL_TREE;
}
@@ -2460,46 +2137,39 @@ dfs_push_type_decls (tree binfo, void *data ATTRIBUTE_UNUSED)
static tree
dfs_push_decls (tree binfo, void *data)
{
- tree type;
+ tree type = BINFO_TYPE (binfo);
tree method_vec;
- int dep_base_p;
-
- type = BINFO_TYPE (binfo);
- dep_base_p = (processing_template_decl && type != current_class_type
- && dependent_base_p (binfo));
- if (!dep_base_p)
+ tree fields;
+
+ for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
+ if (DECL_NAME (fields)
+ && TREE_CODE (fields) != TYPE_DECL
+ && TREE_CODE (fields) != USING_DECL
+ && !DECL_ARTIFICIAL (fields))
+ setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
+ else if (TREE_CODE (fields) == FIELD_DECL
+ && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
+ dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
+
+ method_vec = (CLASS_TYPE_P (type)
+ ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
+
+ if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
{
- tree fields;
- for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
- if (DECL_NAME (fields)
- && TREE_CODE (fields) != TYPE_DECL
- && TREE_CODE (fields) != USING_DECL
- && !DECL_ARTIFICIAL (fields))
- setup_class_bindings (DECL_NAME (fields), /*type_binding_p=*/0);
- else if (TREE_CODE (fields) == FIELD_DECL
- && ANON_AGGR_TYPE_P (TREE_TYPE (fields)))
- dfs_push_decls (TYPE_BINFO (TREE_TYPE (fields)), data);
-
- method_vec = (CLASS_TYPE_P (type)
- ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE);
-
- if (method_vec && TREE_VEC_LENGTH (method_vec) >= 3)
- {
- tree *methods;
- tree *end;
-
- /* Farm out constructors and destructors. */
- end = TREE_VEC_END (method_vec);
-
- for (methods = &TREE_VEC_ELT (method_vec, 2);
- methods < end && *methods;
- methods++)
- setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
- /*type_binding_p=*/0);
- }
+ tree *methods;
+ tree *end;
+
+ /* Farm out constructors and destructors. */
+ end = TREE_VEC_END (method_vec);
+
+ for (methods = &TREE_VEC_ELT (method_vec, 2);
+ methods < end && *methods;
+ methods++)
+ setup_class_bindings (DECL_NAME (OVL_CURRENT (*methods)),
+ /*type_binding_p=*/0);
}
- CLEAR_BINFO_PUSHDECLS_MARKED (binfo);
+ BINFO_PUSHDECLS_MARKED (binfo) = 0;
return NULL_TREE;
}
@@ -2678,9 +2348,11 @@ dfs_check_overlap (tree empty_binfo, void *data)
/* Trivial function to stop base traversal when we find something. */
static tree
-dfs_no_overlap_yet (tree binfo, void *data)
+dfs_no_overlap_yet (tree derived, int ix, void *data)
{
+ tree binfo = BINFO_BASETYPE (derived, ix);
struct overlap_info *oi = (struct overlap_info *) data;
+
return !oi->found_overlap ? binfo : NULL_TREE;
}
@@ -2759,14 +2431,99 @@ binfo_via_virtual (tree binfo, tree limit)
return NULL_TREE;
}
-/* Returns the BINFO (if any) for the virtual baseclass T of the class
- C from the CLASSTYPE_VBASECLASSES list. */
+/* BINFO is a base binfo in the complete type BINFO_TYPE (HERE).
+ Find the equivalent binfo within whatever graph HERE is located.
+ This is the inverse of original_binfo. */
tree
-binfo_for_vbase (tree basetype, tree classtype)
+copied_binfo (tree binfo, tree here)
{
- tree binfo;
+ tree result = NULL_TREE;
+
+ if (TREE_VIA_VIRTUAL (binfo))
+ {
+ tree t;
- binfo = purpose_member (basetype, CLASSTYPE_VBASECLASSES (classtype));
- return binfo ? TREE_VALUE (binfo) : NULL_TREE;
+ for (t = here; BINFO_INHERITANCE_CHAIN (t);
+ t = BINFO_INHERITANCE_CHAIN (t))
+ continue;
+
+ result = purpose_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (BINFO_TYPE (t)));
+ result = TREE_VALUE (result);
+ }
+ else if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ tree base_binfos;
+ int ix, n;
+
+ base_binfos = copied_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+ base_binfos = BINFO_BASETYPES (base_binfos);
+ n = TREE_VEC_LENGTH (base_binfos);
+ for (ix = 0; ix != n; ix++)
+ {
+ tree base = TREE_VEC_ELT (base_binfos, ix);
+
+ if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
+ {
+ result = base;
+ break;
+ }
+ }
+ }
+ else
+ {
+ my_friendly_assert (BINFO_TYPE (here) == BINFO_TYPE (binfo), 20030202);
+ result = here;
+ }
+
+ my_friendly_assert (result, 20030202);
+ return result;
}
+
+/* BINFO is some base binfo of HERE, within some other
+ hierachy. Return the equivalent binfo, but in the hierarchy
+ dominated by HERE. This is the inverse of copied_binfo. If BINFO
+ is not a base binfo of HERE, returns NULL_TREE. */
+
+tree
+original_binfo (tree binfo, tree here)
+{
+ tree result = NULL;
+
+ if (BINFO_TYPE (binfo) == BINFO_TYPE (here))
+ result = here;
+ else if (TREE_VIA_VIRTUAL (binfo))
+ {
+ result = purpose_member (BINFO_TYPE (binfo),
+ CLASSTYPE_VBASECLASSES (BINFO_TYPE (here)));
+ if (result)
+ result = TREE_VALUE (result);
+ }
+ else if (BINFO_INHERITANCE_CHAIN (binfo))
+ {
+ tree base_binfos;
+
+ base_binfos = original_binfo (BINFO_INHERITANCE_CHAIN (binfo), here);
+ if (base_binfos)
+ {
+ int ix, n;
+
+ base_binfos = BINFO_BASETYPES (base_binfos);
+ n = TREE_VEC_LENGTH (base_binfos);
+ for (ix = 0; ix != n; ix++)
+ {
+ tree base = TREE_VEC_ELT (base_binfos, ix);
+
+ if (BINFO_TYPE (base) == BINFO_TYPE (binfo))
+ {
+ result = base;
+ break;
+ }
+ }
+ }
+ }
+
+ return result;
+}
+