]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/35146 (weird error in template function specialization)
authorJason Merrill <jason@redhat.com>
Mon, 6 Apr 2009 20:55:04 +0000 (16:55 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 6 Apr 2009 20:55:04 +0000 (16:55 -0400)
PR c++/35146
* pt.c (fn_type_unification): For DEDUCE_EXACT check that
the deduced template arguments give us the parameter types
we're looking for.

From-SVN: r145625

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

index 408625789239e710ed8b380fae5b39403ab6972b..02440e516e04b77bf9d12e67856023da00ece9dd 100644 (file)
@@ -1,3 +1,10 @@
+2009-04-06  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35146
+       * pt.c (fn_type_unification): For DEDUCE_EXACT check that
+       the deduced template arguments give us the parameter types
+       we're looking for.
+
 2009-04-05  Giovanni Bajo <giovannibajo@libero.it>
            Jason Merrill  <jason@redhat.com>
 
index 3e3d4f250f28862c0ac86f3c011a29602e138be6..92815c08267b67b16cae06d9f5b76c7c18829461 100644 (file)
@@ -12301,9 +12301,27 @@ fn_type_unification (tree fn,
        the corresponding deduced argument values.  If the
        substitution results in an invalid type, as described above,
        type deduction fails.  */
-    if (tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE)
-       == error_mark_node)
-      return 1;
+    {
+      tree substed = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+      if (substed == error_mark_node)
+       return 1;
+
+      /* If we're looking for an exact match, check that what we got
+        is indeed an exact match.  It might not be if some template
+        parameters are used in non-deduced contexts.  */
+      if (strict == DEDUCE_EXACT)
+       {
+         tree sarg
+           = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
+         tree arg = args;
+         if (return_type)
+           sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
+         for (; arg && sarg;
+              arg = TREE_CHAIN (arg), sarg = TREE_CHAIN (sarg))
+           if (!same_type_p (TREE_VALUE (arg), TREE_VALUE (sarg)))
+             return 1;
+       }
+    }
 
   return result;
 }
index 40b0d240ee5aeed59ec637e7cd2c9777765bfa2f..b4864a20dbb0888e5d728cd8f07d25a0876a8933 100644 (file)
@@ -1,3 +1,8 @@
+2009-04-06  Jason Merrill  <jason@redhat.com>
+
+       PR c++/35146
+       * g++.dg/template/fnspec1.C: New.
+
 2009-04-06  Laurent GUERBY  <laurent@guerby.net>
 
         * lib/gnat.exp: Handle multilib.
diff --git a/gcc/testsuite/g++.dg/template/fnspec1.C b/gcc/testsuite/g++.dg/template/fnspec1.C
new file mode 100644 (file)
index 0000000..5d53244
--- /dev/null
@@ -0,0 +1,16 @@
+// PR c++/35146
+
+template <typename T> struct S {};
+
+template <typename R> struct ref;
+template <>           struct ref<double> { typedef double result; };
+
+template <typename T>
+void foo(typename ref<T>::result, S<T>*);
+template <>
+void foo(S<double>,               S<double>*); // { dg-error "does not match" }
+template <>
+void foo(double alpha,            S<double>* x)
+{
+  alpha; x;
+}