[C++ DR 2336] virtual dtors, exception specs & abstract classes
authorNathan Sidwell <nathan@acm.org>
Thu, 15 Nov 2018 15:51:39 +0000 (15:51 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 15 Nov 2018 15:51:39 +0000 (15:51 +0000)
https://gcc.gnu.org/ml/gcc-patches/2018-11/msg01389.html
DR 2336
* cp-tree.h (enum special_function_kind): Add sfk_virtual_destructor.
* method.c (type_has_trivial_fn): Add it.
(SFK_DTOR_P): Likewise.
(synthesized_method_base_walk): Don't check access of vbases of
abstract classes when sfk_virtual_destructor.
(synthesized_method_walk): Skip vbases of abstract classes except
when sfk_virtual_destructor.
(get_defaulted_eh_spec): Set sfk_virtual_destructor as needed.

* g++.dg/cpp1y/pr79393-3.C: New.

From-SVN: r266188

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp1y/pr79393-3.C [new file with mode: 0644]

index f8efe7de9c726dffd4522cb8b16fb2b4b236f8f8..d6ee781d730b0b6155cca9e9482cb3bb64960ac7 100644 (file)
@@ -1,5 +1,15 @@
 2018-11-15  Nathan Sidwell  <nathan@acm.org>
 
+       DR 2336
+       * cp-tree.h (enum special_function_kind): Add sfk_virtual_destructor.
+       * method.c (type_has_trivial_fn): Add it.
+       (SFK_DTOR_P): Likewise.
+       (synthesized_method_base_walk): Don't check access of vbases of
+       abstract classes when sfk_virtual_destructor.
+       (synthesized_method_walk): Skip vbases of abstract classes except
+       when sfk_virtual_destructor.
+       (get_defaulted_eh_spec): Set sfk_virtual_destructor as needed.
+
        * cp-tree.h (enum special_function_kind): Reorder and comment.
        * method.c (SFK_CTOR_P, SFK_DTOR_P, SFK_ASSIGN_P, SFK_COPY_P)
        (SFK_MOVE_P): New predicates.
index dbde05fb809a7031e3f587cf38d68705fd3041f4..f2e670920b57683fe41aa1394e61c0a1de5e9170 100644 (file)
@@ -5099,7 +5099,8 @@ enum special_function_kind {
                              deletes the object after it has been
                              destroyed.  */
   sfk_conversion,         /* A conversion operator.  */
-  sfk_deduction_guide     /* A class template deduction guide.  */
+  sfk_deduction_guide,    /* A class template deduction guide.  */
+  sfk_virtual_destructor   /* Used by member synthesis fns.  */
 };
 
 /* The various kinds of linkage.  From [basic.link],
index ebf14c52e099ac6822cfd93591d38798ec6209da..435ba1d7ed3ca438e77d34a9d4b74f6e529d0360 100644 (file)
@@ -402,6 +402,7 @@ type_has_trivial_fn (tree ctype, special_function_kind sfk)
     case sfk_move_assignment:
       return !TYPE_HAS_COMPLEX_MOVE_ASSIGN (ctype);
     case sfk_destructor:
+    case sfk_virtual_destructor:
       return !TYPE_HAS_NONTRIVIAL_DESTRUCTOR (ctype);
     case sfk_inheriting_constructor:
       return false;
@@ -1287,7 +1288,7 @@ process_subob_fn (tree fn, tree *spec_p, bool *trivial_p,
 #define SFK_CTOR_P(sfk) \
   ((sfk) >= sfk_constructor && (sfk) <= sfk_move_constructor)
 #define SFK_DTOR_P(sfk) \
-  ((sfk) == sfk_destructor)
+  ((sfk) == sfk_destructor || (sfk) == sfk_virtual_destructor)
 #define SFK_ASSIGN_P(sfk) \
   ((sfk) == sfk_copy_assignment || (sfk) == sfk_move_assignment)
 #define SFK_COPY_P(sfk) \
@@ -1481,12 +1482,11 @@ synthesized_method_base_walk (tree binfo, tree base_binfo,
       if (flag_new_inheriting_ctors)
        defer = dk_deferred;
     }
-  /* To be conservative, ignore access to the base dtor that
-     DR1658 instructs us to ignore.  See the comment in
-     synthesized_method_walk.  */
-  else if (cxx_dialect >= cxx14 && fnname == complete_dtor_identifier
+  else if (cxx_dialect >= cxx14 && sfk == sfk_virtual_destructor
           && BINFO_VIRTUAL_P (base_binfo)
           && ABSTRACT_CLASS_TYPE_P (BINFO_TYPE (binfo)))
+    /* Don't check access when looking at vbases of abstract class's
+       virtual destructor.  */
     defer = dk_no_check;
 
   if (defer != dk_no_deferred)
@@ -1572,7 +1572,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
   bool check_vdtor = false;
   tree fnname;
 
-if (SFK_DTOR_P (sfk))
+  if (SFK_DTOR_P (sfk))
     {
       check_vdtor = true;
       /* The synthesized method will call base dtors, but check complete
@@ -1696,12 +1696,11 @@ if (SFK_DTOR_P (sfk))
   else if (vec_safe_is_empty (vbases))
     /* No virtual bases to worry about.  */;
   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)
+          /* DR 1658 specifis that vbases of abstract classes are
+             ignored for both ctors and dtors.  Except DR 2338
+             overrides that skipping when determing the eh-spec of a
+             virtual destructor.  */
+          && sfk != sfk_virtual_destructor)
     /* Vbase cdtors are not relevant.  */;
   else
     {
@@ -1748,6 +1747,9 @@ get_defaulted_eh_spec (tree decl, tsubst_flags_t complain)
   tree spec = empty_except_spec;
   bool diag = !DECL_DELETED_FN (decl) && (complain & tf_error);
   tree inh = DECL_INHERITED_CTOR (decl);
+  if (SFK_DTOR_P (sfk) && DECL_VIRTUAL_P (decl))
+    /* We have to examine virtual bases even if abstract.  */
+    sfk = sfk_virtual_destructor;
   synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL,
                           NULL, diag, &inh, parms);
   return spec;
index 9eb2c3aae26d5ded552e6628e37c2a5d2de3293d..2842a7b2b89430e72bfc09e20e49343c64f9ba1d 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-15  Nathan Sidwell  <nathan@acm.org>
+
+       DR 2336
+       * g++.dg/cpp1y/pr79393-3.C: New.
+
 2018-11-15  David Malcolm  <dmalcolm@redhat.com>
 
        PR other/19165
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C b/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C
new file mode 100644 (file)
index 0000000..23dc265
--- /dev/null
@@ -0,0 +1,44 @@
+// pr c++/79393
+// { dg-do compile { target c++14 } }
+
+struct A 
+{
+  friend class C;
+private:
+  ~A () noexcept (false);
+};
+
+A::~A () noexcept(false) {}
+
+struct B : virtual A
+{
+  // non-virtual, abstract, ignores A
+  ~B ();
+  virtual void abs () = 0;
+};
+
+B::~B () {
+  throw 1; // { dg-warning "will always call terminate" }
+}
+
+struct C : virtual A
+{
+  // non-virtual, non-abstract, considers A
+  ~C ();
+  virtual void abs ();
+};
+
+C::~C () {
+  throw 1;
+}
+
+struct D : virtual A
+{
+  // virtual, abstract, considers A
+  virtual ~D ();
+  virtual void abs () = 0;
+};
+
+D::~D () {
+  throw 1;
+}