diff options
author | Jason Merrill <jason@redhat.com> | 2022-01-05 19:39:48 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-01-06 19:25:43 -0500 |
commit | 32d8ff73718fd07a9a7dfd2566d3b7b69f37b6bd (patch) | |
tree | 8a181e36328d7c23208fbd7237bd9b2a2524724d /gcc | |
parent | 6ad76e73375a9c00a0a5f5729ae70bce7a6db5bc (diff) | |
download | gcc-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.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/eh/delegating1.C | 28 |
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); +} |