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;