From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2122) id F1FA53858015; Wed, 9 Feb 2022 01:10:01 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org F1FA53858015 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Jason Merrill To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-7117] c++: cleanup constant-init'd members [PR96876] X-Act-Checkin: gcc X-Git-Author: Jason Merrill X-Git-Refname: refs/heads/master X-Git-Oldrev: 2a2fda2d9bebb9ef7fe4b9c8aa492a6517603e21 X-Git-Newrev: 53cac72cf0821217f99d0640ba72cc2999ec7dc0 Message-Id: <20220209011001.F1FA53858015@sourceware.org> Date: Wed, 9 Feb 2022 01:10:01 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 09 Feb 2022 01:10:02 -0000 https://gcc.gnu.org/g:53cac72cf0821217f99d0640ba72cc2999ec7dc0 commit r12-7117-g53cac72cf0821217f99d0640ba72cc2999ec7dc0 Author: Jason Merrill Date: Fri Feb 4 18:25:51 2022 -0500 c++: cleanup constant-init'd members [PR96876] This is a case missed by my recent fixes to aggregate initialization and exception cleanup for PR94041 et al: we also need to clean up members with constant initialization if initialization of a later member throws. It also occurs to me that we needn't bother building the cleanups if -fno-exceptions; build_vec_init already doesn't. PR c++/96876 gcc/cp/ChangeLog: * typeck2.cc (split_nonconstant_init_1): Push cleanups for preceding members with constant initialization. (maybe_push_temp_cleanup): Do nothing if -fno-exceptions. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/aggr-base11.C: New test. * g++.dg/eh/aggregate2.C: New test. Diff: --- gcc/cp/typeck2.cc | 26 ++++++++++++++++++++++++++ gcc/testsuite/g++.dg/cpp1z/aggr-base11.C | 19 +++++++++++++++++++ gcc/testsuite/g++.dg/eh/aggregate2.C | 27 +++++++++++++++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index 4015bd53257..39d03e4c3c4 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -467,6 +467,8 @@ cxx_incomplete_type_error (location_t loc, const_tree value, const_tree type) static void maybe_push_temp_cleanup (tree sub, vec **flags) { + if (!flag_exceptions) + return; if (tree cleanup = cxx_maybe_build_cleanup (sub, tf_warning_or_error)) { @@ -496,6 +498,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, bool array_type_p = false; bool complete_p = true; HOST_WIDE_INT num_split_elts = 0; + tree last_split_elt = NULL_TREE; switch (TREE_CODE (type)) { @@ -572,6 +575,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, else { /* Mark element for removal. */ + last_split_elt = field_index; CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; if (idx < tidx) tidx = idx; @@ -584,6 +588,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, flags)); /* Mark element for removal. */ + last_split_elt = field_index; CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; if (idx < tidx) tidx = idx; @@ -593,6 +598,26 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, { tree code; + /* Push cleanups for any preceding members with constant + initialization. */ + if (CLASS_TYPE_P (type)) + for (tree prev = (last_split_elt ? + DECL_CHAIN (last_split_elt) + : TYPE_FIELDS (type)); + ; prev = DECL_CHAIN (prev)) + { + prev = next_initializable_field (prev); + if (prev == field_index) + break; + tree ptype = TREE_TYPE (prev); + if (type_build_dtor_call (ptype)) + { + tree pcref = build3 (COMPONENT_REF, ptype, dest, prev, + NULL_TREE); + maybe_push_temp_cleanup (pcref, flags); + } + } + /* Mark element for removal. */ CONSTRUCTOR_ELT (init, idx)->index = NULL_TREE; if (idx < tidx) @@ -645,6 +670,7 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, maybe_push_temp_cleanup (sub, flags); } + last_split_elt = field_index; num_split_elts++; } } diff --git a/gcc/testsuite/g++.dg/cpp1z/aggr-base11.C b/gcc/testsuite/g++.dg/cpp1z/aggr-base11.C new file mode 100644 index 00000000000..88625dc9533 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/aggr-base11.C @@ -0,0 +1,19 @@ +// PR c++/96876 +// { dg-do compile { target c++17 } } + +struct B { +protected: + ~B() {} // { dg-message "" } +}; + +struct A { }; +struct C1: B { int n; }; +struct C2: A, B { int n; }; + +A af (); +int f(); + +void g() { + C1 c1{ {}, f()}; // { dg-error "protected" } + C2 c2{ af(), {}, f()}; // { dg-error "protected" } +} diff --git a/gcc/testsuite/g++.dg/eh/aggregate2.C b/gcc/testsuite/g++.dg/eh/aggregate2.C new file mode 100644 index 00000000000..8424d63de2d --- /dev/null +++ b/gcc/testsuite/g++.dg/eh/aggregate2.C @@ -0,0 +1,27 @@ +// PR c++/96876 +// { dg-do run { target c++11 } } + +int d; +struct B { + ~B() { ++d; } +}; + +struct C1 { B b; int n; }; +struct C2 { int i; B b; int n; }; + +int f() { throw 24; return 42; } +int dummy; +int g() { ++dummy; return 42; } + +int main() { + try { + C1 c{{}, f()}; + } catch (...) { } + + try { + C2 c{g(), {}, f()}; + } catch (...) { } + + if (d != 2) + __builtin_abort (); +}