@@ -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);
@@ -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)
@@ -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;
}
new file mode 100644
@@ -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>();
+}