From 817a77e41e22599a66610617b1112bb76850ff26 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 11 Feb 2017 22:31:02 -0500 Subject: [PATCH] PR c++/77659 - ICE with new and C++14 aggregate NSDMI * init.c (build_new): Make backups of any CONSTRUCTORs in init. (build_new_1): Use replace_placeholders. * tree.c (replace_placeholders_t): Also track whether we've seen a placeholder. (replace_placeholders, replace_placeholders_r): Adjust. * cp-tree.h: Adjust. From-SVN: r245372 --- gcc/cp/ChangeLog | 8 ++++++++ gcc/cp/cp-tree.h | 2 +- gcc/cp/init.c | 26 ++++++++++++++++++++++-- gcc/cp/tree.c | 22 +++++++++++++++----- gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C | 14 +++++++++++++ 5 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 553db8a126b..486cb88575f 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,13 @@ 2017-02-11 Jason Merrill + PR c++/77659 - ICE with new and C++14 aggregate NSDMI + * init.c (build_new): Make backups of any CONSTRUCTORs in init. + (build_new_1): Use replace_placeholders. + * tree.c (replace_placeholders_t): Also track whether we've seen a + placeholder. + (replace_placeholders, replace_placeholders_r): Adjust. + * cp-tree.h: Adjust. + PR c++/77790 - ICE with auto function in C++11 mode * decl.c (undeduced_auto_decl): Remove C++14 limitation. (require_deduced_type): Add complain parm, return bool. diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 0146332181c..6675ee5bb50 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6658,7 +6658,7 @@ extern tree array_type_nelts_total (tree); extern tree array_type_nelts_top (tree); extern tree break_out_target_exprs (tree); extern tree build_ctor_subob_ref (tree, tree, tree); -extern tree replace_placeholders (tree, tree); +extern tree replace_placeholders (tree, tree, bool * = NULL); extern tree get_type_decl (tree); extern tree decl_namespace_context (tree); extern bool decl_anon_ns_mem_p (const_tree); diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 42f1c6192ec..524c583138f 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -3282,7 +3282,19 @@ build_new_1 (vec **placement, tree type, tree nelts, init_expr = cp_build_modify_expr (input_location, init_expr, INIT_EXPR, ie, complain); } - stable = stabilize_init (init_expr, &init_preeval_expr); + /* If the initializer uses C++14 aggregate NSDMI that refer to the + object being initialized, replace them now and don't try to + preevaluate. */ + bool had_placeholder = false; + if (cxx_dialect >= cxx14 + && !processing_template_decl + && TREE_CODE (init_expr) == INIT_EXPR) + TREE_OPERAND (init_expr, 1) + = replace_placeholders (TREE_OPERAND (init_expr, 1), + TREE_OPERAND (init_expr, 0), + &had_placeholder); + stable = (!had_placeholder + && stabilize_init (init_expr, &init_preeval_expr)); } if (init_expr == error_mark_node) @@ -3454,7 +3466,17 @@ build_new (vec **placement, tree type, tree nelts, orig_placement = make_tree_vector_copy (*placement); orig_nelts = nelts; if (*init) - orig_init = make_tree_vector_copy (*init); + { + orig_init = make_tree_vector_copy (*init); + /* Also copy any CONSTRUCTORs in *init, since reshape_init and + digest_init clobber them in place. */ + for (unsigned i = 0; i < orig_init->length(); ++i) + { + tree e = (**init)[i]; + if (TREE_CODE (e) == CONSTRUCTOR) + (**init)[i] = copy_node (e); + } + } make_args_non_dependent (*placement); if (nelts) diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index 56c4bbaf8b8..d3c63b82cb3 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -2728,13 +2728,20 @@ build_ctor_subob_ref (tree index, tree type, tree obj) return obj; } +struct replace_placeholders_t +{ + tree obj; /* The object to be substituted for a PLACEHOLDER_EXPR. */ + bool seen; /* Whether we've encountered a PLACEHOLDER_EXPR. */ +}; + /* Like substitute_placeholder_in_expr, but handle C++ tree codes and build up subexpressions as we go deeper. */ static tree replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) { - tree obj = static_cast(data_); + replace_placeholders_t *d = static_cast(data_); + tree obj = d->obj; if (TREE_CONSTANT (*t)) { @@ -2753,6 +2760,7 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) gcc_assert (TREE_CODE (x) == COMPONENT_REF); *t = x; *walk_subtrees = false; + d->seen = true; } break; @@ -2778,9 +2786,10 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) if (TREE_CODE (*valp) == TARGET_EXPR) valp = &TARGET_EXPR_INITIAL (*valp); } - + d->obj = subob; cp_walk_tree (valp, replace_placeholders_r, - subob, NULL); + data_, NULL); + d->obj = obj; } *walk_subtrees = false; break; @@ -2794,12 +2803,15 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_) } tree -replace_placeholders (tree exp, tree obj) +replace_placeholders (tree exp, tree obj, bool *seen_p) { tree *tp = &exp; + replace_placeholders_t data = { obj, false }; if (TREE_CODE (exp) == TARGET_EXPR) tp = &TARGET_EXPR_INITIAL (exp); - cp_walk_tree (tp, replace_placeholders_r, obj, NULL); + cp_walk_tree (tp, replace_placeholders_r, &data, NULL); + if (seen_p) + *seen_p = data.seen; return exp; } diff --git a/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C new file mode 100644 index 00000000000..83fdedde11e --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C @@ -0,0 +1,14 @@ +// PR c++/77659 +// { dg-do compile { target c++14 } } + +template Type get_max_value(Type); +struct A { + struct B { + int baz = get_max_value(baz); + }; + template void m_fn1() { new B{}; } +}; +void foo() { + A a; + a.m_fn1(); +} -- 2.30.2