* 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
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.
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);
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)
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)
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))
{
gcc_assert (TREE_CODE (x) == COMPONENT_REF);
*t = x;
*walk_subtrees = false;
+ d->seen = true;
}
break;
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;
}
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;
}
--- /dev/null
+// 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>();
+}