re PR c++/49672 ([C++0x] Internal error when passing variadic template args to a...
authorJason Merrill <jason@redhat.com>
Mon, 11 Jul 2011 21:03:19 +0000 (17:03 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 11 Jul 2011 21:03:19 +0000 (17:03 -0400)
PR c++/49672
* pt.c (extract_fnparm_pack): Split out from...
(make_fnparm_pack): ...here.
(instantiate_decl): Handle non-pack parms after a pack.
* semantics.c (maybe_add_lambda_conv_op): Don't in a template.

From-SVN: r176183

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C [new file with mode: 0644]

index a6df4fb6fac2ae4242e3896223e49c4fbe281299..6d44bf2f5efc1fb6b1797e6d5f72c6ad69c21f67 100644 (file)
@@ -1,5 +1,11 @@
 2011-07-11  Jason Merrill  <jason@redhat.com>
 
+       PR c++/49672
+       * pt.c (extract_fnparm_pack): Split out from...
+       (make_fnparm_pack): ...here.
+       (instantiate_decl): Handle non-pack parms after a pack.
+       * semantics.c (maybe_add_lambda_conv_op): Don't in a template.
+
        * decl2.c (decl_constant_var_p): Use decl_maybe_constant_var_p.
 
        PR c++/44609
index 7c735ef75b7771004ea670ab133c413dc9e7c70d..33b5b5fab0c59abadce9091384ee804533afdc7b 100644 (file)
@@ -8711,11 +8711,12 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
   return r;
 }
 
-/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
-   NONTYPE_ARGUMENT_PACK.  */
+/* Given a function parameter pack TMPL_PARM and some function parameters
+   instantiated from it at *SPEC_P, return a NONTYPE_ARGUMENT_PACK of them
+   and set *SPEC_P to point at the next point in the list.  */
 
 static tree
-make_fnparm_pack (tree spec_parm)
+extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
 {
   /* Collect all of the extra "packed" parameters into an
      argument pack.  */
@@ -8723,11 +8724,18 @@ make_fnparm_pack (tree spec_parm)
   tree parmtypevec;
   tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
   tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
-  int i, len = list_length (spec_parm);
+  tree spec_parm = *spec_p;
+  int i, len;
+
+  for (len = 0; spec_parm; ++len, spec_parm = TREE_CHAIN (spec_parm))
+    if (tmpl_parm
+       && !function_parameter_expanded_from_pack_p (spec_parm, tmpl_parm))
+      break;
 
   /* Fill in PARMVEC and PARMTYPEVEC with all of the parameters.  */
   parmvec = make_tree_vec (len);
   parmtypevec = make_tree_vec (len);
+  spec_parm = *spec_p;
   for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
     {
       TREE_VEC_ELT (parmvec, i) = spec_parm;
@@ -8738,9 +8746,19 @@ make_fnparm_pack (tree spec_parm)
   SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
   SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
   TREE_TYPE (argpack) = argtypepack;
+  *spec_p = spec_parm;
 
   return argpack;
-}        
+}
+
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+   NONTYPE_ARGUMENT_PACK.  */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+  return extract_fnparm_pack (NULL_TREE, &spec_parm);
+}
 
 /* Substitute ARGS into T, which is an pack expansion
    (i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
@@ -17830,21 +17848,21 @@ instantiate_decl (tree d, int defer_ok,
          spec_parm = skip_artificial_parms_for (d, spec_parm);
          tmpl_parm = skip_artificial_parms_for (subst_decl, tmpl_parm);
        }
-      while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+      for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
        {
-         register_local_specialization (spec_parm, tmpl_parm);
-         tmpl_parm = DECL_CHAIN (tmpl_parm);
-         spec_parm = DECL_CHAIN (spec_parm);
+         if (!FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+           {
+             register_local_specialization (spec_parm, tmpl_parm);
+             spec_parm = DECL_CHAIN (spec_parm);
+           }
+         else
+           {
+             /* Register the (value) argument pack as a specialization of
+                TMPL_PARM, then move on.  */
+             tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm);
+             register_local_specialization (argpack, tmpl_parm);
+           }
        }
-      if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
-        {
-          /* Register the (value) argument pack as a specialization of
-             TMPL_PARM, then move on.  */
-         tree argpack = make_fnparm_pack (spec_parm);
-          register_local_specialization (argpack, tmpl_parm);
-          tmpl_parm = DECL_CHAIN (tmpl_parm);
-         spec_parm = NULL_TREE;
-        }
       gcc_assert (!spec_parm);
 
       /* Substitute into the body of the function.  */
index 84b0dd8559fc1822072e022ff97fec6cbe692e5f..fd00e2976da0a15f93e88c75540f1cb1ccecdafe 100644 (file)
@@ -8808,6 +8808,9 @@ maybe_add_lambda_conv_op (tree type)
   if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
     return;
 
+  if (processing_template_decl)
+    return;
+
   stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
                                  FUNCTION_ARG_CHAIN (callop));
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C
new file mode 100644 (file)
index 0000000..f17b336
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/49672
+// { dg-options -std=c++0x }
+
+template<typename ... Args>
+static void foo()
+{
+  [](Args..., int x) {
+    x;
+  };
+}
+
+int main()
+{
+  foo();
+}