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