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.
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;
#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) \
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)
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
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
{
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;
--- /dev/null
+// 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;
+}