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