From 2bd652d265f8158e9deed8715e5d1972bf8cd7c4 Mon Sep 17 00:00:00 2001 From: Nathan Sidwell Date: Thu, 15 Nov 2018 15:51:39 +0000 Subject: [PATCH] [C++ DR 2336] virtual dtors, exception specs & abstract classes 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 | 10 ++++++ gcc/cp/cp-tree.h | 3 +- gcc/cp/method.c | 26 ++++++++------- gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/g++.dg/cpp1y/pr79393-3.C | 44 ++++++++++++++++++++++++++ 5 files changed, 75 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/pr79393-3.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index f8efe7de9c7..d6ee781d730 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 2018-11-15 Nathan Sidwell + 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. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index dbde05fb809..f2e670920b5 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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], diff --git a/gcc/cp/method.c b/gcc/cp/method.c index ebf14c52e09..435ba1d7ed3 100644 --- a/gcc/cp/method.c +++ b/gcc/cp/method.c @@ -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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 9eb2c3aae26..2842a7b2b89 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2018-11-15 Nathan Sidwell + + DR 2336 + * g++.dg/cpp1y/pr79393-3.C: New. + 2018-11-15 David Malcolm 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 index 00000000000..23dc2650900 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/pr79393-3.C @@ -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; +} -- 2.30.2