On Tue, Nov 27, 2018 at 05:20:56PM -0500, Jason Merrill wrote:
> On 11/23/18 4:15 PM, Jakub Jelinek wrote:
> > Hi!
> > 
> > On the following testcase, the call to operator () is marked as
> > CALL_FROM_THUNK_P and therefore genericization ignores all subtrees thereof.
> > Unfortunately, one of the arguments is a move ctor call which is not itself
> > CALL_FROM_THUNK_P and thus we need to genericize its arguments, otherwise
> > we pass address of a temporary which holds a reference value instead of the
> > reference itself.
> > 
> > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> > Or should CALL_FROM_THUNK_P not be set in this call (it is set in
> > maybe_add_lambda_conv_op and then copied over during tsubst*).
> 
> The call with CALL_FROM_THUNK_P set should be inside the thunk whose address
> we get when converting the lambda to a function pointer (on return from
> foo).  Its arguments should just be the parms of that thunk, I don't know
> where this temporary is coming from.

In the *.original dump this is:
<<cleanup_point <<< Unknown tree: expr_stmt
  foo()::<lambda(auto:1)>::operator()<S> (0B, &TARGET_EXPR <D.2406, <<< Unknown 
tree: aggr_init_expr
  5
  __ct_comp
  D.2406
  (struct S *) <<< Unknown tree: void_cst >>>
  (struct S &) &D.2402 >>>>) >>>>>;
return;

where CALL_FROM_THUNK_P is set on the call to
foo()::<lambda(auto:1)>::operator()<S> and D.2402 is the
PARM_DECL which shouldn't have the &.
In *.gimple it is:
foo()::<lambda(auto:1)>::_FUN<S> (struct S & restrict D.2402) // the arg is 
DECL_BY_REFERENCE
{
  struct S D.2406;
  struct S & D.2413;

  D.2413 = D.2402;
  S::S (&D.2406, &D.2413); // this ctor wants S & arg, so it should be just 
D.2402
  try
    {
      try
        {
          foo()::<lambda(auto:1)>::operator()<S> (0B, &D.2406);
        }
      finally
        {
          S::~S (&D.2406);
        }
    }
  finally
    {
      D.2406 = {CLOBBER};
    }
  return;
}

CALL_FROM_THUNK_P is set on the operator() call in maybe_add_lambda_conv_op
and at that the call is:
 <call_expr 0x7fffefc8b2a0
    fn <component_ref 0x7fffefde9f30
        arg:0 <indirect_ref 0x7fffefdf4880 type <record_type 0x7fffefdf9150 
__lambda0>
            readonly
            arg:0 <nop_expr 0x7fffefdf4860 type <pointer_type 0x7fffefdf92a0>
                constant
                arg:0 <nop_expr 0x7fffefdf4840 type <pointer_type 
0x7fffefdf9348>
                    constant
                    arg:0 <integer_cst 0x7fffefca1228 constant 0>>>>
        arg:1 <identifier_node 0x7fffefc97800 operator() tree_2
            simple-op local bindings <0x7fffefdd7488>>>
    arg:0 <indirect_ref 0x7fffefdf48c0
        type <template_type_parm 0x7fffefded7e0 auto:1 type_0 type_6 VOID
            align:8 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type 
0x7fffefded7e0
           index 0 level 1 orig_level 1
            reference_to_this <reference_type 0x7fffefdf93f0> chain <type_decl 
0x7fffefda1ab0 auto:1>>
        side-effects
        arg:0 <static_cast_expr 0x7fffefdf48a0 type <reference_type 
0x7fffefdf9498>
            side-effects arg:0 <parm_decl 0x7fffefdf2e00 val>>>>
The rest (TARGET_EXPR, ctor etc.) appears during instantiation.

        Jakub

Reply via email to