re PR c++/46394 ([C++0X] [4.6 Regression] no matching function with default template...
authorDodji Seketeli <dodji@redhat.com>
Sun, 20 Feb 2011 17:37:03 +0000 (17:37 +0000)
committerDodji Seketeli <dodji@gcc.gnu.org>
Sun, 20 Feb 2011 17:37:03 +0000 (18:37 +0100)
PR c++/46394

gcc/cp/

PR c++/46394
* pt.c (tsubst_pack_expansion): do not use
cp_tree_equal/same_type_p to detect an expansion of a parameter
pack.

gcc/testsuite/

PR c++/46394
* g++.dg/template/typedef38.C: New test.

From-SVN: r170341

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

index 938d3f2c40b9d8f92931c133ae110c00a475c0cf..a40fd02141bc7f1d52f191e0b2047682dd97a532 100644 (file)
@@ -1,3 +1,10 @@
+2011-02-20  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/46394
+       * pt.c (tsubst_pack_expansion): do not use
+       cp_tree_equal/same_type_p to detect an expansion of a parameter
+       pack.
+
 2011-02-19  Jason Merrill  <jason@redhat.com>
 
        PR c++/47503
index 49906361a61ea90c6f8f28b743251de3339a5531..8867225bc4da423e75afdc11012fcfd02dd234a4 100644 (file)
@@ -8711,19 +8711,51 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
          return result;
        }
 
+      /* For clarity in the comments below let's use the
+        representation 'argument_pack<elements>' to denote an
+        argument pack and its elements.
+
+        In the 'if' block below, we want to detect cases where
+        ARG_PACK is argument_pack<PARM_PACK...>.  I.e, we want to
+        check if ARG_PACK is an argument pack which sole element is
+        the expansion of PARM_PACK.  That argument pack is typically
+        created by template_parm_to_arg when passed a parameter
+        pack.  */
       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.  */
+         /* So we have an argument_pack<P...>.  We want to test if P
+            is actually PARM_PACK.  We will not use cp_tree_equal to
+            test P and PARM_PACK because during type fixup (by
+            fixup_template_parm) P can be a pre-fixup version of a
+            type and PARM_PACK be its post-fixup version.
+            cp_tree_equal would consider them as different even
+            though we would want to consider them compatible for our
+            precise purpose here.
+
+            Thus we are going to consider that P and PARM_PACK are
+            compatible if they have the same DECL.  */
+         if ((/* If ARG_PACK is a type parameter pack named by the
+                 same DECL as parm_pack ...  */
+              (TYPE_P (pattern)
+               && TYPE_P (parm_pack)
+               && TYPE_NAME (pattern) == TYPE_NAME (parm_pack))
+              /* ... or if ARG_PACK is a non-type parameter
+                 named by the same DECL as parm_pack ...  */
+              || (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX
+                  && TREE_CODE (parm_pack) == PARM_DECL
+                  && TEMPLATE_PARM_DECL (pattern)
+                  == TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack))))
+             && template_parameter_pack_p (pattern))
+            /* ... then 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;
         }
           
index 51f26e9f26cde948a24f01be47b3fbcf1e315fc5..ff5650a0815a6a148271c9865146fbc86990092a 100644 (file)
@@ -1,3 +1,8 @@
+2011-02-20  Dodji Seketeli  <dodji@redhat.com>
+
+       PR c++/46394
+       * g++.dg/template/typedef38.C: New test.
+
 2011-02-20  Paul Thomas  <pault@gcc.gnu.org>
 
        PR fortran/46818
diff --git a/gcc/testsuite/g++.dg/template/typedef38.C b/gcc/testsuite/g++.dg/template/typedef38.C
new file mode 100644 (file)
index 0000000..1c76404
--- /dev/null
@@ -0,0 +1,27 @@
+// Origin: PR c++/46394
+// { dg-options "-std=c++0x" }
+// { dg-do "compile" }
+
+template<class T>
+struct S0
+{
+  typedef T type;
+};
+
+template<class... X>
+struct S1
+{
+  typedef int I;
+};
+
+struct A
+{
+  template<class...U, class V=typename S1<typename S0<U>::type...>::I>
+  A(U...u);
+};
+
+int
+main()
+{
+  A a(1, 2);
+}