re PR c++/16889 (ambiguity is not detected)
authorNathan Sidwell <nathan@codesourcery.com>
Fri, 24 Sep 2004 14:04:58 +0000 (14:04 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 24 Sep 2004 14:04:58 +0000 (14:04 +0000)
cp:
PR c++/16889
* search.c (lookup_field_queue_p): Correct check for hidden base.

* search.c (bfs_walk): Remove.
(lookup_member): Use dfs_walk_real.
(dfs_walk_real): Move and adjust documentation from bfs_walk.
testsuite:
PR c++/16889
* g++.dg/lookup/ambig3.C: New.

From-SVN: r88037

gcc/cp/ChangeLog
gcc/cp/search.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/lookup/ambig3.C [new file with mode: 0644]

index 9ea3fe3e7bd731445a2a573747c4e5480b3e3543..80c2b79effc539cad3fd053e1246815967590f6c 100644 (file)
@@ -1,3 +1,12 @@
+2004-09-24  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/16889
+       * search.c (lookup_field_queue_p): Correct check for hidden base.
+
+       * search.c (bfs_walk): Remove.
+       (lookup_member): Use dfs_walk_real.
+       (dfs_walk_real): Move and adjust documentation from bfs_walk.
+
 2004-09-23  Zack Weinberg  <zack@codesourcery.com>
 
        * decl.c (grokfndecl): If ::main is found not to return int,
index 42adbec324ca78033dcefdf42fb5fcdcacc85a7a..67b891f85e3257a4e75af2e059528972db83d209 100644 (file)
@@ -57,8 +57,6 @@ static tree split_conversions (tree, tree, tree, tree);
 static int lookup_conversions_r (tree, int, int,
                                 tree, tree, tree, tree, tree *, tree *);
 static int look_for_overrides_r (tree, tree);
-static tree bfs_walk (tree, tree (*) (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 *);
@@ -991,7 +989,7 @@ lookup_field_queue_p (tree derived, int ix, void *data)
 
   /* If this base class is hidden by the best-known value so far, we
      don't need to look.  */
-  if (lfi->rval_binfo && original_binfo (binfo, lfi->rval_binfo))
+  if (lfi->rval_binfo && derived == lfi->rval_binfo)
     return NULL_TREE;
 
   /* If this is a dependent base, don't look in it.  */
@@ -1256,7 +1254,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
   lfi.type = type;
   lfi.name = name;
   lfi.want_type = want_type;
-  bfs_walk (basetype_path, &lookup_field_r, &lookup_field_queue_p, &lfi);
+  dfs_walk_real (basetype_path, &lookup_field_r, 0,
+                &lookup_field_queue_p, &lfi);
   rval = lfi.rval;
   rval_binfo = lfi.rval_binfo;
   if (rval_binfo)
@@ -1513,101 +1512,16 @@ adjust_result_of_qualified_name_lookup (tree decl,
 }
 
 \f
-/* Walk the class hierarchy dominated by TYPE.  FN is called for each
-   type in the hierarchy, in a breadth-first preorder traversal.
-   If it ever returns a non-NULL value, that value is immediately
-   returned and the walk is terminated.  At each node, FN is passed a
-   BINFO indicating the path from the currently visited base-class to
-   TYPE.  Before each base-class is walked QFN is called.  If the
-   value returned is nonzero, the base-class is walked; otherwise it
-   is not.  If QFN is NULL, it is treated as a function which always
-   returns 1.  Both FN and QFN are passed the DATA whenever they are
-   called.
-
-   Implementation notes: Uses a circular queue, which starts off on
-   the stack but gets moved to the malloc arena if it needs to be
-   enlarged.  The underflow and overflow conditions are
-   indistinguishable except by context: if head == tail and we just
-   moved the head pointer, the queue is empty, but if we just moved
-   the tail pointer, the queue is full.  
-   Start with enough room for ten concurrent base classes.  That
-   will be enough for most hierarchies.  */
-#define BFS_WALK_INITIAL_QUEUE_SIZE 10
-
-static tree
-bfs_walk (tree binfo,
-         tree (*fn) (tree, void *),
-         tree (*qfn) (tree, int, void *),
-         void *data)
-{
-  tree rval = NULL_TREE;
-
-  tree bases_initial[BFS_WALK_INITIAL_QUEUE_SIZE];
-  /* A circular queue of the base classes of BINFO.  These will be
-     built up in breadth-first order, except where QFN prunes the
-     search.  */
-  size_t head, tail;
-  size_t base_buffer_size = BFS_WALK_INITIAL_QUEUE_SIZE;
-  tree *base_buffer = bases_initial;
-
-  head = tail = 0;
-  base_buffer[tail++] = binfo;
-
-  while (head != tail)
-    {
-      int n_bases, ix;
-      tree binfo = base_buffer[head++];
-      if (head == base_buffer_size)
-       head = 0;
-
-      /* Is this the one we're looking for?  If so, we're done.  */
-      rval = fn (binfo, data);
-      if (rval)
-       goto done;
-
-      n_bases = BINFO_N_BASE_BINFOS (binfo);
-      for (ix = 0; ix != n_bases; ix++)
-       {
-         tree base_binfo;
-         
-         if (qfn)
-           base_binfo = (*qfn) (binfo, ix, data);
-         else
-           base_binfo = BINFO_BASE_BINFO (binfo, ix);
-         
-         if (base_binfo)
-           {
-             base_buffer[tail++] = base_binfo;
-             if (tail == base_buffer_size)
-               tail = 0;
-             if (tail == head)
-               {
-                 tree *new_buffer = xmalloc (2 * base_buffer_size
-                                             * sizeof (tree));
-                 memcpy (&new_buffer[0], &base_buffer[0],
-                         tail * sizeof (tree));
-                 memcpy (&new_buffer[head + base_buffer_size],
-                         &base_buffer[head],
-                         (base_buffer_size - head) * sizeof (tree));
-                 if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
-                   free (base_buffer);
-                 base_buffer = new_buffer;
-                 head += base_buffer_size;
-                 base_buffer_size *= 2;
-               }
-           }
-       }
-    }
-
- done:
-  if (base_buffer_size != BFS_WALK_INITIAL_QUEUE_SIZE)
-    free (base_buffer);
-  return rval;
-}
-
-/* Exactly like bfs_walk, except that a depth-first traversal is
-   performed, and PREFN is called in preorder, while POSTFN is called
-   in postorder.  */
+/* Walk the class hierarchy within BINFO, in a depth-first traversal.
+   PREFN is called in preorder, while POSTFN is called in postorder.
+   If they ever returns a non-NULL value, that value is immediately
+   returned and the walk is terminated.  Both PREFN and POSTFN can be
+   NULL.  At each node, PREFN and POSTFN are passed the binfo to
+   examine.  Before each base-binfo of BINFO is walked, QFN is called.
+   If the value returned is nonzero, the base-binfo is walked;
+   otherwise it is not.  If QFN is NULL, it is treated as a function
+   which always returns 1.  All callbacks are passed DATA whenever
+   they are called.  */
 
 tree
 dfs_walk_real (tree binfo,
@@ -1649,8 +1563,8 @@ dfs_walk_real (tree binfo,
   return rval;
 }
 
-/* Exactly like bfs_walk, except that a depth-first post-order traversal is
-   performed.  */
+/* Exactly like dfs_walk_real, except that there is no pre-order
+   function call and  FN is called in post-order.  */
 
 tree
 dfs_walk (tree binfo,
index 8b4d071659896172173cda201f43c52f1942b283..e543df5d392163058e8ee5f3d424d2d5ef02708d 100644 (file)
@@ -1,3 +1,8 @@
+2004-08-24  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/16889
+       * g++.dg/lookup/ambig3.C: New.
+
 2004-09-24  Andrew Pinski  <pinskia@physics.uc.edu>
 
        PR tree-opt/17624
diff --git a/gcc/testsuite/g++.dg/lookup/ambig3.C b/gcc/testsuite/g++.dg/lookup/ambig3.C
new file mode 100644 (file)
index 0000000..7a0a837
--- /dev/null
@@ -0,0 +1,18 @@
+// { dg-do compile }
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 23 Sep 2004 <nathan@codesourcery.com>
+// Origin: Wolfgang Bangerth  <bangerth@dealii.org>
+
+// Follow on from Bug 16889:Undetected ambiguity.
+
+struct B { 
+  int f(); // { dg-error "int B::f" "" }
+}; 
+struct B1 : virtual B {}; 
+struct B2 : B {};
+struct B2_2 : B2 {};
+struct BB : B1, B2_2 {}; 
+int i = BB().f();  // { dg-error "ambiguous" "" }