https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94325
--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> --- sizeof (MD) == sizeof (void *), so the clearing of the vptr in DD::~DD() when DE::~DE() is invoked later on looks wrong. But, without -fsanitize=vptr this isn't done. I've added that guard in PR87095, see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87095#c3 for more details. So, either we can just do what build_clobber_this does, which would be just: --- gcc/cp/decl.c 2020-03-27 09:59:26.407083563 +0100 +++ gcc/cp/decl.c 2020-04-06 13:14:15.814200485 +0200 @@ -16662,10 +16662,7 @@ begin_destructor_body (void) /* If the vptr is shared with some virtual nearly empty base, don't clear it if not in charge, the dtor of the virtual nearly empty base will do that later. */ - if (CLASSTYPE_VBASECLASSES (current_class_type) - && CLASSTYPE_PRIMARY_BINFO (current_class_type) - && BINFO_VIRTUAL_P - (CLASSTYPE_PRIMARY_BINFO (current_class_type))) + if (CLASSTYPE_VBASECLASSES (current_class_type)) { stmt = convert_to_void (stmt, ICV_STATEMENT, tf_warning_or_error); or try to narrow down the condition to cover this problematic case too, though I'm afraid I have no idea what that would be. Nathan/Jason, can I ask for help here? A wild shot in the dark could be: --- gcc/cp/decl.c.jj 2020-03-27 09:59:26.407083563 +0100 +++ gcc/cp/decl.c 2020-04-06 13:25:03.321511554 +0200 @@ -16662,14 +16662,20 @@ begin_destructor_body (void) /* If the vptr is shared with some virtual nearly empty base, don't clear it if not in charge, the dtor of the virtual nearly empty base will do that later. */ - if (CLASSTYPE_VBASECLASSES (current_class_type) - && CLASSTYPE_PRIMARY_BINFO (current_class_type) - && BINFO_VIRTUAL_P - (CLASSTYPE_PRIMARY_BINFO (current_class_type))) + if (CLASSTYPE_VBASECLASSES (current_class_type)) { - stmt = convert_to_void (stmt, ICV_STATEMENT, - tf_warning_or_error); - stmt = build_if_in_charge (stmt); + tree c = current_class_type; + while (CLASSTYPE_PRIMARY_BINFO (c)) + { + if (BINFO_VIRTUAL_P (CLASSTYPE_PRIMARY_BINFO (c))) + { + stmt = convert_to_void (stmt, ICV_STATEMENT, + tf_warning_or_error); + stmt = build_if_in_charge (stmt); + break; + } + c = BINFO_TYPE (CLASSTYPE_PRIMARY_BINFO (c)); + } } finish_decl_cleanup (NULL_TREE, stmt); } just from the fact that the existing code seemed to DTRT for D::~D() where CLASSTYPE_VBASECLASSES is non-NULL, CLASSTYPE_PRIMARY_BINFO too and BINFO_VIRTUAL_P on that is set as well. But in DD::~DD() the last condition doesn't hold, but BINFO_TYPE of the CLASSTYPE_PRIMARY_BINFO is D which has this property.