aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2022-01-05 19:39:48 -0500
committerJason Merrill <jason@redhat.com>2022-01-06 19:25:43 -0500
commit32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd (patch)
tree8a181e36328d7c23208fbd7237bd9b2a2524724d /gcc
parent6ad76e73375a9c00a0a5f5729ae70bce7a6db5bc (diff)
downloadgcc-32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd.zip
gcc-32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd.tar.gz
gcc-32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd.tar.bz2
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.c10
-rw-r--r--gcc/testsuite/g++.dg/eh/delegating1.C28
2 files changed, 38 insertions, 0 deletions
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);
+}