aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2017-02-11 22:31:02 -0500
committerJason Merrill <jason@gcc.gnu.org>2017-02-11 22:31:02 -0500
commit817a77e41e22599a66610617b1112bb76850ff26 (patch)
tree5b93c54d8db50f37340efb1d9d46397ca795616d /gcc
parent95bbcf58810306bb5f0c24e67620a9e710b0d691 (diff)
downloadgcc-817a77e41e22599a66610617b1112bb76850ff26.zip
gcc-817a77e41e22599a66610617b1112bb76850ff26.tar.gz
gcc-817a77e41e22599a66610617b1112bb76850ff26.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/cp-tree.h2
-rw-r--r--gcc/cp/init.c26
-rw-r--r--gcc/cp/tree.c22
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/nsdmi-aggr6.C14
5 files changed, 64 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 553db8a..486cb88 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,13 @@
2017-02-11 Jason Merrill <jason@redhat.com>
+ 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 0146332..6675ee5 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 42f1c61..524c583 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -3282,7 +3282,19 @@ build_new_1 (vec<tree, va_gc> **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<tree, va_gc> **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 56c4bba..d3c63b8 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<tree>(data_);
+ replace_placeholders_t *d = static_cast<replace_placeholders_t*>(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 0000000..83fdedd
--- /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 <typename Type> Type get_max_value(Type);
+struct A {
+ struct B {
+ int baz = get_max_value(baz);
+ };
+ template <typename> void m_fn1() { new B{}; }
+};
+void foo() {
+ A a;
+ a.m_fn1<int>();
+}