re PR c++/48451 ([C++0x][SFINAE] Failures with n-ary initialization expressions ...
authorJason Merrill <jason@redhat.com>
Fri, 8 Apr 2011 02:03:25 +0000 (22:03 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 8 Apr 2011 02:03:25 +0000 (22:03 -0400)
PR c++/48451
* pt.c (fn_type_unification): Don't clear incomplete pack flag.
(type_unification_real): Clear it here instead.

From-SVN: r172159

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

index d20cf51..fcb5232 100644 (file)
@@ -1,5 +1,9 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       PR c++/48451
+       * pt.c (fn_type_unification): Don't clear incomplete pack flag.
+       (type_unification_real): Clear it here instead.
+
        PR c++/48468
        * except.c (build_noexcept_spec): Propagate error_mark_node.
        (finish_noexcept_expr): Likewise.
index 66db880..4edd404 100644 (file)
@@ -13719,7 +13719,8 @@ fn_type_unification (tree fn,
               template_parm_level_and_index (parm, &level, &idx);
 
               /* Mark the argument pack as "incomplete". We could
-                 still deduce more arguments during unification.  */
+                 still deduce more arguments during unification.
+                We remove this mark in type_unification_real.  */
               targ = TMPL_ARG (converted_args, level, idx);
               if (targ)
                 {
@@ -13776,22 +13777,6 @@ fn_type_unification (tree fn,
                                  targs, parms, args, nargs, /*subr=*/0,
                                  strict, flags);
 
-  if (result == 0 && incomplete_argument_packs_p)
-    {
-      int i, len = NUM_TMPL_ARGS (targs);
-
-      /* Clear the "incomplete" flags on all argument packs.  */
-      for (i = 0; i < len; i++)
-        {
-          tree arg = TREE_VEC_ELT (targs, i);
-          if (ARGUMENT_PACK_P (arg))
-            {
-              ARGUMENT_PACK_INCOMPLETE_P (arg) = 0;
-              ARGUMENT_PACK_EXPLICIT_ARGS (arg) = NULL_TREE;
-            }
-        }
-    }
-
   /* Now that we have bindings for all of the template arguments,
      ensure that the arguments deduced for the template template
      parameters have compatible template parameter lists.  We cannot
@@ -14136,15 +14121,17 @@ type_unification_real (tree tparms,
     return 1;
 
   if (!subr)
-    for (i = 0; i < ntparms; i++)
-      if (!TREE_VEC_ELT (targs, i))
+    {
+      /* Check to see if we need another pass before we start clearing
+        ARGUMENT_PACK_INCOMPLETE_P.  */
+      for (i = 0; i < ntparms; i++)
        {
-         tree tparm;
-
-          if (TREE_VEC_ELT (tparms, i) == error_mark_node)
-            continue;
+         tree targ = TREE_VEC_ELT (targs, i);
+         tree tparm = TREE_VEC_ELT (tparms, i);
 
-          tparm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
+         if (targ || tparm == error_mark_node)
+           continue;
+         tparm = TREE_VALUE (tparm);
 
          /* If this is an undeduced nontype parameter that depends on
             a type parameter, try another pass; its type may have been
@@ -14154,59 +14141,78 @@ type_unification_real (tree tparms,
              && uses_template_parms (TREE_TYPE (tparm))
              && !saw_undeduced++)
            goto again;
+       }
 
-          /* Core issue #226 (C++0x) [temp.deduct]:
+      for (i = 0; i < ntparms; i++)
+       {
+         tree targ = TREE_VEC_ELT (targs, i);
+         tree tparm = TREE_VEC_ELT (tparms, i);
 
-               If a template argument has not been deduced, its
-               default template argument, if any, is used. 
+         /* Clear the "incomplete" flags on all argument packs now so that
+            substituting them into later default arguments works.  */
+         if (targ && ARGUMENT_PACK_P (targ))
+            {
+              ARGUMENT_PACK_INCOMPLETE_P (targ) = 0;
+              ARGUMENT_PACK_EXPLICIT_ARGS (targ) = NULL_TREE;
+            }
 
-             When we are in C++98 mode, TREE_PURPOSE will either
+         if (targ || tparm == error_mark_node)
+           continue;
+         tparm = TREE_VALUE (tparm);
+
+         /* Core issue #226 (C++0x) [temp.deduct]:
+
+            If a template argument has not been deduced, its
+            default template argument, if any, is used. 
+
+            When we are in C++98 mode, TREE_PURPOSE will either
             be NULL_TREE or ERROR_MARK_NODE, so we do not need
             to explicitly check cxx_dialect here.  */
-          if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
-            {
+         if (TREE_PURPOSE (TREE_VEC_ELT (tparms, i)))
+           {
              tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
              tree arg = TREE_PURPOSE (TREE_VEC_ELT (tparms, i));
-              arg = tsubst_template_arg (arg, targs, tf_none, NULL_TREE);
+             arg = tsubst_template_arg (arg, targs, tf_none, NULL_TREE);
              arg = convert_template_argument (parm, arg, targs, tf_none,
                                               i, NULL_TREE);
-              if (arg == error_mark_node)
-                return 1;
-              else
-                {
-                  TREE_VEC_ELT (targs, i) = arg;
+             if (arg == error_mark_node)
+               return 1;
+             else
+               {
+                 TREE_VEC_ELT (targs, i) = arg;
                  /* The position of the first default template argument,
                     is also the number of non-defaulted arguments in TARGS.
                     Record that.  */
                  if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
                    SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, i);
-                  continue;
-                }
-            }
+                 continue;
+               }
+           }
 
-          /* If the type parameter is a parameter pack, then it will
-             be deduced to an empty parameter pack.  */
-          if (template_parameter_pack_p (tparm))
-            {
-              tree arg;
+         /* If the type parameter is a parameter pack, then it will
+            be deduced to an empty parameter pack.  */
+         if (template_parameter_pack_p (tparm))
+           {
+             tree arg;
 
-              if (TREE_CODE (tparm) == TEMPLATE_PARM_INDEX)
-                {
-                  arg = make_node (NONTYPE_ARGUMENT_PACK);
-                  TREE_TYPE (arg)  = TREE_TYPE (TEMPLATE_PARM_DECL (tparm));
-                  TREE_CONSTANT (arg) = 1;
-                }
-              else
-                arg = cxx_make_type (TYPE_ARGUMENT_PACK);
+             if (TREE_CODE (tparm) == TEMPLATE_PARM_INDEX)
+               {
+                 arg = make_node (NONTYPE_ARGUMENT_PACK);
+                 TREE_TYPE (arg)  = TREE_TYPE (TEMPLATE_PARM_DECL (tparm));
+                 TREE_CONSTANT (arg) = 1;
+               }
+             else
+               arg = cxx_make_type (TYPE_ARGUMENT_PACK);
 
-              SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
+             SET_ARGUMENT_PACK_ARGS (arg, make_tree_vec (0));
 
-              TREE_VEC_ELT (targs, i) = arg;
-              continue;
-            }
+             TREE_VEC_ELT (targs, i) = arg;
+             continue;
+           }
 
          return 2;
        }
+    }
 #ifdef ENABLE_CHECKING
   if (!NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
     SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs, TREE_VEC_LENGTH (targs));
index dc446df..8f52da2 100644 (file)
@@ -1,5 +1,7 @@
 2011-04-07  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/variadic107.C: New.
+
        * g++.dg/cpp0x/sfinae11.C: New.
        * g++.dg/cpp0x/noexcept02.C: Fix.
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic107.C b/gcc/testsuite/g++.dg/cpp0x/variadic107.C
new file mode 100644 (file)
index 0000000..5c3f468
--- /dev/null
@@ -0,0 +1,15 @@
+// PR c++/48451
+// { dg-options -std=c++0x }
+
+namespace std {
+  template <class T> T&& declval();
+}
+
+template<class T, class... Args,
+ class = decltype(T(std::declval<Args>()...))
+ >
+char f(int);
+
+struct From2Ints { From2Ints(int, int); };
+
+static_assert(sizeof(f<From2Ints, int, int>(0)) == 1, "Error"); // b