Patchwork [2/4] Don't generate lambda conversion op if arglist has parameter pack.

login
register
mail settings
Submitter Adam Butcher
Date Aug. 27, 2013, 7:42 p.m.
Message ID <1377632573-14453-3-git-send-email-adam@jessamine.co.uk>
Download mbox | patch
Permalink /patch/270209/
State New
Headers show

Comments

Adam Butcher - Aug. 27, 2013, 7:42 p.m.
* 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(-)
Jason Merrill - Sept. 1, 2013, 8:28 p.m.
On 08/27/2013 03:42 PM, Adam Butcher wrote:
> +	if (FUNCTION_PARAMETER_PACK_P (src))
> +	  return;

Yeah, in the case of a parameter pack we want to pass a pack expansion.

Jason

Patch

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)))