We need to loosen the check for an exact match when we're doing partial ordering, because dealing with dependent types means we can't instantiate things like typenames to see what they end up being. And it's not necessary because when we've gotten to partial ordering, we already know that both candidates are viable.

Tested x86_64-pc-linux-gnu, applying to trunk and 4.8.
commit 99cdae90e846894d63ff11e45ac47a9d1172483b
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Jan 30 23:29:54 2014 -0500

    	PR c++/57043
    	* pt.c (fn_type_unification): Don't do DEDUCE_EXACT check
    	during partial ordering.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 981e2e0..ae5995b 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -15740,8 +15740,11 @@ fn_type_unification (tree fn,
 
   /* 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)
+     parameters are used in non-deduced contexts.  But don't check
+     for an exact match if we have dependent template arguments;
+     in that case we're doing partial ordering, and we already know
+     that we have two candidates that will provide the actual type.  */
+  if (strict == DEDUCE_EXACT && !any_dependent_template_arguments_p (targs))
     {
       tree substed = TREE_TYPE (decl);
       unsigned int i;
diff --git a/gcc/testsuite/g++.dg/template/partial15.C b/gcc/testsuite/g++.dg/template/partial15.C
new file mode 100644
index 0000000..357bb05
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/partial15.C
@@ -0,0 +1,19 @@
+// PR c++/57043
+// { dg-do link }
+
+template<typename D> struct complex { };
+
+template<typename Tp>
+complex<Tp>
+pow(const complex<Tp>& x, const complex<Tp>& y) { return complex<Tp>(); }
+
+template<typename T, typename U>
+struct promote_2 { typedef T type; };
+
+template<typename Tp, typename Up>
+complex<typename promote_2<Tp, Up>::type>
+pow(const complex<Tp>& x, const complex<Up>& y);
+
+complex<double> (*powcc)(const complex<double>&, const complex<double>&) = pow;
+
+int main() {}

Reply via email to