diff options
author | Jakub Jelinek <jakub@redhat.com> | 2018-03-16 13:46:12 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2018-03-16 13:46:12 +0100 |
commit | 570f86f94eca76fbfab919dcbfe639a5ba69f20e (patch) | |
tree | 1139d8cfc2b9466af7e0ef552bbdca551cdc549b /gcc/cp/tree.c | |
parent | aafdbe06af7127972c483fb2c9bf07b542b49d23 (diff) | |
download | gcc-570f86f94eca76fbfab919dcbfe639a5ba69f20e.zip gcc-570f86f94eca76fbfab919dcbfe639a5ba69f20e.tar.gz gcc-570f86f94eca76fbfab919dcbfe639a5ba69f20e.tar.bz2 |
re PR c++/79937 (ICE in replace_placeholders_r)
PR c++/79937
PR c++/82410
* tree.h (TARGET_EXPR_NO_ELIDE): Define.
* gimplify.c (gimplify_modify_expr_rhs): Don't elide TARGET_EXPRs with
TARGET_EXPR_NO_ELIDE flag set unless *expr_p is INIT_EXPR.
* cp-tree.h (CONSTRUCTOR_PLACEHOLDER_BOUNDARY): Define.
(find_placeholder): Declare.
* tree.c (struct replace_placeholders_t): Add exp member.
(replace_placeholders_r): Don't walk into ctors with
CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set, unless they are equal to
d->exp. Replace PLACEHOLDER_EXPR with unshare_expr (x) rather than x.
(replace_placeholders): Initialize data.exp.
(find_placeholders_r, find_placeholders): New functions.
* typeck2.c (process_init_constructor_record,
process_init_constructor_union): Set CONSTRUCTOR_PLACEHOLDER_BOUNDARY
if adding NSDMI on which find_placeholder returns true.
* call.c (build_over_call): Don't call replace_placeholders here.
* cp-gimplify.c (cp_genericize_r): Set TARGET_EXPR_NO_ELIDE on
TARGET_EXPRs with CONSTRUCTOR_PLACEHOLDER_BOUNDARY set on
TARGET_EXPR_INITIAL.
(cp_fold): Copy over CONSTRUCTOR_PLACEHOLDER_BOUNDARY bit to new
ctor.
* g++.dg/cpp1y/pr79937-1.C: New test.
* g++.dg/cpp1y/pr79937-2.C: New test.
* g++.dg/cpp1y/pr79937-3.C: New test.
* g++.dg/cpp1y/pr79937-4.C: New test.
* g++.dg/cpp1y/pr82410.C: New test.
From-SVN: r258593
Diffstat (limited to 'gcc/cp/tree.c')
-rw-r--r-- | gcc/cp/tree.c | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c2299ba..90fbe18 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -3096,6 +3096,7 @@ build_ctor_subob_ref (tree index, tree type, tree obj) struct replace_placeholders_t { tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. */ + tree exp; /* The outermost exp. */ bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */ hash_set<tree> *pset; /* To avoid walking same trees multiple times. */ }; @@ -3124,7 +3125,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) TREE_TYPE (x)); x = TREE_OPERAND (x, 0)) gcc_assert (TREE_CODE (x) == COMPONENT_REF); - *t = x; + *t = unshare_expr (x); *walk_subtrees = false; d->seen = true; } @@ -3134,7 +3135,12 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) { constructor_elt *ce; vec<constructor_elt,va_gc> *v = CONSTRUCTOR_ELTS (*t); - if (d->pset->add (*t)) + /* Don't walk into CONSTRUCTOR_PLACEHOLDER_BOUNDARY ctors + other than the d->exp one, those have PLACEHOLDER_EXPRs + related to another object. */ + if ((CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t) + && *t != d->exp) + || d->pset->add (*t)) { *walk_subtrees = false; return NULL_TREE; @@ -3192,16 +3198,57 @@ replace_placeholders (tree exp, tree obj, bool *seen_p) return exp; tree *tp = &exp; - hash_set<tree> pset; - replace_placeholders_t data = { obj, false, &pset }; if (TREE_CODE (exp) == TARGET_EXPR) tp = &TARGET_EXPR_INITIAL (exp); + hash_set<tree> pset; + replace_placeholders_t data = { obj, *tp, false, &pset }; cp_walk_tree (tp, replace_placeholders_r, &data, NULL); if (seen_p) *seen_p = data.seen; return exp; } +/* Callback function for find_placeholders. */ + +static tree +find_placeholders_r (tree *t, int *walk_subtrees, void *) +{ + if (TYPE_P (*t) || TREE_CONSTANT (*t)) + { + *walk_subtrees = false; + return NULL_TREE; + } + + switch (TREE_CODE (*t)) + { + case PLACEHOLDER_EXPR: + return *t; + + case CONSTRUCTOR: + if (CONSTRUCTOR_PLACEHOLDER_BOUNDARY (*t)) + *walk_subtrees = false; + break; + + default: + break; + } + + return NULL_TREE; +} + +/* Return true if EXP contains a PLACEHOLDER_EXPR. Don't walk into + ctors with CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set. */ + +bool +find_placeholders (tree exp) +{ + /* This is only relevant for C++14. */ + if (cxx_dialect < cxx14) + return false; + + return cp_walk_tree_without_duplicates (&exp, find_placeholders_r, NULL); +} + /* Similar to `build_nt', but for template definitions of dependent expressions */ |