From: Nathan Sidwell Date: Fri, 24 Sep 2004 14:04:58 +0000 (+0000) Subject: re PR c++/16889 (ambiguity is not detected) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5cf447dbf18327c71263f9afff56905d2a86dc0d;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9ea3fe3e7bd..80c2b79effc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,12 @@ +2004-09-24 Nathan Sidwell + + 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 * decl.c (grokfndecl): If ::main is found not to return int, diff --git a/gcc/cp/search.c b/gcc/cp/search.c index 42adbec324c..67b891f85e3 100644 --- a/gcc/cp/search.c +++ b/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, diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 8b4d0716598..e543df5d392 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-08-24 Nathan Sidwell + + PR c++/16889 + * g++.dg/lookup/ambig3.C: New. + 2004-09-24 Andrew Pinski 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 index 00000000000..7a0a8377a91 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/ambig3.C @@ -0,0 +1,18 @@ +// { dg-do compile } + +// Copyright (C) 2004 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 23 Sep 2004 +// Origin: Wolfgang Bangerth + +// 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" "" }