diff mbox

[C++] 79393 fix

Message ID 9e5a5397-5cd4-7ac7-c38e-34d41ea864bd@acm.org
State New
Headers show

Commit Message

Nathan Sidwell March 13, 2017, 12:06 p.m. UTC
The resolution to DR 1658 causes vbases of abstract classes to be 
ignored when building the cdtors.  That made sense for ctors, when there 
might be no default ctor available.  But for dtors, there is only oe 
dtor and they can be virtual.  That can break virtual overriding, as 
79393 discovered.

I've reported this as a DR, but so GCC 7 doesn't break currently working 
code, I've committed this patch to skip that part of 1658's resolution.

The inhibiting of access checks was needed of pr66443-cxx14-3.C to 
continue passing.  That's a case where the vbase's dtor is inaccessible 
from the abstract base.  That seemed like the most conservative way to 
inhibit 1658's impact by allowing the most code to be compiled, but of 
course is speculative.

nathan

Comments

Jason Merrill March 13, 2017, 9:05 p.m. UTC | #1
On Mon, Mar 13, 2017 at 8:06 AM, Nathan Sidwell <nathan@acm.org> wrote:
> The resolution to DR 1658 causes vbases of abstract classes to be ignored
> when building the cdtors.  That made sense for ctors, when there might be no
> default ctor available.  But for dtors, there is only oe dtor and they can
> be virtual.  That can break virtual overriding, as 79393 discovered.
>
> I've reported this as a DR, but so GCC 7 doesn't break currently working
> code, I've committed this patch to skip that part of 1658's resolution.
>
> The inhibiting of access checks was needed of pr66443-cxx14-3.C to continue
> passing.  That's a case where the vbase's dtor is inaccessible from the
> abstract base.  That seemed like the most conservative way to inhibit 1658's
> impact by allowing the most code to be compiled, but of course is
> speculative.

It looks like you're ignoring the access for all base destructors;
handling this in synthesized_method_base_walk would let you limit the
change to vbases with virtual destructors.  That function also already
handles ignoring access control for an inherited constructor.

Jason
Nathan Sidwell March 13, 2017, 10:20 p.m. UTC | #2
On 03/13/2017 05:05 PM, Jason Merrill wrote:

> It looks like you're ignoring the access for all base destructors;
> handling this in synthesized_method_base_walk would let you limit the
> change to vbases with virtual destructors.  That function also already
> handles ignoring access control for an inherited constructor.

d'oh! you're right.  I was in two minds about ignoring access at all -- and 
xfailing that testcase for the moment.  That would avoid an unfortunate possible 
future where the DR resolves to revert to the pre DR 1658 behaviour for dtors. 
thoughts?

nathan
diff mbox

Patch

2017-03-13  Nathan Sidwell  <nathan@acm.org>

	PR c++/79393 DR 1658 workaround
	* method.c (synthesized_method_walk): Check vbases of abstract
	classes for dtor walk.

Index: cp/method.c
===================================================================
--- cp/method.c	(revision 246084)
+++ cp/method.c	(working copy)
@@ -1664,12 +1664,26 @@  synthesized_method_walk (tree ctype, spe
     /* Already examined vbases above.  */;
   else if (vec_safe_is_empty (vbases))
     /* No virtual bases to worry about.  */;
-  else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14)
+  else if (ABSTRACT_CLASS_TYPE_P (ctype) && cxx_dialect >= cxx14
+	   /* DR 1658 specifies that vbases of abstract classes are
+	      ignored for both ctors and dtors.  However, that breaks
+	      virtual dtor overriding when the ignored base has a
+	      throwing destructor.  So, ignore that piece of 1658.  A
+	      defect has been filed (no number yet).  */
+	   && sfk != sfk_destructor)
     /* Vbase cdtors are not relevant.  */;
   else
     {
       if (constexpr_p)
 	*constexpr_p = false;
+
+      /* To be conservative, ignore access to the base dtor that
+	 DR1658 instructs us to ignore.  */
+      bool no_access_check = (cxx_dialect >= cxx14
+			      && ABSTRACT_CLASS_TYPE_P (ctype));
+
+      if (no_access_check)
+	push_deferring_access_checks (dk_no_check);
       FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
 	synthesized_method_base_walk (binfo, base_binfo, quals,
 				      copy_arg_p, move_p, ctor_p,
@@ -1677,6 +1691,8 @@  synthesized_method_walk (tree ctype, spe
 				      fnname, flags, diag,
 				      spec_p, trivial_p,
 				      deleted_p, constexpr_p);
+      if (no_access_check)
+	pop_deferring_access_checks ();
     }
 
   /* Now handle the non-static data members.  */
Index: testsuite/g++.dg/cpp1y/pr79393.C
===================================================================
--- testsuite/g++.dg/cpp1y/pr79393.C	(revision 0)
+++ testsuite/g++.dg/cpp1y/pr79393.C	(working copy)
@@ -0,0 +1,21 @@ 
+// { dg-do compile { target c++14 } }
+// PR c++/79393 deduced eh spec, deleted dtors and vbases
+
+struct A3;
+
+struct VDT {
+  virtual ~VDT () noexcept (false);
+};
+
+struct A1 : virtual VDT {
+  virtual void abstract () = 0;
+};
+
+struct A2 : A1 {  };
+
+struct A3 : A2 
+{
+  virtual void abstract ();
+};
+
+A3 a3;