search.c (struct lookup_base_data_s): New.
authorNathan Sidwell <nathan@codesourcery.com>
Tue, 12 Oct 2004 14:23:39 +0000 (14:23 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Tue, 12 Oct 2004 14:23:39 +0000 (14:23 +0000)
* search.c (struct lookup_base_data_s): New.
(lookup_base_r): Replace with ...
(dfs_lookup_base): ... this.
(lookup_base): Use dfs_walk_all.

From-SVN: r88934

gcc/cp/ChangeLog
gcc/cp/search.c

index 688a0d3bfaa90b0483ee3cd2480435f4f568bb94..5b87487923defd7eb54c4a765a412df934a30545 100644 (file)
@@ -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.
index 9c3d23077f96e68a09972a9c13d0799d8179b536..9ab861f6aef45159c0f832bb2a394931ed376e97 100644 (file)
@@ -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 */
 
 \f
-/* 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))
     {