On Wed, Mar 14, 2018 at 08:55:47PM -0400, Jason Merrill wrote: > > @@ -3192,16 +3198,70 @@ replace_placeholders (tree exp, tree obj > > return exp; > > > > tree *tp = &exp; > > - hash_set<tree> pset; > > - replace_placeholders_t data = { obj, false, &pset }; > > + /* Use exp instead of *(type *)&exp. */ > > + while (TREE_CODE (exp) == INDIRECT_REF) > > + { > > + tree t = TREE_OPERAND (exp, 0); > > + STRIP_NOPS (t); > > + if (TREE_CODE (t) == ADDR_EXPR > > + && (t = TREE_OPERAND (t, 0)) > > + && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (exp), > > + TREE_TYPE (t))) > > + exp = t; > > + else > > + break; > > + } > > What's the motivation for this?
g++.dg/cpp0x/nsdmi13.C ICEs without that, we have there: a = A({}); and build_over_call does: 8163 else if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base))) 8164 { 8165 arg = cp_build_fold_indirect_ref (arg); 8166 val = build2 (MODIFY_EXPR, TREE_TYPE (to), to, arg); 8167 /* Handle NSDMI that refer to the object being initialized. */ 8168 replace_placeholders (arg, to); 8169 } where arg is after the cp_build_fold_indirect_ref *(struct A &) &TARGET_EXPR <D.2403, {.p=&<PLACEHOLDER_EXPR struct A>}> This is in MODIFY_EXPR rather than INIT_EXPR and the gimplifier through gimple_fold_indirect_ref_rhs folds the *(struct A &) & away and so there is no further temporary and thus cp_gimplify_init_expr isn't called to replace_placeholders, so if we don't replace it here (with to being the a VAR_DECL), we don't replace it ever. > I suspect that it should only apply if REFERENCE_REF_P. Incremental --- gcc/cp/tree.c~ 2018-03-15 09:13:38.000000000 +0100 +++ gcc/cp/tree.c 2018-03-15 09:15:43.029087739 +0100 @@ -3199,7 +3199,7 @@ replace_placeholders (tree exp, tree obj tree *tp = &exp; /* Use exp instead of *(type *)&exp. */ - while (TREE_CODE (exp) == INDIRECT_REF) + while (REFERENCE_REF_P (exp)) { tree t = TREE_OPERAND (exp, 0); STRIP_NOPS (t); works too. I think the gimplifier would gimple_fold_indirect_ref_rhs away even *(A *) &TARGET_EXPR, but maybe that just can't happen in C++. The point in the replace_placeholders data.exp computation is to differentiate between binding a CONSTRUCTOR to a particular object and e.g. the C c = bar (X {1}); case from pr79937-1.C where it is just an expression that contains a CONSTRUCTOR in it. In the former case, e.g. the nsdmi13.C, we want to replace placeholders in it, while in the latter we don't; in both cases there is just one CONSTRUCTOR, so say ignoring the new flag on outermost CONSTRUCTOR we process doesn't work. Jakub