From 32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Wed, 5 Jan 2022 19:39:48 -0500 Subject: [PATCH] c++: when delegating constructor throws [PR103711] We were always calling the complete destructor if the target constructor throws, even if we were calling the base constructor. PR c++/103711 gcc/cp/ChangeLog: * init.c (perform_target_ctor): Select destructor by in_chrg. gcc/testsuite/ChangeLog: * g++.dg/eh/delegating1.C: New test. --- gcc/cp/init.c | 10 ++++++++++ gcc/testsuite/g++.dg/eh/delegating1.C | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) create mode 100644 gcc/testsuite/g++.dg/eh/delegating1.C diff --git a/gcc/cp/init.c b/gcc/cp/init.c index bfe4ad4..c932699 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -545,6 +545,16 @@ perform_target_ctor (tree init) |LOOKUP_NONVIRTUAL |LOOKUP_DESTRUCTOR, 0, tf_warning_or_error); + if (DECL_HAS_IN_CHARGE_PARM_P (current_function_decl)) + { + tree base = build_delete (input_location, + type, decl, sfk_base_destructor, + LOOKUP_NORMAL + |LOOKUP_NONVIRTUAL + |LOOKUP_DESTRUCTOR, + 0, tf_warning_or_error); + expr = build_if_in_charge (expr, base); + } if (expr != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)) finish_eh_cleanup (expr); diff --git a/gcc/testsuite/g++.dg/eh/delegating1.C b/gcc/testsuite/g++.dg/eh/delegating1.C new file mode 100644 index 0000000..c33374a --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/delegating1.C @@ -0,0 +1,28 @@ +// PR c++/103711 +// { dg-do run { target c++11 } } + +int constructions = 0; +int destructions = 0; + +struct A +{ + A() { constructions++; } + virtual ~A() { destructions++; } +}; + +struct B : public virtual A +{ + B(int) { } + B() : B(1) { throw -1; } + virtual ~B() = default; +}; + +struct C : public B { }; + +int main() { + try { + C c; + } + catch (int) {} + return (constructions - destructions); +} -- 2.7.4