From: Jason Merrill Date: Wed, 2 Feb 2022 23:36:41 +0000 (-0500) Subject: c++: assignment, aggregate, array [PR104300] X-Git-Tag: upstream/12.2.0~1628 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=119cea98f664764cce04963243c39c8f6d797d33;p=platform%2Fupstream%2Fgcc.git 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 --git a/gcc/cp/cp-gimplify.cc b/gcc/cp/cp-gimplify.cc index d1c653c..d7323fb 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. */ +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_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/cp-tree.h b/gcc/cp/cp-tree.h index b9eb71f..d71be0a 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/init.cc b/gcc/cp/init.cc index 1f04783..fcb255f 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 2d8f2c5..6e9be71 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 f439dd5..4015bd5 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 0000000..baa4afc --- /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 = {}; }