mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-26 16:51:01 +08:00
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
This commit is contained in:
parent
c5466b25b4
commit
5cf447dbf1
@ -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,
|
||||
|
116
gcc/cp/search.c
116
gcc/cp/search.c
@ -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,
|
||||
}
|
||||
|
||||
|
||||
/* 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,
|
||||
|
@ -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
|
||||
|
18
gcc/testsuite/g++.dg/lookup/ambig3.C
Normal file
18
gcc/testsuite/g++.dg/lookup/ambig3.C
Normal file
@ -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" "" }
|
Loading…
x
Reference in New Issue
Block a user