diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c2abaab0c86..d869b0d51ba 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,11 @@ +2001-12-04 Nathan Sidwell + + PR g++/164 + * init.c (sort_base_init): Allow binfos to be directly specified. + * method.c (do_build_copy_constructor): Explicitly convert to the + base instance. + (do_build_assign_ref): Likewise. + 2001-12-03 Hans-Peter Nilsson * decl.c (xref_basetypes): Don't use C99 construct in tag_code diff --git a/gcc/cp/init.c b/gcc/cp/init.c index b7b230d3ca2..169bc8c07a0 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -556,7 +556,8 @@ sort_base_init (t, base_init_list, rbase_ptr, vbase_ptr) for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x)) { tree basetype = TREE_PURPOSE (x); - tree binfo = binfo_or_else (basetype, t); + tree binfo = (TREE_CODE (basetype) == TREE_VEC + ? basetype : binfo_or_else (basetype, t)); if (binfo == NULL_TREE) /* BASETYPE might be an inaccessible direct base (because it diff --git a/gcc/cp/method.c b/gcc/cp/method.c index 4de7605984c..2424623a4b4 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -554,25 +554,31 @@ do_build_copy_constructor (fndecl) int cvquals = cp_type_quals (TREE_TYPE (parm)); int i; - /* Initialize all the base-classes with the parameter converted to - their type so that we get their copy constructor and not another - constructor that takes current_class_type. */ + /* Initialize all the base-classes with the parameter converted + to their type so that we get their copy constructor and not + another constructor that takes current_class_type. We must + deal with the binfo's directly as a direct base might be + inaccessible due to ambiguity. */ for (t = CLASSTYPE_VBASECLASSES (current_class_type); t; t = TREE_CHAIN (t)) { - tree type = BINFO_TYPE (TREE_VALUE (t)); - base_init_list = tree_cons (type, convert_lvalue (type, parm), + tree binfo = TREE_VALUE (t); + + base_init_list = tree_cons (binfo, + build_base_path (PLUS_EXPR, parm, + binfo, 1), base_init_list); } for (i = 0; i < n_bases; ++i) { - t = TREE_VEC_ELT (binfos, i); - if (TREE_VIA_VIRTUAL (t)) + tree binfo = TREE_VEC_ELT (binfos, i); + if (TREE_VIA_VIRTUAL (binfo)) continue; - t = BINFO_TYPE (t); - base_init_list = tree_cons (t, convert_lvalue (t, parm), + base_init_list = tree_cons (binfo, + build_base_path (PLUS_EXPR, parm, + binfo, 1), base_init_list); } @@ -645,11 +651,18 @@ do_build_assign_ref (fndecl) for (i = 0; i < n_bases; ++i) { - tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i)); - tree p = convert_lvalue (basetype, parm); - p = build_member_call (basetype, ansi_assopname (NOP_EXPR), - build_tree_list (NULL_TREE, p)); - finish_expr_stmt (p); + /* We must deal with the binfo's directly as a direct base + might be inaccessible due to ambiguity. */ + tree binfo = TREE_VEC_ELT (binfos, i); + tree src = build_base_path (PLUS_EXPR, parm, binfo, 1); + tree dst = build_base_path (PLUS_EXPR, current_class_ref, binfo, 1); + + tree expr = build_method_call (dst, + ansi_assopname (NOP_EXPR), + build_tree_list (NULL_TREE, src), + NULL, + LOOKUP_NORMAL | LOOKUP_NONVIRTUAL); + finish_expr_stmt (expr); } for (; fields; fields = TREE_CHAIN (fields)) { diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 76f673f6d0c..795c502821b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2001-12-04 Nathan Sidwell + + * g++.dg/inherit/base1.C: New test. + 2001-12-04 Jakub Jelinek * g++.dg/other/stdarg1.C: New test. diff --git a/gcc/testsuite/g++.dg/inherit/base1.C b/gcc/testsuite/g++.dg/inherit/base1.C new file mode 100644 index 00000000000..952c6d20f3b --- /dev/null +++ b/gcc/testsuite/g++.dg/inherit/base1.C @@ -0,0 +1,22 @@ +// { dg-do compile } +// { dg-options "-pedantic-errors -w" } + +// Copyright (C) 2000 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 29 Nov 2001 + +// PR 164 +// Although a direct base can be inaccessible due to ambiguity, that +// should not blow up synthesized methods. + +struct A {int m;}; +struct B : A {int m;}; +struct C : virtual A, B {int m;}; +struct D : B, C {int m;}; + +void foo2 () +{ + D d; + D e (d); + + e = d; +}