This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Fix bug 69 - non-ambiguous lookup
- To: gcc-patches at gcc dot gnu dot org
- Subject: [C++ PATCH] Fix bug 69 - non-ambiguous lookup
- From: Nathan Sidwell <nathan at codesourcery dot com>
- Date: Mon, 26 Jun 2000 14:21:56 +0100
- Organization: Codesourcery LLC
hi,
I've installed the attached patch and testcase for bug 69.
The implementation of the hiding algorithm was broken for
non-virtual bases of a virtual base.
Approved by Mark, built & tested on i686-pc-linux-gnu
nathan
--
Dr Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
'But that's a lie.' - 'Yes it is. What's your point?'
nathan@codesourcery.com : http://www.cs.bris.ac.uk/~nathan/ : nathan@acm.org
2000-06-24 Nathan Sidwell <nathan@codesourcery.com>
* search.c (hides): Remove.
(is_subobject_of_p): Add most_derived parameter. Use
CANONICAL_BINFO.
(lookup_field_queue_p): Adjust.
(lookup_field_r): Adjust.
Index: cp/search.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/search.c,v
retrieving revision 1.183
diff -c -3 -p -r1.183 search.c
*** search.c 2000/06/23 01:14:40 1.183
--- search.c 2000/06/24 08:44:36
*************** static tree next_baselink PARAMS ((tree)
*** 89,96 ****
static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
static tree lookup_field_1 PARAMS ((tree, tree));
static int lookup_fnfields_here PARAMS ((tree, tree));
! static int is_subobject_of_p PARAMS ((tree, tree));
! static int hides PARAMS ((tree, tree));
static tree virtual_context PARAMS ((tree, tree, tree));
static tree dfs_check_overlap PARAMS ((tree, void *));
static tree dfs_no_overlap_yet PARAMS ((tree, void *));
--- 89,95 ----
static tree get_vbase_1 PARAMS ((tree, tree, unsigned int *));
static tree lookup_field_1 PARAMS ((tree, tree));
static int lookup_fnfields_here PARAMS ((tree, tree));
! static int is_subobject_of_p PARAMS ((tree, tree, tree));
static tree virtual_context PARAMS ((tree, tree, tree));
static tree dfs_check_overlap PARAMS ((tree, void *));
static tree dfs_no_overlap_yet PARAMS ((tree, void *));
*************** accessible_p (type, decl)
*** 1223,1252 ****
/* Routine to see if the sub-object denoted by the binfo PARENT can be
found as a base class and sub-object of the object denoted by
! BINFO. This routine relies upon binfos not being shared, except
! for binfos for virtual bases. */
static int
! is_subobject_of_p (parent, binfo)
! tree parent, binfo;
{
tree binfos;
int i, n_baselinks;
- /* We want to canonicalize for comparison purposes. But, when we
- iterate through basetypes later, we want the binfos from the
- original hierarchy. That's why we have to calculate BINFOS
- first, and then canonicalize. */
- binfos = BINFO_BASETYPES (binfo);
- parent = canonical_binfo (parent);
- binfo = canonical_binfo (binfo);
-
if (parent == binfo)
return 1;
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
! /* Process and/or queue base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
--- 1222,1244 ----
/* Routine to see if the sub-object denoted by the binfo PARENT can be
found as a base class and sub-object of the object denoted by
! BINFO. MOST_DERIVED is the most derived type of the hierarchy being
! searched. */
static int
! is_subobject_of_p (parent, binfo, most_derived)
! tree parent, binfo, most_derived;
{
tree binfos;
int i, n_baselinks;
if (parent == binfo)
return 1;
+ binfos = BINFO_BASETYPES (binfo);
n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
! /* Iterate the base types. */
for (i = 0; i < n_baselinks; i++)
{
tree base_binfo = TREE_VEC_ELT (binfos, i);
*************** is_subobject_of_p (parent, binfo)
*** 1255,1285 ****
class there's no way to descend into it. */
continue;
! if (is_subobject_of_p (parent, base_binfo))
return 1;
}
return 0;
}
- /* See if a one FIELD_DECL hides another. This routine is meant to
- correspond to ANSI working paper Sept 17, 1992 10p4. The two
- binfos given are the binfos corresponding to the particular places
- the FIELD_DECLs are found. This routine relies upon binfos not
- being shared, except for virtual bases. */
-
- static int
- hides (hider_binfo, hidee_binfo)
- tree hider_binfo, hidee_binfo;
- {
- /* hider hides hidee, if hider has hidee as a base class and
- the instance of hidee is a sub-object of hider. The first
- part is always true is the second part is true.
-
- When hider and hidee are the same (two ways to get to the exact
- same member) we consider either one as hiding the other. */
- return is_subobject_of_p (hidee_binfo, hider_binfo);
- }
-
/* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */
--- 1247,1260 ----
class there's no way to descend into it. */
continue;
! if (is_subobject_of_p (parent,
! CANONICAL_BINFO (base_binfo, most_derived),
! most_derived))
return 1;
}
return 0;
}
/* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */
*************** lookup_field_queue_p (binfo, data)
*** 1344,1350 ****
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
if (!lfi->from_dep_base_p && lfi->rval_binfo
! && hides (lfi->rval_binfo, binfo))
return NULL_TREE;
return CANONICAL_BINFO (binfo, lfi->type);
--- 1319,1325 ----
/* If this base class is hidden by the best-known value so far, we
don't need to look. */
if (!lfi->from_dep_base_p && lfi->rval_binfo
! && is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
return NULL_TREE;
return CANONICAL_BINFO (binfo, lfi->type);
*************** lookup_field_r (binfo, data)
*** 1448,1459 ****
/* If the lookup already found a match, and the new value doesn't
hide the old one, we might have an ambiguity. */
! if (lfi->rval_binfo && !hides (binfo, lfi->rval_binfo))
{
if (nval == lfi->rval && SHARED_MEMBER_P (nval))
/* The two things are really the same. */
;
! else if (hides (lfi->rval_binfo, binfo))
/* The previous value hides the new one. */
;
else
--- 1423,1434 ----
/* If the lookup already found a match, and the new value doesn't
hide the old one, we might have an ambiguity. */
! if (lfi->rval_binfo && !is_subobject_of_p (lfi->rval_binfo, binfo, lfi->type))
{
if (nval == lfi->rval && SHARED_MEMBER_P (nval))
/* The two things are really the same. */
;
! else if (is_subobject_of_p (binfo, lfi->rval_binfo, lfi->type))
/* The previous value hides the new one. */
;
else
Index: testsuite/ChangeLog
===================================================================
RCS file: /cvs/gcc/egcs/gcc/testsuite/ChangeLog,v
retrieving revision 1.537
diff -c -3 -p -r1.537 ChangeLog
*** ChangeLog 2000/06/26 11:07:19 1.537
--- ChangeLog 2000/06/26 13:14:33
***************
*** 1,5 ****
--- 1,9 ----
2000-06-26 Nathan Sidwell <nathan@codesourcery.com>
+ * g++.old-deja/g++.other/ambig3.C: New test.
+
+ 2000-06-26 Nathan Sidwell <nathan@codesourcery.com>
+
* g++.old-deja/g++.pt/syntax1.C: New test.
* g++.old-deja/g++.pt/syntax2.C: New test.
* g++.old-deja/g++.other/syntax3.C: New test.
Index: testsuite/g++.old-deja/g++.other/ambig3.C
===================================================================
RCS file: ambig3.C
diff -N ambig3.C
*** /dev/null Tue May 5 13:32:27 1998
--- ambig3.C Mon Jun 26 06:14:33 2000
***************
*** 0 ****
--- 1,34 ----
+ // Build don't link:
+
+ // Copyright (C) 2000 Free Software Foundation, Inc.
+ // Contributed by Nathan Sidwell 23 June 2000 <nathan@codesourcery.com>
+
+ // Origin GNATS bug report 69 from Glenn Ammons <ammons@cs.wisc.edu>
+ //
+ // A base which derives a virtual base hides declarations in the virtual base,
+ // even if that virtual base is accessible via another path [10.2]/6. Make
+ // sure that non-virtual bases of the virtual base are also hidden, not matter
+ // what order bases are declared in.
+
+ struct A {int a;};
+ struct B : A {};
+
+ struct L1 : virtual B { int a; };
+ struct L2 : virtual A { int a; };
+
+ struct R1 : virtual B {};
+ struct R2 : virtual A {};
+
+ struct C1 : R1, L1 {};
+ struct C2 : R2, L2 {};
+
+ struct D1 : L1, R1 {};
+ struct D2 : L2, R2 {};
+
+ void fn (C1 *c1, D1 *d1, C2 *c2, D2 *d2)
+ {
+ c1->a = 1;
+ d1->a = 1;
+ c2->a = 1;
+ d2->a = 1;
+ }