PR c++/84126 - ICE with variadic generic lambda
authorJason Merrill <jason@redhat.com>
Thu, 1 Feb 2018 18:44:41 +0000 (13:44 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 1 Feb 2018 18:44:41 +0000 (13:44 -0500)
PR c++/84036
PR c++/82249
* pt.c (tsubst_pack_expansion): Handle function parameter_packs in
PACK_EXPANSION_EXTRA_ARGS.

From-SVN: r257307

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C [new file with mode: 0644]

index 8fc9042ea012b2a2c9a302a75a0451eecd67d2d1..897774e43f7a21b3cf2d205143c76548137f4cea 100644 (file)
@@ -1,3 +1,11 @@
+2018-02-01  Jason Merrill  <jason@redhat.com>
+
+       PR c++/84126 - ICE with variadic generic lambda
+       PR c++/84036
+       PR c++/82249
+       * pt.c (tsubst_pack_expansion): Handle function parameter_packs in
+       PACK_EXPANSION_EXTRA_ARGS.
+
 2018-02-01  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/83796
index 8983674881d4a9fed3673a82585fc57759b05919..5f14e51463836e340cbdf54059d0b65457d600fa 100644 (file)
@@ -3496,7 +3496,11 @@ extern void decl_shadowed_for_var_insert (tree, tree);
     : &TYPE_MIN_VALUE_RAW (TYPE_PACK_EXPANSION_CHECK (NODE)))
 
 /* Any additional template args to be applied when substituting into
-   the pattern, set by tsubst_pack_expansion for partial instantiations.  */
+   the pattern, set by tsubst_pack_expansion for partial instantiations.
+   If this is a TREE_LIST, the TREE_VALUE of the first element is the
+   usual template argument TREE_VEC, and the TREE_PURPOSE of later elements
+   are enclosing functions that provided function parameter packs we'll need
+   to map appropriately.  */
 #define PACK_EXPANSION_EXTRA_ARGS(NODE)                \
   *(TREE_CODE (NODE) == TYPE_PACK_EXPANSION    \
     ? &TYPE_MAX_VALUE_RAW (NODE)                       \
index 9516be893aae5baac579fa5bc57832b56221d3ae..ca73bb18d973b496bd373aa6ce841405f23f6d9f 100644 (file)
@@ -11439,7 +11439,20 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   pattern = PACK_EXPANSION_PATTERN (t);
 
   /* Add in any args remembered from an earlier partial instantiation.  */
-  args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
+  tree extra = PACK_EXPANSION_EXTRA_ARGS (t);
+  if (extra && TREE_CODE (extra) == TREE_LIST)
+    {
+      /* The partial instantiation involved function parameter packs; map
+         from the general template to our current context.  */
+      for (tree fns = TREE_CHAIN (extra); fns; fns = TREE_CHAIN (fns))
+       {
+         tree fn = TREE_PURPOSE (fns);
+         tree inst = enclosing_instantiation_of (fn);
+         register_parameter_specializations (fn, inst);
+       }
+      extra = TREE_VALUE (extra);
+    }
+  args = add_to_template_args (extra, args);
 
   levels = TMPL_ARGS_DEPTH (args);
 
@@ -11610,7 +11623,28 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
         have values for all the packs.  So remember these until then.  */
 
       t = make_pack_expansion (pattern, complain);
-      PACK_EXPANSION_EXTRA_ARGS (t) = args;
+      tree extra = args;
+      if (unsubstituted_fn_pack)
+       {
+         /* For function parameter packs it's more complicated; we need to
+            remember which enclosing function(s) provided them to this pack
+            expansion so we can map their parameters to the parameters of a
+            later full instantiation.  */
+         tree fns = NULL_TREE;
+         for (tree p = packs; p; p = TREE_CHAIN (p))
+           {
+             tree parm = TREE_PURPOSE (p);
+             if (TREE_CODE (parm) != PARM_DECL)
+               continue;
+             parm = DECL_CONTEXT (parm);
+             if (purpose_member (parm, fns))
+               continue;
+             fns = tree_cons (parm, NULL_TREE, fns);
+           }
+         if (fns)
+           extra = tree_cons (NULL_TREE, extra, fns);
+       }
+      PACK_EXPANSION_EXTRA_ARGS (t) = extra;
       return t;
     }
   else if (unsubstituted_packs)
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C
new file mode 100644 (file)
index 0000000..1b3a644
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/84126
+// { dg-do compile { target c++14 } }
+
+template <class... Ts>
+void sink(Ts...);
+
+template <typename T>
+int bar(T&); // ICE with reference, work with just T
+
+template <typename T >
+void foo(T){
+  [](auto ... k){
+    sink (bar(k) ...);
+  }(0);
+}
+
+int main() {
+  foo(0);
+}