@@ -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) \
@@ -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<tree> 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<tree> *) 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<tree> *) 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<tree> 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<tree> 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;
}
@@ -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
@@ -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
@@ -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;
}
new file mode 100644
@@ -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 = {}; }