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

Reply via email to