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.

Reply via email to