public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* C++ PATCH for c++/84126, ICE with variadic generic lambda
@ 2018-02-01 18:30 Jason Merrill
  0 siblings, 0 replies; only message in thread
From: Jason Merrill @ 2018-02-01 18:30 UTC (permalink / raw)
  To: gcc-patches List

[-- Attachment #1: Type: text/plain, Size: 878 bytes --]

In a partial instantiation of a pack expansion we can have a situation
where we have arguments for some of the packs but not all.  We deal
with this by leaving the pattern uninstantiated and remembering the
arguments passed to the partial specialization so we can use them
later in doing a full instantiation.  My patch for 84036 started to
use this mechanism when we don't have the expansion of a function
parameter pack, but it broke for this testcase because when we went to
look for the local specialization of the function parameter pack, we
were looking for a specialization of the original parameter pack, but
local_specializations only knows about the partially instantiated
parameter pack.  Fixed by remembering in this situation what function
we are using parameter packs from, so we can set up the appropriate
mapping.

Tested x86_64-pc-linux-gnu, applying to trunk.

[-- Attachment #2: 84126.diff --]
[-- Type: text/plain, Size: 3857 bytes --]

commit ad4789988c130a58f6e3c885cfa10e02b8fa0c77
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Jan 31 17:35:59 2018 -0500

            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.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8983674881d..5f14e514638 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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)			\
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9516be893aa..ca73bb18d97 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
index 00000000000..1b3a6442efd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic9.C
@@ -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);
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2018-02-01 18:30 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-02-01 18:30 C++ PATCH for c++/84126, ICE with variadic generic lambda Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).