From b533084d756a2696a3eb6521810e0a0b2182a8e8 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Mon, 30 Jan 2023 18:18:54 -0500 Subject: [PATCH] c++: aggregate base and TARGET_EXPR_ELIDING_P [PR108559] We also need to split up a CONSTRUCTOR in cp_genericize_init if we need to add extra copy constructor calls to deal with CWG2403. PR c++/108559 gcc/cp/ChangeLog: * cp-gimplify.cc (any_non_eliding_target_exprs): New. (cp_genericize_init): Check it. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/aggr-base13.C: New test. --- gcc/cp/cp-gimplify.cc | 22 +++++++++++++++++++--- gcc/testsuite/g++.dg/cpp1z/aggr-base13.C | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1z/aggr-base13.C diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index a35cedd05cc..9929d29981a 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -893,6 +893,21 @@ omp_cxx_notice_variable (struct cp_genericize_omp_taskreg *omp_ctx, tree decl) } } +/* True if any of the element initializers in CTOR are TARGET_EXPRs that are + not expected to elide, e.g. because unsafe_copy_elision_p is true. */ + +static bool +any_non_eliding_target_exprs (tree ctor) +{ + for (const constructor_elt &e : *CONSTRUCTOR_ELTS (ctor)) + { + if (TREE_CODE (e.value) == TARGET_EXPR + && !TARGET_EXPR_ELIDING_P (e.value)) + return true; + } + return false; +} + /* If we might need to clean up a partially constructed object, break down the CONSTRUCTOR with split_nonconstant_init. Also expand VEC_INIT_EXPR at this point. If initializing TO with FROM is non-trivial, overwrite *REPLACE with @@ -904,10 +919,11 @@ cp_genericize_init (tree *replace, tree from, tree to) tree init = NULL_TREE; if (TREE_CODE (from) == VEC_INIT_EXPR) init = expand_vec_init_expr (to, from, tf_warning_or_error); - else if (flag_exceptions - && TREE_CODE (from) == CONSTRUCTOR + else if (TREE_CODE (from) == CONSTRUCTOR && TREE_SIDE_EFFECTS (from) - && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (from))) + && ((flag_exceptions + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (from))) + || any_non_eliding_target_exprs (from))) { to = cp_stabilize_reference (to); replace_placeholders (from, to); diff --git a/gcc/testsuite/g++.dg/cpp1z/aggr-base13.C b/gcc/testsuite/g++.dg/cpp1z/aggr-base13.C new file mode 100644 index 00000000000..c4c7ee0e8f0 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/aggr-base13.C @@ -0,0 +1,19 @@ +// PR c++/108559 +// { dg-do compile { target c++17 } } + +struct A { + int g = 0; + + A() {} + A(const A&) {} +}; + +struct B : A {}; + +A u() { return A{}; } + +int bug() { return B{u()}.g; } + +int main() { + return 0; +}