On Thu, Mar 15, 2018 at 4:28 PM, Jakub Jelinek <ja...@redhat.com> wrote:
> On Thu, Mar 15, 2018 at 03:33:12PM -0400, Jason Merrill wrote:
>> Folding away the INDIRECT_REF is fine.  It's the TARGET_EXPR handling
>> that is wrong.
>
> Ah, ok.
>
>> > types of TARGET_EXPR, or ask some langhook whether it is ok to do so
>> > (say not ok if find_placeholders (t))?  Or contains_placeholder_p?
>> > Though the last one could also affect Ada and could return true even if
>> > the PLACEHOLDER_EXPRs are for some nested TARGET_EXPR in it.
>>
>> The existing test for whether to collapse a TARGET_EXPR is
>>
>>             if (init
>>                 && !VOID_TYPE_P (TREE_TYPE (init)))
>>
>> so we need this test to fail somehow when the constructor contains
>> placeholders, either by adding an additional test (like the ones you
>> mention) or by making the initialization void in a way that other
>> gimplification knows how to handle.
>
> So what about this?  It uses an unused bit on TARGET_EXPRs rather than
> a langhook, but if you prefer a langhook, I can add it.
>
> Tested so far just with
> make check-c++-all RUNTESTFLAGS="dg.exp='pr79937* pr82410.C nsdmi*'"
>
> 2018-03-15  Jakub Jelinek  <ja...@redhat.com>
>
>         PR c++/79937
>         PR c++/82410
>         * tree.h (TARGET_EXPR_NO_ELIDE): Define.
>         * gimplify.c (gimplify_arg, gimplify_modify_expr_rhs): Don't elide
>         TARGET_EXPRs with TARGET_EXPR_NO_ELIDE flag set.
>
>         * cp-tree.h (CONSTRUCTOR_PLACEHOLDER_BOUNDARY): Define.
>         (find_placeholder): Declare.
>         * tree.c (struct replace_placeholders_t): Add exp member.
>         (replace_placeholders_r): Don't walk into ctors with
>         CONSTRUCTOR_PLACEHOLDER_BOUNDARY flag set, unless they are equal to
>         d->exp.
>         (replace_placeholders): Initialize data.exp.
>         (find_placeholders_r, find_placeholders): New functions.
>         * typeck2.c (process_init_constructor_record,
>         process_init_constructor_union): Set CONSTRUCTOR_PLACEHOLDER_BOUNDARY
>         if adding NSDMI on which find_placeholder returns true.
>         * call.c (build_over_call): Don't call replace_placeholders here.
>         * cp-gimplify.c (cp_genericize_r): Set TARGET_EXPR_NO_ELIDE on
>         TARGET_EXPRs with CONSTRUCTOR_PLACEHOLDER_BOUNDARY set on
>         TARGET_EXPR_INITIAL.
>         (cp_fold): Copy over CONSTRUCTOR_PLACEHOLDER_BOUNDARY bit to new
>         ctor.
>
>         * g++.dg/cpp1y/pr79937-1.C: New test.
>         * g++.dg/cpp1y/pr79937-2.C: New test.
>         * g++.dg/cpp1y/pr79937-3.C: New test.
>         * g++.dg/cpp1y/pr79937-4.C: New test.
>         * g++.dg/cpp1y/pr82410.C: New test.
>
> +/* Don't elide the initialization of TARGET_EXPR_SLOT for this TARGET_EXPR.  
> */
> +#define TARGET_EXPR_NO_ELIDE(NODE) (TARGET_EXPR_CHECK 
> (NODE)->base.private_flag)

This should be specifically on the rhs of a MODIFY_EXPR; it's OK to
elide on the rhs of an INIT_EXPR.

> @@ -3155,7 +3155,8 @@ gimplify_arg (tree *arg_p, gimple_seq *p
>      {
>        test = is_gimple_lvalue, fb = fb_either;
>        /* Also strip a TARGET_EXPR that would force an extra copy.  */
> -      if (TREE_CODE (*arg_p) == TARGET_EXPR)
> +      if (TREE_CODE (*arg_p) == TARGET_EXPR
> +         && !TARGET_EXPR_NO_ELIDE (*arg_p))

This is also an initialization context, so we don't need to check it here.

> @@ -5211,6 +5212,7 @@ gimplify_modify_expr_rhs (tree *expr_p,
>             tree init = TARGET_EXPR_INITIAL (*from_p);
>
>             if (init
> +               && !TARGET_EXPR_NO_ELIDE (*from_p)

Here should check TREE_CODE (*expr_p).

Jason

Reply via email to