aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2020-06-03 23:50:06 -0400
committerJason Merrill <jason@redhat.com>2020-06-04 15:11:42 -0400
commit0ddb93ce77374004c49cdfbd748ba35867620cf1 (patch)
treee72f9c9d166a469f442772331639a2fbf04ee818 /gcc/cp/class.c
parent8c727bdf4acf28c8315b119a1c8f6d6af745c2af (diff)
downloadgcc-0ddb93ce77374004c49cdfbd748ba35867620cf1.zip
gcc-0ddb93ce77374004c49cdfbd748ba35867620cf1.tar.gz
gcc-0ddb93ce77374004c49cdfbd748ba35867620cf1.tar.bz2
c++: Fix FE devirt with diamond inheritance [PR95158]
This started breaking in GCC 8 because of the fix for PR15272; after that change, we (correctly) remember the lookup from template parsing time that found Base::foo through the non-dependent MiddleB base, and so we overlook the overrider in MiddleA. But given that, the devirtualization condition from the fix for PR59031 is insufficient; we know that d has to be a Derived, and we found Base::foo in Base, but forcing a non-virtual call gets the wrong function. Fixed by removing the PR59031 code that the PR67184 patch moved to build_over_call, and instead looking up the overrider in BINFO_VIRTUALS. gcc/cp/ChangeLog: PR c++/95158 * class.c (lookup_vfn_in_binfo): New. * call.c (build_over_call): Use it. * cp-tree.h (resolves_to_fixed_type_p): Add default argument. (lookup_vfn_in_binfo): Declare. gcc/testsuite/ChangeLog: PR c++/95158 * g++.dg/template/virtual5.C: New test.
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r--gcc/cp/class.c14
1 files changed, 14 insertions, 0 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 757e010..f8e38ec 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2445,6 +2445,20 @@ get_vcall_index (tree fn, tree type)
gcc_unreachable ();
}
+/* Given a DECL_VINDEX of a virtual function found in BINFO, return the final
+ overrider at that index in the vtable. This should only be used when we
+ know that BINFO is correct for the dynamic type of the object. */
+
+tree
+lookup_vfn_in_binfo (tree idx, tree binfo)
+{
+ int ix = tree_to_shwi (idx);
+ if (TARGET_VTABLE_USES_DESCRIPTORS)
+ ix /= MAX (TARGET_VTABLE_USES_DESCRIPTORS, 1);
+ tree virtuals = BINFO_VIRTUALS (binfo);
+ return TREE_VALUE (chain_index (ix, virtuals));
+}
+
/* Update an entry in the vtable for BINFO, which is in the hierarchy
dominated by T. FN is the old function; VIRTUALS points to the
corresponding position in the new BINFO_VIRTUALS list. IX is the index