On 11/27/18 5:41 PM, Jakub Jelinek wrote:
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.
Sounds like that's the bug, then; instantiation is failing to preserve
the pass-through nature of the call.
Jason