Commit 5cf447db by Nathan Sidwell Committed by Nathan Sidwell

re PR c++/16889 (ambiguity is not detected)

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
parent c5466b25
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> 2004-09-23 Zack Weinberg <zack@codesourcery.com>
* decl.c (grokfndecl): If ::main is found not to return int, * decl.c (grokfndecl): If ::main is found not to return int,
......
...@@ -57,8 +57,6 @@ static tree split_conversions (tree, tree, tree, tree); ...@@ -57,8 +57,6 @@ static tree split_conversions (tree, tree, tree, tree);
static int lookup_conversions_r (tree, int, int, static int lookup_conversions_r (tree, int, int,
tree, tree, tree, tree, tree *, tree *); tree, tree, tree, tree, tree *, tree *);
static int look_for_overrides_r (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 tree lookup_field_queue_p (tree, int, void *);
static int shared_member_p (tree); static int shared_member_p (tree);
static tree lookup_field_r (tree, void *); static tree lookup_field_r (tree, void *);
...@@ -991,7 +989,7 @@ lookup_field_queue_p (tree derived, int ix, void *data) ...@@ -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 /* If this base class is hidden by the best-known value so far, we
don't need to look. */ 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; return NULL_TREE;
/* If this is a dependent base, don't look in it. */ /* 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) ...@@ -1256,7 +1254,8 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type)
lfi.type = type; lfi.type = type;
lfi.name = name; lfi.name = name;
lfi.want_type = want_type; 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 = lfi.rval;
rval_binfo = lfi.rval_binfo; rval_binfo = lfi.rval_binfo;
if (rval_binfo) if (rval_binfo)
...@@ -1513,101 +1512,16 @@ adjust_result_of_qualified_name_lookup (tree decl, ...@@ -1513,101 +1512,16 @@ adjust_result_of_qualified_name_lookup (tree decl,
} }
/* Walk the class hierarchy dominated by TYPE. FN is called for each /* Walk the class hierarchy within BINFO, in a depth-first traversal.
type in the hierarchy, in a breadth-first preorder traversal. PREFN is called in preorder, while POSTFN is called in postorder.
If it ever returns a non-NULL value, that value is immediately If they ever returns a non-NULL value, that value is immediately
returned and the walk is terminated. At each node, FN is passed a returned and the walk is terminated. Both PREFN and POSTFN can be
BINFO indicating the path from the currently visited base-class to NULL. At each node, PREFN and POSTFN are passed the binfo to
TYPE. Before each base-class is walked QFN is called. If the examine. Before each base-binfo of BINFO is walked, QFN is called.
value returned is nonzero, the base-class is walked; otherwise it If the value returned is nonzero, the base-binfo is walked;
is not. If QFN is NULL, it is treated as a function which always otherwise it is not. If QFN is NULL, it is treated as a function
returns 1. Both FN and QFN are passed the DATA whenever they are which always returns 1. All callbacks are passed DATA whenever
called. 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. */
tree tree
dfs_walk_real (tree binfo, dfs_walk_real (tree binfo,
...@@ -1649,8 +1563,8 @@ dfs_walk_real (tree binfo, ...@@ -1649,8 +1563,8 @@ dfs_walk_real (tree binfo,
return rval; return rval;
} }
/* Exactly like bfs_walk, except that a depth-first post-order traversal is /* Exactly like dfs_walk_real, except that there is no pre-order
performed. */ function call and FN is called in post-order. */
tree tree
dfs_walk (tree binfo, dfs_walk (tree binfo,
......
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> 2004-09-24 Andrew Pinski <pinskia@physics.uc.edu>
PR tree-opt/17624 PR tree-opt/17624
......
// { 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" "" }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment