re PR c++/31993 (ICE with template class in variadic template class)
authorDoug Gregor <dgregor@gcc.gnu.org>
Tue, 30 Oct 2007 13:36:34 +0000 (13:36 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Tue, 30 Oct 2007 13:36:34 +0000 (13:36 +0000)
2007-10-30  Douglas Gregor  <doug.gregor@gmail.com>

PR c++/31993
PR c++/32252
* pt.c (find_parameter_packs_r): Fix typo in comment.
(convert_template_argument): Look at the pattern of a pack
expansion to determine what kind of entity we're converting.
(coerce_template_parameter_pack): When we have coerced a non-type
template parameter pack, substitute into the type of that pack.
(tsubst_pack_expansion): When our substitution of a parameter pack
is a "trivial" substitution of itself, just substitute into the
pack expansion rather than actually expanding.

2007-10-30  Douglas Gregor  <doug.gregor@gmail.com>

PR c++/31993
PR c++/32252
* g++.dg/cpp0x/pr31993.C: New
* g++.dg/cpp0x/pr32252.C: New

From-SVN: r129773

gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/pr31993.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr32252.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/crash36.C

index c9b232563197bc0af90eddf3aa442126e916b512..d5b73e797cb85efa2384c7a33241c65a2b91fb2c 100644 (file)
@@ -1,3 +1,16 @@
+2007-10-30  Douglas Gregor  <doug.gregor@gmail.com>
+
+       PR c++/31993
+       PR c++/32252
+       * pt.c (find_parameter_packs_r): Fix typo in comment.
+       (convert_template_argument): Look at the pattern of a pack
+       expansion to determine what kind of entity we're converting.
+       (coerce_template_parameter_pack): When we have coerced a non-type
+       template parameter pack, substitute into the type of that pack.
+       (tsubst_pack_expansion): When our substitution of a parameter pack
+       is a "trivial" substitution of itself, just substitute into the
+       pack expansion rather than actually expanding.
+
 2007-10-29  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/33841
index 3e8f6e585dae3a7b10193fd92d65ebf6baa3bc51..5f6e29690d2cedeb2c6a0780c6aa553571cf8a43 100644 (file)
@@ -2426,9 +2426,9 @@ struct find_parameter_pack_data
   struct pointer_set_t *visited;
 };
 
-/* Identifiers all of the argument packs that occur in a template
+/* Identifies all of the argument packs that occur in a template
    argument and appends them to the TREE_LIST inside DATA, which is a
-   find_parameter_pack_Data structure. This is a subroutine of
+   find_parameter_pack_data structure. This is a subroutine of
    make_pack_expansion and uses_parameter_packs.  */
 static tree
 find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
@@ -4668,9 +4668,9 @@ convert_template_argument (tree parm,
                           int i,
                           tree in_decl)
 {
+  tree orig_arg;
   tree val;
   int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
-  tree check_arg = arg;
 
   if (TREE_CODE (arg) == TREE_LIST
       && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
@@ -4680,24 +4680,26 @@ convert_template_argument (tree parm,
         invalid, but static members are OK.  In any
         case, grab the underlying fields/functions
         and issue an error later if required.  */
-      arg = TREE_VALUE (arg);
+      orig_arg = TREE_VALUE (arg);
       TREE_TYPE (arg) = unknown_type_node;
     }
 
+  orig_arg = arg;
+
   requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
   requires_type = (TREE_CODE (parm) == TYPE_DECL
                   || requires_tmpl_type);
 
   /* When determining whether an argument pack expansion is a template,
      look at the pattern.  */
-  if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
-    check_arg = PACK_EXPANSION_PATTERN (check_arg);
+  if (TREE_CODE (arg) == TYPE_PACK_EXPANSION)
+    arg = PACK_EXPANSION_PATTERN (arg);
 
   is_tmpl_type = 
-    ((TREE_CODE (check_arg) == TEMPLATE_DECL
-      && TREE_CODE (DECL_TEMPLATE_RESULT (check_arg)) == TYPE_DECL)
-     || TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
-     || TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE);
+    ((TREE_CODE (arg) == TEMPLATE_DECL
+      && TREE_CODE (DECL_TEMPLATE_RESULT (arg)) == TYPE_DECL)
+     || TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
+     || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE);
 
   if (is_tmpl_type
       && (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
@@ -4710,12 +4712,13 @@ convert_template_argument (tree parm,
       && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
     {
       pedwarn ("to refer to a type member of a template parameter, "
-              "use %<typename %E%>", arg);
+              "use %<typename %E%>", orig_arg);
 
-      arg = make_typename_type (TREE_OPERAND (arg, 0),
-                               TREE_OPERAND (arg, 1),
-                               typename_type,
-                               complain & tf_error);
+      orig_arg = make_typename_type (TREE_OPERAND (arg, 0),
+                                    TREE_OPERAND (arg, 1),
+                                    typename_type,
+                                    complain & tf_error);
+      arg = orig_arg;
       is_type = 1;
     }
   if (is_type != requires_type)
@@ -4730,11 +4733,11 @@ convert_template_argument (tree parm,
              if (is_type)
                error ("  expected a constant of type %qT, got %qT",
                       TREE_TYPE (parm),
-                      (is_tmpl_type ? DECL_NAME (arg) : arg));
+                      (is_tmpl_type ? DECL_NAME (arg) : orig_arg));
              else if (requires_tmpl_type)
-               error ("  expected a class template, got %qE", arg);
+               error ("  expected a class template, got %qE", orig_arg);
              else
-               error ("  expected a type, got %qE", arg);
+               error ("  expected a type, got %qE", orig_arg);
            }
        }
       return error_mark_node;
@@ -4749,7 +4752,7 @@ convert_template_argument (tree parm,
          if (is_tmpl_type)
            error ("  expected a type, got %qT", DECL_NAME (arg));
          else
-           error ("  expected a class template, got %qT", arg);
+           error ("  expected a class template, got %qT", orig_arg);
        }
       return error_mark_node;
     }
@@ -4767,19 +4770,13 @@ convert_template_argument (tree parm,
              tree parmparm = DECL_INNERMOST_TEMPLATE_PARMS (parm);
              tree argparm;
 
-              check_arg = arg;
-              /* When determining whether a pack expansion is a template,
-                 look at the pattern.  */
-              if (TREE_CODE (check_arg) == TYPE_PACK_EXPANSION)
-                check_arg = PACK_EXPANSION_PATTERN (check_arg);
-
-              argparm = DECL_INNERMOST_TEMPLATE_PARMS (check_arg);
+              argparm = DECL_INNERMOST_TEMPLATE_PARMS (arg);
 
              if (coerce_template_template_parms (parmparm, argparm,
                                                  complain, in_decl,
                                                  args))
                {
-                 val = arg;
+                 val = orig_arg;
 
                  /* TEMPLATE_TEMPLATE_PARM node is preferred over
                     TEMPLATE_DECL.  */
@@ -4788,9 +4785,9 @@ convert_template_argument (tree parm,
                       if (DECL_TEMPLATE_TEMPLATE_PARM_P (val))
                         val = TREE_TYPE (val);
                       else if (TREE_CODE (val) == TYPE_PACK_EXPANSION
-                               && DECL_TEMPLATE_TEMPLATE_PARM_P (check_arg))
+                               && DECL_TEMPLATE_TEMPLATE_PARM_P (arg))
                         {
-                          val = TREE_TYPE (check_arg);
+                          val = TREE_TYPE (arg);
                           val = make_pack_expansion (val);
                         }
                     }
@@ -4803,7 +4800,7 @@ convert_template_argument (tree parm,
                             "template parameter list for %qD",
                             i + 1, in_decl);
                      error ("  expected a template of type %qD, got %qD",
-                            parm, arg);
+                            parm, orig_arg);
                    }
 
                  val = error_mark_node;
@@ -4811,7 +4808,7 @@ convert_template_argument (tree parm,
            }
        }
       else
-       val = arg;
+       val = orig_arg;
       /* We only form one instance of each template specialization.
         Therefore, if we use a non-canonical variant (i.e., a
         typedef), any future messages referring to the type will use
@@ -4827,7 +4824,7 @@ convert_template_argument (tree parm,
       if (invalid_nontype_parm_type_p (t, complain))
        return error_mark_node;
 
-      if (!uses_template_parms (arg) && !uses_template_parms (t))
+      if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
        /* We used to call digest_init here.  However, digest_init
           will report errors, which we don't want when complain
           is zero.  More importantly, digest_init will try too
@@ -4838,14 +4835,14 @@ convert_template_argument (tree parm,
           conversions can occur is part of determining which
           function template to call, or whether a given explicit
           argument specification is valid.  */
-       val = convert_nontype_argument (t, arg);
+       val = convert_nontype_argument (t, orig_arg);
       else
-       val = arg;
+       val = orig_arg;
 
       if (val == NULL_TREE)
        val = error_mark_node;
       else if (val == error_mark_node && (complain & tf_error))
-       error ("could not convert template argument %qE to %qT",  arg, t);
+       error ("could not convert template argument %qE to %qT",  orig_arg, t);
     }
 
   return val;
@@ -4959,7 +4956,8 @@ coerce_template_parameter_pack (tree parms,
   else
     {
       argument_pack = make_node (NONTYPE_ARGUMENT_PACK);
-      TREE_TYPE (argument_pack) = TREE_TYPE (TREE_VALUE (parm));
+      TREE_TYPE (argument_pack) 
+        = tsubst (TREE_TYPE (TREE_VALUE (parm)), args, complain, in_decl);
       TREE_CONSTANT (argument_pack) = 1;
     }
 
@@ -7108,6 +7106,22 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
          return result;
        }
 
+      if (arg_pack
+          && TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
+          && PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0)))
+        {
+          tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
+          tree pattern = PACK_EXPANSION_PATTERN (expansion);
+          if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
+              || (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
+            /* The argument pack that the parameter maps to is just an
+               expansion of the parameter itself, such as one would
+               find in the implicit typedef of a class inside the
+               class itself.  Consider this parameter "unsubstituted",
+               so that we will maintain the outer pack expansion.  */
+            arg_pack = NULL_TREE;
+        }
+          
       if (arg_pack)
         {
           int my_len = 
index 19ae6a8e97c7226d8dcd1176e8dd408a1fd84b32..0956218a9817d711c61f559e89c24af250b1e182 100644 (file)
@@ -1,3 +1,10 @@
+2007-10-30  Douglas Gregor  <doug.gregor@gmail.com>
+
+       PR c++/31993
+       PR c++/32252
+       * g++.dg/cpp0x/pr31993.C: New
+       * g++.dg/cpp0x/pr32252.C: New
+
 2007-10-30  Jakub Jelinek  <jakub@redhat.com>
 
        PR tree-optimization/33723
@@ -8,6 +15,7 @@
        * gcc.c-torture/execute/20071030-1.c: New testcase copied from
        gcc.target/i386/loop-3.c.
 
+>>>>>>> .r129772
 2007-10-30  Revital Eres  <eres@il.ibm.com>
 
        * testsuite/gcc.dg/vect/pr33866.c: Require vect_long.
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr31993.C b/gcc/testsuite/g++.dg/cpp0x/pr31993.C
new file mode 100644 (file)
index 0000000..94fb9cc
--- /dev/null
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+template<typename...> struct A;
+
+template<template<int> class... T> struct A<T<0>...>
+{
+  template<int> struct B {};
+  B<0> b;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr32252.C b/gcc/testsuite/g++.dg/cpp0x/pr32252.C
new file mode 100644 (file)
index 0000000..543dc88
--- /dev/null
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+int x[5];
+
+template<int M, int N, int (&... p)[N]> struct A;
+
+template<int M> struct A<M,5,x> {};
+
+A<0,5,x> a;  
index 1e5ab8f25625e34da2824c34bd2fb113849e1d6d..e73e928350d4f6177eabe3437391886f9304b9ca 100644 (file)
@@ -5,7 +5,7 @@
 template <typename... T> struct A      // { dg-error "does not include variadic templates" }
 {
   static T &t;                         // { dg-error "not expanded with|T" }
-  static const int i = sizeof (++t);   // { dg-error "invalid use of template type parameter" }
+  static const int i = sizeof (++t);
 };
 
 int x[A <int>::i];     // { dg-error "is not an integral constant-expression" }