This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Fix PRs c++/31993 and c++/32252 (variadic templates)


PRs c++/31993 and c++/32252 (both P1s) are ice-on-valid-code failures
in the handling of variadic templates. PR 31993 concerns member
templates of variadic templates, while PR 32252 concerns non-type
template parameter packs whose types involve other template
parameters. Both problems concern substitution of argument packs, so
I've addressed both PRs with one patch.

Tested powerpc-apple-darwin8.10.0; no regressions in the C++ front end
or libstdc++.

Okay for mainline?

:ADDPATCH c++:

- Doug

2007-07-04 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): We our substitution of a parameter pack
	is a "trivial" substitution of itself, just substitute into the
	pack expansion rather than actually expanding.
	(tsubst): Dig out the pattern of a pack expansion when examining
	the structure of the expansion.

2007-07-04 Douglas Gregor <doug.gregor@gmail.com>

	* g++.dg/cpp0x/pr31993.C: New
	* g++.dg/cpp0x/pr32252.C: New
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 126265)
+++ cp/pt.c	(working copy)
@@ -2389,9 +2389,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)
@@ -4630,7 +4630,7 @@ convert_template_argument (tree parm,
 {
   tree val;
   int is_type, requires_type, is_tmpl_type, requires_tmpl_type;
-  tree check_arg = arg;
+  tree check_arg;
 
   if (TREE_CODE (arg) == TREE_LIST
       && TREE_CODE (TREE_VALUE (arg)) == OFFSET_REF)
@@ -4644,6 +4644,8 @@ convert_template_argument (tree parm,
       TREE_TYPE (arg) = unknown_type_node;
     }
 
+  check_arg = arg;
+
   requires_tmpl_type = TREE_CODE (parm) == TEMPLATE_DECL;
   requires_type = (TREE_CODE (parm) == TYPE_DECL
 		   || requires_tmpl_type);
@@ -4664,18 +4666,24 @@ convert_template_argument (tree parm,
 	  || TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE))
     arg = TYPE_STUB_DECL (arg);
 
-  is_type = TYPE_P (arg) || is_tmpl_type;
+  if (is_tmpl_type
+      && (TREE_CODE (check_arg) == TEMPLATE_TEMPLATE_PARM
+	  || TREE_CODE (check_arg) == UNBOUND_CLASS_TEMPLATE))
+    check_arg = TYPE_STUB_DECL (check_arg);
+
+  is_type = TYPE_P (check_arg) || is_tmpl_type;
 
-  if (requires_type && ! is_type && TREE_CODE (arg) == SCOPE_REF
-      && TREE_CODE (TREE_OPERAND (arg, 0)) == TEMPLATE_TYPE_PARM)
+  if (requires_type && ! is_type && TREE_CODE (check_arg) == SCOPE_REF
+      && TREE_CODE (TREE_OPERAND (check_arg, 0)) == TEMPLATE_TYPE_PARM)
     {
       pedwarn ("to refer to a type member of a template parameter, "
-	       "use %<typename %E%>", arg);
+	       "use %<typename %E%>", check_arg);
 
-      arg = make_typename_type (TREE_OPERAND (arg, 0),
-				TREE_OPERAND (arg, 1),
+      arg = make_typename_type (TREE_OPERAND (check_arg, 0),
+				TREE_OPERAND (check_arg, 1),
 				typename_type,
 				complain & tf_error);
+      check_arg = arg;
       is_type = 1;
     }
   if (is_type != requires_type)
@@ -4718,21 +4726,15 @@ convert_template_argument (tree parm,
     {
       if (requires_tmpl_type)
 	{
-	  if (TREE_CODE (TREE_TYPE (arg)) == UNBOUND_CLASS_TEMPLATE)
+	  if (TREE_CODE (TREE_TYPE (check_arg)) == UNBOUND_CLASS_TEMPLATE)
 	    /* The number of argument required is not known yet.
 	       Just accept it for now.  */
-	    val = TREE_TYPE (arg);
+	    val = TREE_TYPE (check_arg);
 	  else
 	    {
 	      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);
 
 	      if (coerce_template_template_parms (parmparm, argparm,
@@ -4763,7 +4765,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, check_arg);
 		    }
 
 		  val = error_mark_node;
@@ -4918,7 +4920,8 @@ coerce_template_parameter_pack (tree par
   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;
     }
 
@@ -6998,6 +7001,22 @@ tsubst_pack_expansion (tree t, tree args
 	  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 = 
@@ -8607,6 +8626,12 @@ tsubst (tree t, tree args, tsubst_flags_
 		if (argvec == error_mark_node)
 		  return error_mark_node;
 
+                /* We can get a pack expansion here when we are
+                   instantiating a member template and ARG is a pack
+                   expansion from the outer template.  */
+                if (PACK_EXPANSION_P (arg))
+                  arg = PACK_EXPANSION_PATTERN (arg);
+
 		/* We can get a TEMPLATE_TEMPLATE_PARM here when we
 		   are resolving nested-types in the signature of a
 		   member function templates.  Otherwise ARG is a
Index: testsuite/g++.dg/cpp0x/pr31993.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr31993.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr31993.C	(revision 0)
@@ -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;
+};
Index: testsuite/g++.dg/cpp0x/pr32252.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr32252.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/pr32252.C	(revision 0)
@@ -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 Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]