2017-12-23 Jakub Jelinek PR c++/83556 * tree.c (replace_placeholders_r): Pass NULL as last argument to cp_walk_tree instead of d->pset. If non-TREE_CONSTANT and non-PLACEHOLDER_EXPR tree has been seen already, set *walk_subtrees to false and return. (replace_placeholders): Pass NULL instead of &pset as last argument to cp_walk_tree. * g++.dg/cpp0x/pr83556.C: New test. --- gcc/cp/tree.c.jj 2017-12-15 16:10:37.000000000 +0100 +++ gcc/cp/tree.c 2017-12-22 23:24:16.720428548 +0100 @@ -3106,6 +3106,11 @@ replace_placeholders_r (tree* t, int* wa { constructor_elt *ce; vec *v = CONSTRUCTOR_ELTS (*t); + if (d->pset->add (*t)) + { + *walk_subtrees = false; + return NULL_TREE; + } for (unsigned i = 0; vec_safe_iterate (v, i, &ce); ++i) { tree *valp = &ce->value; @@ -3125,7 +3130,7 @@ replace_placeholders_r (tree* t, int* wa valp = &TARGET_EXPR_INITIAL (*valp); } d->obj = subob; - cp_walk_tree (valp, replace_placeholders_r, data_, d->pset); + cp_walk_tree (valp, replace_placeholders_r, data_, NULL); d->obj = obj; } *walk_subtrees = false; @@ -3133,6 +3138,8 @@ replace_placeholders_r (tree* t, int* wa } default: + if (d->pset->add (*t)) + *walk_subtrees = false; break; } @@ -3161,7 +3168,7 @@ replace_placeholders (tree exp, tree obj replace_placeholders_t data = { obj, false, &pset }; if (TREE_CODE (exp) == TARGET_EXPR) tp = &TARGET_EXPR_INITIAL (exp); - cp_walk_tree (tp, replace_placeholders_r, &data, &pset); + cp_walk_tree (tp, replace_placeholders_r, &data, NULL); if (seen_p) *seen_p = data.seen; return exp; --- gcc/testsuite/g++.dg/cpp0x/pr83556.C.jj 2017-12-22 23:30:10.771126002 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr83556.C 2017-12-22 23:29:21.000000000 +0100 @@ -0,0 +1,28 @@ +// PR c++/83556 +// { dg-do run { target c++11 } } + +int +foo () +{ + return 1; +} + +struct A +{ + int a = foo (); + int b = 1; + int c = a ? 1 * b : 2 * b; +}; + +struct B +{ + A d {}; +}; + +int +main () +{ + B e {}; + if (e.d.c != 1) + __builtin_abort (); +}