re PR c++/67164 (ICE: tree check: expected class ‘expression’, have ‘exceptional...
authorJason Merrill <jason@redhat.com>
Fri, 4 Mar 2016 01:45:43 +0000 (20:45 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 4 Mar 2016 01:45:43 +0000 (20:45 -0500)
PR c++/67164

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

From-SVN: r233954

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

index 6eae6fd919714eb07f52e3e52d1fc44ab4a5e9de..e68382c3440c686b66b57cd411573b262fb71d47 100644 (file)
@@ -1,5 +1,9 @@
 2016-03-03  Jason Merrill  <jason@redhat.com>
 
+       PR c++/67164
+       * pt.c (copy_template_args): New.
+       (tsubst_pack_expansion): Use it.
+
        * call.c (build_aggr_conv): Use get_nsdmi.
 
        PR c++/51406
index b3681be9e43879785c4e45e1a2e9b31dba5c801b..c5b92013830bd539117522bf938bd60411080a73 100644 (file)
@@ -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 (file)
index 0000000..43c00e9
--- /dev/null
@@ -0,0 +1,29 @@
+// PR c++/67164
+// { dg-do compile { target c++11 } }
+
+#include <type_traits>
+
+namespace detail {
+    template <bool ...b>
+    struct fast_and
+        : std::is_same<fast_and<b...>, fast_and<(b, true)...>>
+    { };
+}
+
+template <typename ...Xn>
+struct tuple {
+    tuple() { }
+
+    template <typename ...Yn, typename = typename std::enable_if<
+        detail::fast_and<std::is_constructible<Xn, Yn&&>::value...>::value
+    >::type>
+    tuple(Yn&& ...yn) { }
+
+    template <typename ...Yn, typename = typename std::enable_if<
+        detail::fast_and<std::is_constructible<Xn, Yn const&>::value...>::value
+    >::type>
+    tuple(tuple<Yn...> const& other) { }
+};
+
+tuple<tuple<>> t{};
+tuple<tuple<>> copy = t;