diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f02f7fa8ced..deaa83f5a5b 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2001-06-14 Jason Merrill + + * class.c (dfs_find_final_overrider): Fix logic. + + * class.c (update_vtable_entry_for_fn): Uncomment optimization to use + virtual thunk instead of non-virtual. + (get_matching_virtual): Uncomment. + + * pt.c (unify): Don't recurse between the POINTER_TYPE and the + OFFSET_TYPE. If we're adding cv-quals, the extra ones would be on + PARM, not ARG. + 2001-06-14 Nathan Sidwell * class.c (dfs_accumulate_vtbl_inits): For case 2 & 3, make sure diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 1fbf8d04e68..2ff9d14a9f1 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -2567,32 +2567,44 @@ dfs_find_final_overrider (binfo, data) ffod->overriding_fn = method; ffod->overriding_base = TREE_VALUE (path); } - /* If we found the same overrider we already have, then - we just need to check that we're finding it in the same - place. */ - else if (ffod->overriding_fn == method) + else if (ffod->overriding_fn) { - if (ffod->overriding_base - && (!tree_int_cst_equal + /* We had a best overrider; let's see how this compares. */ + + if (ffod->overriding_fn == method + && (tree_int_cst_equal (BINFO_OFFSET (TREE_VALUE (path)), BINFO_OFFSET (ffod->overriding_base)))) + /* We found the same overrider we already have, and in the + same place; it's still the best. */; + else if (strictly_overrides (ffod->overriding_fn, method)) + /* The old function overrides this function; it's still the + best. */; + else if (strictly_overrides (method, ffod->overriding_fn)) { + /* The new function overrides the old; it's now the + best. */ + ffod->overriding_fn = method; + ffod->overriding_base = TREE_VALUE (path); + } + else + { + /* Ambiguous. */ ffod->candidates = build_tree_list (NULL_TREE, ffod->overriding_fn); + if (method != ffod->overriding_fn) + ffod->candidates + = tree_cons (NULL_TREE, method, ffod->candidates); ffod->overriding_fn = NULL_TREE; ffod->overriding_base = NULL_TREE; } } - /* If there was already an overrider, and it overrides this - function, then the old overrider is still the best - candidate. */ - else if (ffod->overriding_fn - && strictly_overrides (ffod->overriding_fn, - method)) - ; else { + /* We had a list of ambiguous overrides; let's see how this + new one compares. */ + tree candidates; bool incomparable = false; @@ -2692,7 +2704,6 @@ find_final_overrider (t, binfo, fn) return build_tree_list (ffod.overriding_fn, ffod.overriding_base); } -#if 0 /* Returns the function from the BINFO_VIRTUALS entry in T which matches the signature of FUNCTION_DECL FN, or NULL_TREE if none. In other words, the function that the slot in T's primary vtable points to. */ @@ -2709,7 +2720,6 @@ get_matching_virtual (t, fn) return BV_FN (f); return NULL_TREE; } -#endif /* Update an entry in the vtable for BINFO, which is in the hierarchy dominated by T. FN has been overriden in BINFO; VIRTUALS points to the @@ -2784,10 +2794,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) delta = size_diffop (BINFO_OFFSET (TREE_VALUE (overrider)), BINFO_OFFSET (binfo)); -#if 0 - /* Disable this optimization pending an ABI change, or until - we can force emission of the non-virtual thunk even if we don't - use it. */ if (! integer_zerop (delta)) { /* We'll need a thunk. But if we have a (perhaps formerly) @@ -2810,7 +2816,6 @@ update_vtable_entry_for_fn (t, binfo, fn, virtuals) } } } -#endif } modify_vtable_entry (t, diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 1c9e6593a30..d9fa17fe164 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -8504,7 +8504,7 @@ unify (tparms, targs, parm, arg, strict) return 1; if (!(strict & UNIFY_ALLOW_OUTER_LEVEL) - && TYPE_P (arg) && !CP_TYPE_CONST_P (arg)) + && TYPE_P (parm) && !CP_TYPE_CONST_P (parm)) strict &= ~UNIFY_ALLOW_MORE_CV_QUAL; strict &= ~UNIFY_ALLOW_OUTER_LEVEL; strict &= ~UNIFY_ALLOW_DERIVED; @@ -8712,6 +8712,18 @@ unify (tparms, targs, parm, arg, strict) level of pointers. */ strict |= (strict_in & UNIFY_ALLOW_DERIVED); + if (TREE_CODE (TREE_TYPE (parm)) == OFFSET_TYPE + && TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) + { + /* Avoid getting confused about cv-quals; don't recurse here. + Pointers to members should really be just OFFSET_TYPE, not + this two-level nonsense... */ + + parm = TREE_TYPE (parm); + arg = TREE_TYPE (arg); + goto offset; + } + return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE (arg), strict); } @@ -8864,6 +8876,7 @@ unify (tparms, targs, parm, arg, strict) DEDUCE_EXACT, 0, -1); case OFFSET_TYPE: + offset: if (TREE_CODE (arg) != OFFSET_TYPE) return 1; if (unify (tparms, targs, TYPE_OFFSET_BASETYPE (parm), diff --git a/gcc/testsuite/g++.old-deja/g++.other/override2.C b/gcc/testsuite/g++.old-deja/g++.other/override2.C new file mode 100644 index 00000000000..6466b7d76ef --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.other/override2.C @@ -0,0 +1,9 @@ +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Jason Merrill 14 Jun 2001 + +// Test for diagnosis of missing final overrider. + +struct A { virtual void f (); }; +struct B1: virtual A { virtual void f (); }; +struct B2: virtual A { virtual void f (); }; +struct C: public B1, public B2 {}; // ERROR - no final overrider diff --git a/gcc/testsuite/g++.old-deja/g++.pt/deduct7.C b/gcc/testsuite/g++.old-deja/g++.pt/deduct7.C new file mode 100644 index 00000000000..ec51d30878d --- /dev/null +++ b/gcc/testsuite/g++.old-deja/g++.pt/deduct7.C @@ -0,0 +1,14 @@ +// Copyright (C) 2001 Free Software Foundation, Inc. +// Contributed by Jason Merrill 14 Jun 2001 + +// Test that deduction can add cv-quals to a pointer-to-member type. + +struct A; +int A::* pi; + +template void f (const T A::*) {} + +int main () +{ + f (pi); +} diff --git a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C index 4e2f392b64b..afe57d1cd14 100644 --- a/gcc/testsuite/g++.old-deja/g++.pt/unify8.C +++ b/gcc/testsuite/g++.old-deja/g++.pt/unify8.C @@ -9,10 +9,12 @@ template void Foo (T const **); +template void Bar (T const * const *); void Foo (int); // ERROR - candidate void Foo (float); // ERROR - candidate void baz (int **p1) { Foo (p1); // ERROR - no such function + Bar (p1); // OK }