diff mbox

C++ PATCH for c++/54437 (firefox build failure)

Message ID 50464CE1.4090904@redhat.com
State New
Headers show

Commit Message

Jason Merrill Sept. 4, 2012, 6:48 p.m. UTC
Here, the problem was that we were resolving the address of an 
overloaded function in the context of the template being called (which 
doesn't have access to the function) rather than the caller (which 
does).  We need to massage explicit template arguments before we enter 
the callee's context.

Tested x86_64-pc-linux-gnu, applying to trunk.
diff mbox

Patch

commit c17767b10d05c0ea47107a3b7f067da76cc5ad8d
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Sep 4 11:27:03 2012 -0400

    	PR c++/54437
    	PR c++/51213
    	* pt.c (fn_type_unification): Call coerce_template_parms before
    	entering substitution context.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4a39427..6f6235c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14591,11 +14591,22 @@  fn_type_unification (tree fn,
   static int deduction_depth;
   struct pending_template *old_last_pend = last_pending_template;
   struct tinst_level *old_error_tinst = last_error_tinst_level;
+  tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
   tree tinst;
   tree r = error_mark_node;
 
-  if (excessive_deduction_depth)
-    return error_mark_node;
+  /* Adjust any explicit template arguments before entering the
+     substitution context.  */
+  if (explicit_targs)
+    {
+      explicit_targs
+	= (coerce_template_parms (tparms, explicit_targs, NULL_TREE,
+				  complain,
+				  /*require_all_args=*/false,
+				  /*use_default_args=*/false));
+      if (explicit_targs == error_mark_node)
+	return error_mark_node;
+    }
 
   /* In C++0x, it's possible to have a function template whose type depends
      on itself recursively.  This is most obvious with decltype, but can also
@@ -14608,6 +14619,8 @@  fn_type_unification (tree fn,
      substitutions back up to the initial one.
 
      This is, of course, not reentrant.  */
+  if (excessive_deduction_depth)
+    return error_mark_node;
   tinst = build_tree_list (fn, targs);
   if (!push_tinst_level (tinst))
     {
@@ -14640,23 +14653,10 @@  fn_type_unification (tree fn,
 	 specified template argument values.  If a substitution in a
 	 template parameter or in the function type of the function
 	 template results in an invalid type, type deduction fails.  */
-      tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
       int i, len = TREE_VEC_LENGTH (tparms);
       location_t loc = input_location;
-      tree converted_args;
       bool incomplete = false;
 
-      if (explicit_targs == error_mark_node)
-	goto fail;
-
-      converted_args
-	= (coerce_template_parms (tparms, explicit_targs, NULL_TREE,
-				  complain,
-				   /*require_all_args=*/false,
-				   /*use_default_args=*/false));
-      if (converted_args == error_mark_node)
-	goto fail;
-
       /* Substitute the explicit args into the function type.  This is
 	 necessary so that, for instance, explicitly declared function
 	 arguments can match null pointed constants.  If we were given
@@ -14667,7 +14667,7 @@  fn_type_unification (tree fn,
         {
           tree parm = TREE_VALUE (TREE_VEC_ELT (tparms, i));
           bool parameter_pack = false;
-	  tree targ = TREE_VEC_ELT (converted_args, i);
+	  tree targ = TREE_VEC_ELT (explicit_targs, i);
 
           /* Dig out the actual parm.  */
           if (TREE_CODE (parm) == TYPE_DECL
@@ -14705,7 +14705,7 @@  fn_type_unification (tree fn,
 
       processing_template_decl += incomplete;
       input_location = DECL_SOURCE_LOCATION (fn);
-      fntype = tsubst (TREE_TYPE (fn), converted_args,
+      fntype = tsubst (TREE_TYPE (fn), explicit_targs,
 		       complain | tf_partial, NULL_TREE);
       input_location = loc;
       processing_template_decl -= incomplete;
@@ -14714,8 +14714,8 @@  fn_type_unification (tree fn,
 	goto fail;
 
       /* Place the explicitly specified arguments in TARGS.  */
-      for (i = NUM_TMPL_ARGS (converted_args); i--;)
-	TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
+      for (i = NUM_TMPL_ARGS (explicit_targs); i--;)
+	TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i);
     }
 
   /* Never do unification on the 'this' parameter.  */
diff --git a/gcc/testsuite/g++.dg/template/access24.C b/gcc/testsuite/g++.dg/template/access24.C
new file mode 100644
index 0000000..9f19226
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access24.C
@@ -0,0 +1,8 @@ 
+// PR c++/54437
+
+template <void (*P)()> void f();
+class A {
+  template <class T> static void g();
+  template <class T> static void h () { f<g<T> >(); }
+  static void i() { h<int>(); }
+};