From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2122) id 502DA385841E; Sat, 5 Feb 2022 05:57:32 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 502DA385841E 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-7069] c++: assignment, aggregate, array [PR104300] X-Act-Checkin: gcc X-Git-Author: Jason Merrill X-Git-Refname: refs/heads/master X-Git-Oldrev: 0ef416e7edc4c66a06a3c05025720dfc98cf07f5 X-Git-Newrev: 119cea98f664764cce04963243c39c8f6d797d33 Message-Id: <20220205055732.502DA385841E@sourceware.org> Date: Sat, 5 Feb 2022 05:57:32 +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: Sat, 05 Feb 2022 05:57:32 -0000 https://gcc.gnu.org/g:119cea98f664764cce04963243c39c8f6d797d33 commit r12-7069-g119cea98f664764cce04963243c39c8f6d797d33 Author: Jason Merrill Date: Wed Feb 2 18:36:41 2022 -0500 c++: assignment, aggregate, array [PR104300] The PR92385 fix meant that we see more VEC_INIT_EXPR outside of INIT_EXPR; in such cases, we need to wrap them in TARGET_EXPR. I previously fixed that in build_array_copy; we also need it in process_init_constructor. After fixing that, I needed to adjust a few places to recognize the VEC_INIT_EXPR even inside a TARGET_EXPR. And prevent cp_fully_fold_init from lowering VEC_INIT_EXPR too soon. And handle COMPOUND_EXPR inside TARGET_EXPR better. PR c++/104300 PR c++/92385 gcc/cp/ChangeLog: * cp-tree.h (get_vec_init_expr): New. (target_expr_needs_replace): New. * cp-gimplify.cc (cp_gimplify_init_expr): Use it. (struct cp_fold_data): New. (cp_fold_r): Only genericize inits at end of fn. (cp_fold_function): Here. (cp_fully_fold_init): Not here. * init.cc (build_vec_init): Use get_vec_init_expr. * tree.cc (build_vec_init_expr): Likewise. * typeck2.cc (split_nonconstant_init_1): Likewise. (process_init_constructor): Wrap VEC_INIT_EXPR in TARGET_EXPR. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-array14.C: New test. Diff: --- gcc/cp/cp-tree.h | 27 +++++++++++++++++++ gcc/cp/cp-gimplify.cc | 39 ++++++++++++++++++--------- gcc/cp/init.cc | 12 ++++++--- gcc/cp/tree.cc | 4 +-- gcc/cp/typeck2.cc | 9 +++++-- gcc/testsuite/g++.dg/cpp0x/initlist-array14.C | 12 +++++++++ 6 files changed, 82 insertions(+), 21 deletions(-) diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b9eb71fbc3a..d71be0a5bc7 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -4201,6 +4201,18 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) #define VEC_INIT_EXPR_VALUE_INIT(NODE) \ TREE_LANG_FLAG_1 (VEC_INIT_EXPR_CHECK (NODE)) +/* If T is a VEC_INIT_EXPR, return it, possibly stripping a TARGET_EXPR + wrapper. Otherwise, return null. */ +inline tree +get_vec_init_expr (tree t) +{ + if (t && TREE_CODE (t) == TARGET_EXPR) + t = TARGET_EXPR_INITIAL (t); + if (t && TREE_CODE (t) == VEC_INIT_EXPR) + return t; + return NULL_TREE; +} + /* The condition under which this MUST_NOT_THROW_EXPR actually blocks exceptions. NULL_TREE means 'true'. */ #define MUST_NOT_THROW_COND(NODE) \ @@ -5361,6 +5373,21 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) && TARGET_EXPR_INITIAL (NODE) \ && !VOID_TYPE_P (TREE_TYPE (TARGET_EXPR_INITIAL (NODE)))) +/* True if T is a TARGET_EXPR for which we'll need to replace_decl to use it as + an initializer. */ +inline bool +target_expr_needs_replace (tree t) +{ + if (!t || TREE_CODE (t) != TARGET_EXPR) + return false; + tree init = TARGET_EXPR_INITIAL (t); + if (!init || !VOID_TYPE_P (TREE_TYPE (init))) + return false; + while (TREE_CODE (init) == COMPOUND_EXPR) + init = TREE_OPERAND (init, 1); + return TREE_CODE (init) != AGGR_INIT_EXPR; +} + /* True if EXPR expresses direct-initialization of a TYPE. */ #define DIRECT_INIT_EXPR_P(TYPE,EXPR) \ (TREE_CODE (EXPR) == TARGET_EXPR && TREE_LANG_FLAG_2 (EXPR) \ diff --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index d1c653c5fda..d7323fb5c09 100644 --- a/gcc/cp/cp-gimplify.cc +++ b/gcc/cp/cp-gimplify.cc @@ -249,8 +249,7 @@ cp_gimplify_init_expr (tree *expr_p) if (TREE_CODE (from) == TARGET_EXPR) if (tree init = TARGET_EXPR_INITIAL (from)) { - if (VOID_TYPE_P (TREE_TYPE (init)) - && TREE_CODE (init) != AGGR_INIT_EXPR) + if (target_expr_needs_replace (from)) { /* If this was changed by cp_genericize_target_expr, we need to walk into it to replace uses of the slot. */ @@ -950,14 +949,23 @@ struct cp_genericize_data /* Perform any pre-gimplification folding of C++ front end trees to GENERIC. - Note: The folding of none-omp cases is something to move into + Note: The folding of non-omp cases is something to move into the middle-end. As for now we have most foldings only on GENERIC in fold-const, we need to perform this before transformation to GIMPLE-form. */ -static tree -cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) +struct cp_fold_data { + hash_set pset; + bool genericize; // called from cp_fold_function? + + cp_fold_data (bool g): genericize (g) {} +}; + +static tree +cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data_) +{ + cp_fold_data *data = (cp_fold_data*)data_; tree stmt = *stmt_p; enum tree_code code = TREE_CODE (stmt); @@ -967,7 +975,7 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) if (TREE_CODE (PTRMEM_CST_MEMBER (stmt)) == FUNCTION_DECL && DECL_IMMEDIATE_FUNCTION_P (PTRMEM_CST_MEMBER (stmt))) { - if (!((hash_set *) data)->add (stmt)) + if (!data->pset.add (stmt)) error_at (PTRMEM_CST_LOCATION (stmt), "taking address of an immediate function %qD", PTRMEM_CST_MEMBER (stmt)); @@ -1001,7 +1009,7 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) *stmt_p = stmt = cp_fold (*stmt_p); - if (((hash_set *) data)->add (stmt)) + if (data->pset.add (stmt)) { /* Don't walk subtrees of stmts we've already walked once, otherwise we can have exponential complexity with e.g. lots of nested @@ -1075,12 +1083,17 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) } break; + /* These are only for genericize time; they're here rather than in + cp_genericize to avoid problems with the invisible reference + transition. */ case INIT_EXPR: - cp_genericize_init_expr (stmt_p); + if (data->genericize) + cp_genericize_init_expr (stmt_p); break; case TARGET_EXPR: - cp_genericize_target_expr (stmt_p); + if (data->genericize) + cp_genericize_target_expr (stmt_p); break; default: @@ -1096,8 +1109,8 @@ cp_fold_r (tree *stmt_p, int *walk_subtrees, void *data) void cp_fold_function (tree fndecl) { - hash_set pset; - cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &pset, NULL); + cp_fold_data data (/*genericize*/true); + cp_walk_tree (&DECL_SAVED_TREE (fndecl), cp_fold_r, &data, NULL); } /* Turn SPACESHIP_EXPR EXPR into GENERIC. */ @@ -2358,8 +2371,8 @@ cp_fully_fold_init (tree x) if (processing_template_decl) return x; x = cp_fully_fold (x); - hash_set pset; - cp_walk_tree (&x, cp_fold_r, &pset, NULL); + cp_fold_data data (/*genericize*/false); + cp_walk_tree (&x, cp_fold_r, &data, NULL); return x; } diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index 1f047831b6d..fcb255f1ac7 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -4368,8 +4368,8 @@ build_vec_init (tree base, tree maxindex, tree init, && from_array != 2) init = TARGET_EXPR_INITIAL (init); - if (init && TREE_CODE (init) == VEC_INIT_EXPR) - init = VEC_INIT_EXPR_INIT (init); + if (tree vi = get_vec_init_expr (init)) + init = VEC_INIT_EXPR_INIT (vi); bool direct_init = false; if (from_array && init && BRACE_ENCLOSED_INITIALIZER_P (init) @@ -4581,10 +4581,14 @@ build_vec_init (tree base, tree maxindex, tree init, num_initialized_elts++; + /* We need to see sub-array TARGET_EXPR before cp_fold_r so we can + handle cleanup flags properly. */ + gcc_checking_assert (!target_expr_needs_replace (elt)); + if (digested) one_init = build2 (INIT_EXPR, type, baseref, elt); - else if (TREE_CODE (elt) == VEC_INIT_EXPR) - one_init = expand_vec_init_expr (baseref, elt, complain, flags); + else if (tree vi = get_vec_init_expr (elt)) + one_init = expand_vec_init_expr (baseref, vi, complain, flags); else if (MAYBE_CLASS_TYPE_P (type) || TREE_CODE (type) == ARRAY_TYPE) one_init = build_aggr_init (baseref, elt, 0, complain); else diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index 2d8f2c551c0..6e9be713c51 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -785,8 +785,8 @@ build_vec_init_elt (tree type, tree init, tsubst_flags_t complain) tree build_vec_init_expr (tree type, tree init, tsubst_flags_t complain) { - if (init && TREE_CODE (init) == VEC_INIT_EXPR) - return init; + if (tree vi = get_vec_init_expr (init)) + return vi; tree elt_init; if (init && TREE_CODE (init) == CONSTRUCTOR diff --git a/gcc/cp/typeck2.cc b/gcc/cp/typeck2.cc index f439dd54866..4015bd53257 100644 --- a/gcc/cp/typeck2.cc +++ b/gcc/cp/typeck2.cc @@ -548,6 +548,10 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, bool elt_last = last && idx == CONSTRUCTOR_NELTS (init) - 1; + /* We need to see sub-array TARGET_EXPR before cp_fold_r so we can + handle cleanup flags properly. */ + gcc_checking_assert (!target_expr_needs_replace (value)); + if (TREE_CODE (value) == CONSTRUCTOR) { if (!split_nonconstant_init_1 (sub, value, elt_last, flags) @@ -574,9 +578,9 @@ split_nonconstant_init_1 (tree dest, tree init, bool last, num_split_elts++; } } - else if (TREE_CODE (value) == VEC_INIT_EXPR) + else if (tree vi = get_vec_init_expr (value)) { - add_stmt (expand_vec_init_expr (sub, value, tf_warning_or_error, + add_stmt (expand_vec_init_expr (sub, vi, tf_warning_or_error, flags)); /* Mark element for removal. */ @@ -1925,6 +1929,7 @@ process_init_constructor (tree type, tree init, int nested, int flags, initializer-clause until later so we can use a loop. */ TREE_TYPE (init) = init_list_type_node; init = build_vec_init_expr (type, init, complain); + init = get_target_expr (init); } return init; } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array14.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array14.C new file mode 100644 index 00000000000..baa4afc91fd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array14.C @@ -0,0 +1,12 @@ +// PR c++/104300 +// { dg-do compile { target c++11 } } + +struct ss { + char r; + ss(); +}; +struct a { + ss e[6]; +}; +a vv; +void ff() { vv = {}; }