The existing code to handle pack expansions in trailing-return-type assumed that such expansions would only occur inside decltype, which is not the case. This patch fixes the test to check for whether or not we're doing the substitution in the context of a function body, and fixes at_function_scope_p to properly return false when we're substituting deduced arguments into a candidate function template.

Even with the change to at_function_scope_p it was impossible to tell that we weren't in function scope when instantiating a function declaration as part of overload resolution, so I also changed instantiate_template_1 to use push_to_top_level rather than just clear processing_template_decl. In my testing it was enough to just clear current_function_decl as well, but since in fact the instantiation happens at top level it seems more correct to use push_to_top_level.

The second patch is a bug I noticed in dependent_name while working on this patch, though it isn't necessary to this patch; a BASELINK should not be considered a dependent name, or we end up treating calls to members of different classes as equivalent.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 4df8b36d378adc678ed4ca9ac91088ad0772b750
Author: Jason Merrill <ja...@redhat.com>
Date:   Thu Dec 22 11:03:09 2011 -0500

    	PR c++/51507
    	* search.c (at_function_scope_p): Also check cfun.
    	* pt.c (tsubst_pack_expansion): Check it instead of
    	cp_unevaluated_operand.
    	(instantiate_template_1): Clear current_function_decl.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 820b1ff..20f67aa 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9297,6 +9297,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   int i, len = -1;
   tree result;
   htab_t saved_local_specializations = NULL;
+  bool need_local_specializations = false;
   int levels;
 
   gcc_assert (PACK_EXPANSION_P (t));
@@ -9330,7 +9331,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
        }
       if (TREE_CODE (parm_pack) == PARM_DECL)
 	{
-	  if (!cp_unevaluated_operand)
+	  if (at_function_scope_p ())
 	    arg_pack = retrieve_local_specialization (parm_pack);
 	  else
 	    {
@@ -9346,6 +9347,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
 		arg_pack = NULL_TREE;
 	      else
 		arg_pack = make_fnparm_pack (arg_pack);
+	      need_local_specializations = true;
 	    }
 	}
       else
@@ -9476,7 +9478,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
   if (len < 0)
     return error_mark_node;
 
-  if (cp_unevaluated_operand)
+  if (need_local_specializations)
     {
       /* We're in a late-specified return type, so create our own local
 	 specializations table; the current table is either NULL or (in the
@@ -14524,7 +14526,6 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
   tree fndecl;
   tree gen_tmpl;
   tree spec;
-  HOST_WIDE_INT saved_processing_template_decl;
 
   if (tmpl == error_mark_node)
     return error_mark_node;
@@ -14585,18 +14586,22 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
      deferring all checks until we have the FUNCTION_DECL.  */
   push_deferring_access_checks (dk_deferred);
 
-  /* Although PROCESSING_TEMPLATE_DECL may be true at this point
-     (because, for example, we have encountered a non-dependent
-     function call in the body of a template function and must now
-     determine which of several overloaded functions will be called),
-     within the instantiation itself we are not processing a
-     template.  */  
-  saved_processing_template_decl = processing_template_decl;
-  processing_template_decl = 0;
+  /* Instantiation of the function happens in the context of the function
+     template, not the context of the overload resolution we're doing.  */
+  push_to_top_level ();
+  if (DECL_CLASS_SCOPE_P (gen_tmpl))
+    {
+      tree ctx = tsubst (DECL_CONTEXT (gen_tmpl), targ_ptr,
+			 complain, gen_tmpl);
+      push_nested_class (ctx);
+    }
   /* Substitute template parameters to obtain the specialization.  */
   fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
 		   targ_ptr, complain, gen_tmpl);
-  processing_template_decl = saved_processing_template_decl;
+  if (DECL_CLASS_SCOPE_P (gen_tmpl))
+    pop_nested_class ();
+  pop_from_top_level ();
+
   if (fndecl == error_mark_node)
     return error_mark_node;
 
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 0ceb5bc..45fdafc 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -539,7 +539,11 @@ int
 at_function_scope_p (void)
 {
   tree cs = current_scope ();
-  return cs && TREE_CODE (cs) == FUNCTION_DECL;
+  /* Also check cfun to make sure that we're really compiling
+     this function (as opposed to having set current_function_decl
+     for access checking or some such).  */
+  return (cs && TREE_CODE (cs) == FUNCTION_DECL
+	  && cfun && cfun->decl == current_function_decl);
 }
 
 /* Returns true if the innermost active scope is a class scope.  */
diff --git a/gcc/testsuite/g++.dg/cpp0x/variadic121.C b/gcc/testsuite/g++.dg/cpp0x/variadic121.C
new file mode 100644
index 0000000..805c006
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/variadic121.C
@@ -0,0 +1,12 @@
+// PR c++/51507
+// { dg-options -std=c++0x }
+
+template<typename ...>
+struct foo { typedef void type; };
+template<typename ...Ts>
+auto g(Ts ...ts)->
+  typename foo<decltype(ts)...>::type
+{}
+int main() {
+  g(42);
+}
commit a02c1be6a5cb39703b715e8b490976e8eacc9431
Author: Jason Merrill <ja...@redhat.com>
Date:   Fri Dec 23 13:58:46 2011 -0500

    	* tree.c (dependent_name): OFFSET_REF and BASELINK
    	are not dependent names.

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 634c267..dea7632 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1463,6 +1463,8 @@ dependent_name (tree x)
   if (TREE_CODE (x) == IDENTIFIER_NODE)
     return x;
   if (TREE_CODE (x) != COMPONENT_REF
+      && TREE_CODE (x) != OFFSET_REF
+      && TREE_CODE (x) != BASELINK
       && is_overloaded_fn (x))
     return DECL_NAME (get_first_fn (x));
   return NULL_TREE;

Reply via email to