pt.c (tsubst_copy): Cope with tsubst_pack_expansion returning a pack expansion...
authorDouglas Gregor <doug.gregor@gmail.com>
Thu, 27 Mar 2008 14:31:47 +0000 (14:31 +0000)
committerDoug Gregor <dgregor@gcc.gnu.org>
Thu, 27 Mar 2008 14:31:47 +0000 (14:31 +0000)
2008-03-27  Douglas Gregor  <doug.gregor@gmail.com>

* pt.c (tsubst_copy) <case SIZEOF_EXPR>: Cope with
tsubst_pack_expansion returning a pack expansion, or a TREE_VEC
ending in a pack expansion, both of which can occur when
substituting into a nested template.
(tsubst_copy_and_build) <case SIZEOF_EXPR>: When we're
instantiating the sizeof...(X) form, make tsubst_copy do the work.
* parser.c (cp_parser_template_parameter): Deal with unnamed
non-type template parameter packs identified by pack expansions in
the parameter type.

2008-03-27  Douglas Gregor  <doug.gregor@gmail.com>

       * g++.dg/cpp0x/variadic91.C: New.

From-SVN: r133642

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

index 447bfc04117cd0b62052f3a20897bb02d9fcf4f8..68c17fd3ab6d99bf726dd4245216c61e0abef925 100644 (file)
@@ -1,3 +1,15 @@
+2008-03-27  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * pt.c (tsubst_copy) <case SIZEOF_EXPR>: Cope with
+       tsubst_pack_expansion returning a pack expansion, or a TREE_VEC
+       ending in a pack expansion, both of which can occur when
+       substituting into a nested template.
+       (tsubst_copy_and_build) <case SIZEOF_EXPR>: When we're
+       instantiating the sizeof...(X) form, make tsubst_copy do the work.
+       * parser.c (cp_parser_template_parameter): Deal with unnamed
+       non-type template parameter packs identified by pack expansions in
+       the parameter type.
+
 2008-03-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/35546
index 8a9c3e2956373d80d6a15ee6ad34c14594803737..87b353e08c02a76fb69b0c37f342d4ccc54a0454 100644 (file)
@@ -9435,29 +9435,41 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
       maybe_warn_variadic_templates ();
       
       *is_parameter_pack = true;
+    }
+  /* We might end up with a pack expansion as the type of the non-type
+     template parameter, in which case this is a non-type template
+     parameter pack.  */
+  else if (parameter_declarator
+          && parameter_declarator->decl_specifiers.type
+          && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type))
+    {
+      *is_parameter_pack = true;
+      parameter_declarator->decl_specifiers.type = 
+       PACK_EXPANSION_PATTERN (parameter_declarator->decl_specifiers.type);
+    }
 
+  if (*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+    {
       /* Parameter packs cannot have default arguments.  However, a
         user may try to do so, so we'll parse them and give an
         appropriate diagnostic here.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
-       {
-         /* Consume the `='.  */
-         cp_lexer_consume_token (parser->lexer);
 
-         /* Find the name of the parameter pack.  */     
-         id_declarator = parameter_declarator->declarator;
-         while (id_declarator && id_declarator->kind != cdk_id)
-           id_declarator = id_declarator->declarator;
-         
-         if (id_declarator && id_declarator->kind == cdk_id)
-           error ("template parameter pack %qD cannot have a default argument",
-                  id_declarator->u.id.unqualified_name);
-         else
-           error ("template parameter pack cannot have a default argument");
-
-          /* Parse the default argument, but throw away the result.  */
-          cp_parser_default_argument (parser, /*template_parm_p=*/true);
-       }
+      /* Consume the `='.  */
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* Find the name of the parameter pack.  */     
+      id_declarator = parameter_declarator->declarator;
+      while (id_declarator && id_declarator->kind != cdk_id)
+       id_declarator = id_declarator->declarator;
+      
+      if (id_declarator && id_declarator->kind == cdk_id)
+       error ("template parameter pack %qD cannot have a default argument",
+              id_declarator->u.id.unqualified_name);
+      else
+       error ("template parameter pack cannot have a default argument");
+      
+      /* Parse the default argument, but throw away the result.  */
+      cp_parser_default_argument (parser, /*template_parm_p=*/true);
     }
 
   parm = grokdeclarator (parameter_declarator->declarator,
index 6f7efa6e55ea5e924565db784081cc4b78d6433d..6954a1bee9ee1cd0866e446473f3e76c763b691f 100644 (file)
@@ -9916,9 +9916,30 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
           /* We only want to compute the number of arguments.  */
           tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
                                                 complain, in_decl);
+         int len;
+
+         if (TREE_CODE (expanded) == TREE_VEC)
+           len = TREE_VEC_LENGTH (expanded);
+
          if (expanded == error_mark_node)
            return error_mark_node;
-          return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
+         else if (PACK_EXPANSION_P (expanded)
+                  || (TREE_CODE (expanded) == TREE_VEC
+                      && len > 0
+                      && PACK_EXPANSION_P (TREE_VEC_ELT (expanded, len-1))))
+           {
+             if (TREE_CODE (expanded) == TREE_VEC)
+               expanded = TREE_VEC_ELT (expanded, len - 1);
+
+             if (TYPE_P (expanded))
+               return cxx_sizeof_or_alignof_type (expanded, SIZEOF_EXPR, 
+                                                  complain & tf_error);
+             else
+               return cxx_sizeof_or_alignof_expr (expanded, SIZEOF_EXPR,
+                                                   complain & tf_error);
+           }
+         else
+           return build_int_cst (size_type_node, len);
         }
       /* Fall through */
 
@@ -10918,14 +10939,7 @@ tsubst_copy_and_build (tree t,
 
     case SIZEOF_EXPR:
       if (PACK_EXPANSION_P (TREE_OPERAND (t, 0)))
-        {
-          /* We only want to compute the number of arguments.  */
-          tree expanded = tsubst_pack_expansion (TREE_OPERAND (t, 0), args,
-                                                complain, in_decl);
-         if (expanded == error_mark_node)
-           return error_mark_node;
-          return build_int_cst (size_type_node, TREE_VEC_LENGTH (expanded));
-        }
+       return tsubst_copy (t, args, complain, in_decl);
       /* Fall through */
       
     case ALIGNOF_EXPR:
@@ -12920,7 +12934,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
            tree parmvec = TYPE_TI_ARGS (parm);
            tree argvec = INNERMOST_TEMPLATE_ARGS (TYPE_TI_ARGS (arg));
            tree parm_parms 
-             = DECL_INNERMOST_TEMPLATE_PARMS 
+              = DECL_INNERMOST_TEMPLATE_PARMS
                  (TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL (parm));
            int i, len;
             int parm_variadic_p = 0;
index 2a130ae11d1481cac58b5c2cadc737b73f6519c7..42b5dcd80e93562ecdd87f3973c7e34234e06ac4 100644 (file)
@@ -1,3 +1,7 @@
+2008-03-27  Douglas Gregor  <doug.gregor@gmail.com>
+
+       * g++.dg/cpp0x/variadic91.C: New.
+
 2008-03-27  Zdenek Dvorak  <ook@ucw.cz>
 
        * gcc.dg/tree-ssa/loop-32.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic91.C b/gcc/testsuite/g++.dg/cpp0x/variadic91.C
new file mode 100644 (file)
index 0000000..d78b791
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++0x" }
+template<int N> struct Int2Type { };
+
+template<typename... T>
+struct Outer {
+  template<typename... U>
+  void foo(Int2Type<sizeof...(T)>, Int2Type<sizeof...(U)>);
+};
+
+
+Outer<short, int, long> outer;
+
+void g4() {
+  outer.foo<float, double>(Int2Type<3>(), Int2Type<2>());
+}
+
+template<typename... T, template<T...> class X> void f1();