Re: C++ PATCH for c++/67164 (error with variadic templates)

2016-07-19 Thread Jason Merrill
On Thu, Mar 3, 2016 at 8:41 PM, Jason Merrill  wrote:
> When we instantiate an element of a pack expansion, we replace the argument
> pack in the template argument vec with an ARGUMENT_PACK_SELECT which
> indicates the desired element of the vec.  If the args have been used to
> instantiate other templates as well, the args of those instances get
> modified as well, which can lead to strange results when we run into
> ARGUMENT_PACK_SELECT in inappropriate places.  This patch fixes this issue
> by making a copy of the template args before we start messing with them.

...so we don't need to deal with ARGUMENT_PACK_SELECT in the hash
tables anymore.
commit b5cb8944e6feb6f4c53170c5d58bc50e4fa5503a
Author: Jason Merrill 
Date:   Tue Jul 19 12:49:53 2016 -0400

PR c++/67164 - clean up dead code

* pt.c (iterative_hash_template_arg, template_args_equal): Don't
handle ARGUMENT_PACK_SELECT.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 916fd7b..7c7024c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1704,9 +1704,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
 STRIP_NOPS (arg);
 
   if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT)
-/* We can get one of these when re-hashing a previous entry in the middle
-   of substituting into a pack expansion.  Just look through it.  */
-arg = ARGUMENT_PACK_SELECT_FROM_PACK (arg);
+gcc_unreachable ();
 
   code = TREE_CODE (arg);
   tclass = TREE_CODE_CLASS (code);
@@ -7894,17 +7892,7 @@ template_args_equal (tree ot, tree nt)
   return 1;
 }
   else if (ot && TREE_CODE (ot) == ARGUMENT_PACK_SELECT)
-{
-  /* We get here probably because we are in the middle of substituting
- into the pattern of a pack expansion. In that case the
-ARGUMENT_PACK_SELECT temporarily replaces the pack argument we are
-interested in. So we want to use the initial pack argument for
-the comparison.  */
-  ot = ARGUMENT_PACK_SELECT_FROM_PACK (ot);
-  if (nt && TREE_CODE (nt) == ARGUMENT_PACK_SELECT)
-   nt = ARGUMENT_PACK_SELECT_FROM_PACK (nt);
-  return template_args_equal (ot, nt);
-}
+gcc_unreachable ();
   else if (TYPE_P (nt))
 {
   if (!TYPE_P (ot))


C++ PATCH for c++/67164 (error with variadic templates)

2016-03-03 Thread Jason Merrill
When we instantiate an element of a pack expansion, we replace the 
argument pack in the template argument vec with an ARGUMENT_PACK_SELECT 
which indicates the desired element of the vec.  If the args have been 
used to instantiate other templates as well, the args of those instances 
get modified as well, which can lead to strange results when we run into 
ARGUMENT_PACK_SELECT in inappropriate places.  This patch fixes this 
issue by making a copy of the template args before we start messing with 
them.


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

commit e32e331a8f6ada0c20ff13240bac030020f627bf
Author: Jason Merrill 
Date:   Wed Mar 2 09:17:20 2016 -0500

	PR c++/67164

	* pt.c (copy_template_args): New.
	(tsubst_pack_expansion): Use it.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b3681be..c5b9201 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -178,6 +178,7 @@ static int check_cv_quals_for_unify (int, tree, tree);
 static void template_parm_level_and_index (tree, int*, int*);
 static int unify_pack_expansion (tree, tree, tree,
  tree, unification_kind_t, bool, bool);
+static tree copy_template_args (tree);
 static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
 static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
@@ -11037,11 +11038,12 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   /* For each argument in each argument pack, substitute into the
  pattern.  */
   result = make_tree_vec (len);
+  tree elem_args = copy_template_args (args);
   for (i = 0; i < len; ++i)
 {
   t = gen_elem_of_pack_expansion_instantiation (pattern, packs,
 		i,
-		args, complain,
+		elem_args, complain,
 		in_decl);
   TREE_VEC_ELT (result, i) = t;
   if (t == error_mark_node)
@@ -11136,6 +11138,32 @@ make_argument_pack (tree vec)
   return pack;
 }
 
+/* Return an exact copy of template args T that can be modified
+   independently.  */
+
+static tree
+copy_template_args (tree t)
+{
+  if (t == error_mark_node)
+return t;
+
+  int len = TREE_VEC_LENGTH (t);
+  tree new_vec = make_tree_vec (len);
+
+  for (int i = 0; i < len; ++i)
+{
+  tree elt = TREE_VEC_ELT (t, i);
+  if (elt && TREE_CODE (elt) == TREE_VEC)
+	elt = copy_template_args (elt);
+  TREE_VEC_ELT (new_vec, i) = elt;
+}
+
+  NON_DEFAULT_TEMPLATE_ARGS_COUNT (new_vec)
+= NON_DEFAULT_TEMPLATE_ARGS_COUNT (t);
+
+  return new_vec;
+}
+
 /* Substitute ARGS into the vector or list of template arguments T.  */
 
 static tree
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic-tuple2.C b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple2.C
new file mode 100644
index 000..43c00e9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic-tuple2.C
@@ -0,0 +1,29 @@
+// PR c++/67164
+// { dg-do compile { target c++11 } }
+
+#include 
+
+namespace detail {
+template 
+struct fast_and
+: std::is_same>
+{ };
+}
+
+template 
+struct tuple {
+tuple() { }
+
+template ::value...>::value
+>::type>
+tuple(Yn&& ...yn) { }
+
+template ::value...>::value
+>::type>
+tuple(tuple const& other) { }
+};
+
+tuple> t{};
+tuple> copy = t;