diff options
author | Jason Merrill <jason@redhat.com> | 2020-03-05 15:50:45 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2022-01-06 19:23:17 -0500 |
commit | 4f6bc28fc7dd86bd9e7408cbf28de1e973dd1eda (patch) | |
tree | 0a38c0720e5d43cd717dbef2244dad9d139dd830 /gcc/cp/constexpr.c | |
parent | beaee0a871b6485d20573fe050b1fd425581e56a (diff) | |
download | gcc-4f6bc28fc7dd86bd9e7408cbf28de1e973dd1eda.zip gcc-4f6bc28fc7dd86bd9e7408cbf28de1e973dd1eda.tar.gz gcc-4f6bc28fc7dd86bd9e7408cbf28de1e973dd1eda.tar.bz2 |
c++: EH and partially constructed aggr temp [PR66139]
Now that PR94041 is fixed, I can return to addressing PR66139, missing
cleanups for partially constructed aggregate temporaries. My previous
approach of calling split_nonconstant_init in cp_gimplify_init_expr broke
because gimplification is too late to be introducing destructor calls. So
instead I now call it under cp_fold_function, just before cp_genericize;
doing it from cp_genericize itself ran into trouble with the rewriting of
invisible references.
So now the prediction in cp_gimplify_expr that cp_gimplify_init_expr
might need to replace references to TARGET_EXPR_SLOT within
TARGET_EXPR_INITIAL has come to pass. constexpr.c already had the simple
search-and-replace tree walk I needed, but it needed to be fixed to actually
replace all occurrences instead of just the first one.
Handling of VEC_INIT_EXPR at gimplify time had similar issues that we worked
around with build_vec_init_elt, so I'm moving that to cp_fold_function as
well. But it seems that build_vec_init_elt is still useful for setting the
VEC_INIT_EXPR_IS_CONSTEXPR flag, so I'm leaving it alone.
This also fixes 52320, because build_aggr_init of each X from build_vec_init
builds an INIT_EXPR rather than call split_nonconstant_init at that point,
and now that INIT_EXPR gets split later.
PR c++/66139
PR c++/52320
gcc/cp/ChangeLog:
* constexpr.c (replace_decl): Rename from replace_result_decl.
* cp-tree.h (replace_decl): Declare it.
* cp-gimplify.c (cp_gimplify_init_expr): Call it.
(cp_gimplify_expr): Don't handle VEC_INIT_EXPR.
(cp_genericize_init, cp_genericize_init_expr)
(cp_genericize_target_expr): New.
(cp_fold_r): Call them.
* tree.c (build_array_copy): Add a TARGET_EXPR.
* typeck2.c (digest_init_r): Look through a TARGET_EXPR.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/initlist116.C: New test.
* g++.dg/cpp0x/initlist117.C: New test.
* g++.dg/cpp0x/lambda/lambda-eh.C: New test.
* g++.dg/eh/aggregate1.C: New test.
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 4a4b347..41594c7 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2251,24 +2251,26 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call, return cp_build_addr_expr (obj, complain); } -/* Data structure used by replace_result_decl and replace_result_decl_r. */ +/* Data structure used by replace_decl and replace_decl_r. */ -struct replace_result_decl_data +struct replace_decl_data { - /* The RESULT_DECL we want to replace. */ + /* The _DECL we want to replace. */ tree decl; /* The replacement for DECL. */ tree replacement; + /* Trees we've visited. */ + hash_set<tree> *pset; /* Whether we've performed any replacements. */ bool changed; }; -/* Helper function for replace_result_decl, called through cp_walk_tree. */ +/* Helper function for replace_decl, called through cp_walk_tree. */ static tree -replace_result_decl_r (tree *tp, int *walk_subtrees, void *data) +replace_decl_r (tree *tp, int *walk_subtrees, void *data) { - replace_result_decl_data *d = (replace_result_decl_data *) data; + replace_decl_data *d = (replace_decl_data *) data; if (*tp == d->decl) { @@ -2276,24 +2278,25 @@ replace_result_decl_r (tree *tp, int *walk_subtrees, void *data) d->changed = true; *walk_subtrees = 0; } - else if (TYPE_P (*tp)) + else if (TYPE_P (*tp) + || d->pset->add (*tp)) *walk_subtrees = 0; return NULL_TREE; } -/* Replace every occurrence of DECL, a RESULT_DECL, with (an unshared copy of) - REPLACEMENT within the reduced constant expression *TP. Returns true iff a +/* Replace every occurrence of DECL with (an unshared copy of) + REPLACEMENT within the expression *TP. Returns true iff a replacement was performed. */ -static bool -replace_result_decl (tree *tp, tree decl, tree replacement) +bool +replace_decl (tree *tp, tree decl, tree replacement) { - gcc_checking_assert (TREE_CODE (decl) == RESULT_DECL - && (same_type_ignoring_top_level_qualifiers_p - (TREE_TYPE (decl), TREE_TYPE (replacement)))); - replace_result_decl_data data = { decl, replacement, false }; - cp_walk_tree_without_duplicates (tp, replace_result_decl_r, &data); + gcc_checking_assert (same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (decl), TREE_TYPE (replacement))); + hash_set<tree> pset; + replace_decl_data data = { decl, replacement, &pset, false }; + cp_walk_tree (tp, replace_decl_r, &data, NULL); return data.changed; } @@ -2962,7 +2965,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t, if (!*non_constant_p && ctx->object && CLASS_TYPE_P (TREE_TYPE (res)) && !is_empty_class (TREE_TYPE (res))) - if (replace_result_decl (&result, res, ctx->object)) + if (replace_decl (&result, res, ctx->object)) cacheable = false; } else |