* lambda.c (maybe_add_lambda_conv_op): Optimize argvec building and early out if CALLOP contains a function parameter pack. --- gcc/cp/lambda.c | 60 ++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 16 deletions(-)
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c index e9bc7c5..4d76f82 100644 --- a/gcc/cp/lambda.c +++ b/gcc/cp/lambda.c @@ -770,8 +770,51 @@ maybe_add_lambda_conv_op (tree type) return; } + argvec = make_tree_vector (); + + /* Non-template conversion operators are defined directly. Templates are + deferred. In the non-template case, the nullptr instance of the stateless + lambda type is added to ARGVEC for build_call_a. In the template case it + is bound via build_min. */ + if (!generic_lambda_p) + { + arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), + null_pointer_node); + argvec->quick_push (arg); + } + + /* Copy CALLOP's argument list (as per 'copy_list') as FN_ARGS in order to + declare the static member function "_FUN" below. For each arg append to + ARGVEC (converting from reference in the template call op case). Early out + if a parameter pack is found; conversion to function pointer is not + supported in this case. */ + tree fn_args = NULL_TREE; + { + tree src = DECL_CHAIN (DECL_ARGUMENTS (callop)); + tree tgt; + + while (src) + { + if (FUNCTION_PARAMETER_PACK_P (src)) + return; + + if (!fn_args) + fn_args = tgt = copy_node (src); + else + { + TREE_CHAIN (tgt) = copy_node (src); + tgt = TREE_CHAIN (tgt); + } + + mark_exp_read (tgt); + vec_safe_push (argvec, + generic_lambda_p ? convert_from_reference (tgt) : tgt); + + src = TREE_CHAIN (src); + } + } + tree fn_result = TREE_TYPE (TREE_TYPE (callop)); - tree fn_args = copy_list (DECL_CHAIN (DECL_ARGUMENTS (callop))); if (generic_lambda_p) { @@ -780,12 +823,6 @@ maybe_add_lambda_conv_op (tree type) implementation of the conversion operator. */ tree instance = build_nop (type, null_pointer_node); - argvec = make_tree_vector (); - for (arg = fn_args; arg; arg = DECL_CHAIN (arg)) - { - mark_exp_read (arg); - vec_safe_push (argvec, convert_from_reference (arg)); - } tree objfn = build_min (COMPONENT_REF, NULL_TREE, instance, DECL_NAME (callop), NULL_TREE); @@ -802,15 +839,6 @@ maybe_add_lambda_conv_op (tree type) } else { - arg = build1 (NOP_EXPR, TREE_TYPE (DECL_ARGUMENTS (callop)), - null_pointer_node); - argvec = make_tree_vector (); - argvec->quick_push (arg); - for (arg = fn_args; arg; arg = DECL_CHAIN (arg)) - { - mark_exp_read (arg); - vec_safe_push (argvec, arg); - } call = build_call_a (callop, argvec->length (), argvec->address ()); CALL_FROM_THUNK_P (call) = 1; if (MAYBE_CLASS_TYPE_P (TREE_TYPE (call))) -- 1.8.4