summaryrefslogtreecommitdiffstats
path: root/gcc
diff options
context:
space:
mode:
authornathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-12 14:23:39 +0000
committernathan <nathan@138bc75d-0d04-0410-961f-82ee72b054a4>2004-10-12 14:23:39 +0000
commitc9f9c2d0caebbd964c2d5bd4d314711ed6e5726c (patch)
treedcd9d9902f0cff883d070b0448bdb325105a0bf2 /gcc
parent016ae2c6ced3bb7cc663655e7fa0b16eee40e938 (diff)
downloadppe42-gcc-c9f9c2d0caebbd964c2d5bd4d314711ed6e5726c.tar.gz
ppe42-gcc-c9f9c2d0caebbd964c2d5bd4d314711ed6e5726c.zip
* search.c (struct lookup_base_data_s): New.
(lookup_base_r): Replace with ... (dfs_lookup_base): ... this. (lookup_base): Use dfs_walk_all. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@88934 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/search.c172
2 files changed, 100 insertions, 79 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 688a0d3bfaa..5b87487923d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2004-10-12 Nathan Sidwell <nathan@codesourcery.com>
+
+ * search.c (struct lookup_base_data_s): New.
+ (lookup_base_r): Replace with ...
+ (dfs_lookup_base): ... this.
+ (lookup_base): Use dfs_walk_all.
+
2004-10-12 Kazu Hirata <kazu@cs.umass.edu>
* search.c: Fix comment typos.
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 9c3d23077f9..9ab861f6aef 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -37,9 +37,9 @@ Boston, MA 02111-1307, USA. */
#include "stack.h"
static int is_subobject_of_p (tree, tree);
+static tree dfs_lookup_base (tree, void *);
static tree dfs_dcast_hint_pre (tree, void *);
static tree dfs_dcast_hint_post (tree, void *);
-static base_kind lookup_base_r (tree, tree, base_access, bool, tree *);
static tree dfs_debug_mark (tree, void *);
static tree dfs_walk_once_r (tree, tree (*pre_fn) (tree, void *),
tree (*post_fn) (tree, void *), void *data);
@@ -78,88 +78,75 @@ static int n_contexts_saved;
#endif /* GATHER_STATISTICS */
-/* 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. IS_VIRTUAL indicates if BINFO 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 (tree binfo, tree base, base_access access,
- bool is_virtual, /* inside a virtual part */
- tree *binfo_ptr)
+/* Data for lookup_base and its workers. */
+
+struct lookup_base_data_s
{
- int i;
- tree base_binfo;
- base_kind found = bk_not_base;
-
- if (SAME_BINFO_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 (!*binfo_ptr)
- *binfo_ptr = binfo;
- else if (binfo != *binfo_ptr)
- {
- if (access != ba_any)
- *binfo_ptr = NULL;
- else if (!is_virtual)
- /* Prefer a non-virtual base. */
- *binfo_ptr = binfo;
- found = bk_ambig;
- }
-
- return found;
- }
-
- for (i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
- {
- base_kind bk;
+ tree t; /* type being searched. */
+ tree base; /* The base type we're looking for. */
+ tree binfo; /* Found binfo. */
+ bool via_virtual; /* Found via a virtual path. */
+ bool ambiguous; /* Found multiply ambiguous */
+ bool repeated_base; /* Whether there are repeated bases in the
+ hierarchy. */
+ bool want_any; /* Whether we want any matching binfo. */
+};
+
+/* Worker function for lookup_base. See if we've found the desired
+ base and update DATA_ (a pointer to LOOKIP_BASE_DATA_S). */
- bk = lookup_base_r (base_binfo, base,
- access,
- is_virtual || BINFO_VIRTUAL_P (base_binfo),
- binfo_ptr);
+static tree
+dfs_lookup_base (tree binfo, void *data_)
+{
+ struct lookup_base_data_s *data = data_;
- switch (bk)
+ if (SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), data->base))
+ {
+ if (!data->binfo)
{
- case bk_ambig:
- if (access != ba_any)
- return bk;
- found = bk;
- break;
+ data->binfo = binfo;
+ data->via_virtual
+ = binfo_via_virtual (data->binfo, data->t) != NULL_TREE;
+
+ if (!data->repeated_base)
+ /* If there are no repeated bases, we can stop now. */
+ return binfo;
- case bk_same_type:
- bk = bk_proper_base;
- /* Fall through. */
- case bk_proper_base:
- gcc_assert (found == bk_not_base);
- found = bk;
- break;
+ if (data->want_any && !data->via_virtual)
+ /* If this is a non-virtual base, then we can't do
+ better. */
+ return binfo;
- case bk_via_virtual:
- if (found != bk_ambig)
- found = bk;
- break;
+ return dfs_skip_bases;
+ }
+ else
+ {
+ gcc_assert (binfo != data->binfo);
- case bk_not_base:
- break;
+ /* We've found more than one matching binfo. */
+ if (!data->want_any)
+ {
+ /* This is immediately ambiguous. */
+ data->binfo = NULL_TREE;
+ data->ambiguous = true;
+ return error_mark_node;
+ }
+
+ /* Prefer one via a non-virtual path. */
+ if (!binfo_via_virtual (binfo, data->t))
+ {
+ data->binfo = binfo;
+ data->via_virtual = false;
+ return binfo;
+ }
- default:
- gcc_unreachable ();
+ /* There must be repeated bases, otherwise we'd have stopped
+ on the first base we found. */
+ return dfs_skip_bases;
}
}
- return found;
+
+ return NULL_TREE;
}
/* Returns true if type BASE is accessible in T. (BASE is known to be
@@ -202,8 +189,8 @@ accessible_base_p (tree t, tree base)
tree
lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
{
- tree binfo = NULL_TREE; /* The binfo we've found so far. */
- tree t_binfo = NULL_TREE;
+ tree binfo;
+ tree t_binfo;
base_kind bk;
if (t == error_mark_node || base == error_mark_node)
@@ -219,7 +206,7 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
t_binfo = t;
t = BINFO_TYPE (t);
}
- else
+ else
{
t = complete_type (TYPE_MAIN_VARIANT (t));
t_binfo = TYPE_BINFO (t);
@@ -228,9 +215,33 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
base = complete_type (TYPE_MAIN_VARIANT (base));
if (t_binfo)
- bk = lookup_base_r (t_binfo, base, access, 0, &binfo);
+ {
+ struct lookup_base_data_s data;
+
+ data.t = t;
+ data.base = base;
+ data.binfo = NULL_TREE;
+ data.ambiguous = data.via_virtual = false;
+ data.repeated_base = CLASSTYPE_REPEATED_BASE_P (t);
+ data.want_any = access == ba_any;
+
+ dfs_walk_once (t_binfo, dfs_lookup_base, NULL, &data);
+ binfo = data.binfo;
+
+ if (!binfo)
+ bk = data.ambiguous ? bk_ambig : bk_not_base;
+ else if (binfo == t_binfo)
+ bk = bk_same_type;
+ else if (data.via_virtual)
+ bk = bk_via_virtual;
+ else
+ bk = bk_proper_base;
+ }
else
- bk = bk_not_base;
+ {
+ binfo = NULL_TREE;
+ bk = bk_not_base;
+ }
/* Check that the base is unambiguous and accessible. */
if (access != ba_any)
@@ -240,7 +251,6 @@ lookup_base (tree t, tree base, base_access access, base_kind *kind_ptr)
break;
case bk_ambig:
- binfo = NULL_TREE;
if (!(access & ba_quiet))
{
error ("%qT is an ambiguous base of %qT", base, t);
@@ -2415,6 +2425,10 @@ binfo_from_vbase (tree binfo)
tree
binfo_via_virtual (tree binfo, tree limit)
{
+ if (limit && !CLASSTYPE_VBASECLASSES (limit))
+ /* LIMIT has no virtual bases, so BINFO cannot be via one. */
+ return NULL_TREE;
+
for (; binfo && !SAME_BINFO_TYPE_P (BINFO_TYPE (binfo), limit);
binfo = BINFO_INHERITANCE_CHAIN (binfo))
{
OpenPOWER on IntegriCloud