mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 23:11:36 +08:00
c++: generic lambda forwarding function [PR94546]
While instantiating test(Plot) we partially instantiate the generic lambda. We look at forward<T>(rest)... and see that it's just replacing parameter packs with new parameter packs and tries to do a direct substitution. But because register_parameter_specializations had built up a NONTYPE_ARGUMENT_PACK around the new parameter pack, the substitution failed. So let's not wrap it that way. gcc/cp/ChangeLog 2020-04-22 Jason Merrill <jason@redhat.com> PR c++/94546 * pt.c (register_parameter_specializations): If the instantiation is still a parameter pack, don't wrap it in a NONTYPE_ARGUMENT_PACK. (tsubst_pack_expansion, tsubst_expr): Adjust.
This commit is contained in:
parent
587970215f
commit
aedd04caa9
@ -1,3 +1,10 @@
|
||||
2020-04-22 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/94546
|
||||
* pt.c (register_parameter_specializations): If the instantiation is
|
||||
still a parameter pack, don't wrap it in a NONTYPE_ARGUMENT_PACK.
|
||||
(tsubst_pack_expansion, tsubst_expr): Adjust.
|
||||
|
||||
2020-04-22 Martin Sebor <msebor@redhat.com>
|
||||
Jason Merrill <jason@redhat.com>
|
||||
|
||||
|
28
gcc/cp/pt.c
28
gcc/cp/pt.c
@ -12753,7 +12753,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
||||
tree pattern;
|
||||
tree pack, packs = NULL_TREE;
|
||||
bool unsubstituted_packs = false;
|
||||
bool unsubstituted_fn_pack = false;
|
||||
int i, len = -1;
|
||||
tree result;
|
||||
bool need_local_specializations = false;
|
||||
@ -12833,19 +12832,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
||||
else
|
||||
arg_pack = make_fnparm_pack (arg_pack);
|
||||
}
|
||||
else if (argument_pack_element_is_expansion_p (arg_pack, 0))
|
||||
/* This argument pack isn't fully instantiated yet. We set this
|
||||
flag rather than clear arg_pack because we do want to do the
|
||||
optimization below, and we don't want to substitute directly
|
||||
into the pattern (as that would expose a NONTYPE_ARGUMENT_PACK
|
||||
where it isn't expected). */
|
||||
unsubstituted_fn_pack = true;
|
||||
else if (DECL_PACK_P (arg_pack))
|
||||
/* This argument pack isn't fully instantiated yet. */
|
||||
arg_pack = NULL_TREE;
|
||||
}
|
||||
else if (is_capture_proxy (parm_pack))
|
||||
{
|
||||
arg_pack = retrieve_local_specialization (parm_pack);
|
||||
if (argument_pack_element_is_expansion_p (arg_pack, 0))
|
||||
unsubstituted_fn_pack = true;
|
||||
if (DECL_PACK_P (arg_pack))
|
||||
arg_pack = NULL_TREE;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -12880,8 +12875,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
||||
|
||||
if (len < 0)
|
||||
len = my_len;
|
||||
else if (len != my_len
|
||||
&& !unsubstituted_fn_pack)
|
||||
else if (len != my_len)
|
||||
{
|
||||
if (!(complain & tf_error))
|
||||
/* Fail quietly. */;
|
||||
@ -12904,10 +12898,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
||||
/* We can't substitute for this parameter pack. We use a flag as
|
||||
well as the missing_level counter because function parameter
|
||||
packs don't have a level. */
|
||||
if (!(processing_template_decl || is_auto (parm_pack)))
|
||||
{
|
||||
gcc_unreachable ();
|
||||
}
|
||||
gcc_assert (processing_template_decl || is_auto (parm_pack));
|
||||
unsubstituted_packs = true;
|
||||
}
|
||||
@ -17897,7 +17887,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
|
||||
{
|
||||
inst = (retrieve_local_specialization
|
||||
(DECL_CAPTURED_VARIABLE (decl)));
|
||||
gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK);
|
||||
gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK
|
||||
|| DECL_PACK_P (inst));
|
||||
}
|
||||
else
|
||||
inst = lookup_init_capture_pack (decl);
|
||||
@ -25315,7 +25306,8 @@ register_parameter_specializations (tree pattern, tree inst)
|
||||
}
|
||||
for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
|
||||
{
|
||||
if (!DECL_PACK_P (tmpl_parm))
|
||||
if (!DECL_PACK_P (tmpl_parm)
|
||||
|| (spec_parm && DECL_PACK_P (spec_parm)))
|
||||
{
|
||||
register_local_specialization (spec_parm, tmpl_parm);
|
||||
spec_parm = DECL_CHAIN (spec_parm);
|
||||
|
23
gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic20.C
Normal file
23
gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic20.C
Normal file
@ -0,0 +1,23 @@
|
||||
// PR c++/94546
|
||||
// { dg-do compile { target c++2a } }
|
||||
|
||||
template <class T> T&& forward(T&& t) { return static_cast<T&&>(t); }
|
||||
|
||||
template <class X>
|
||||
void test(X&& plot)
|
||||
{
|
||||
// Note: For brevity, this lambda function is only
|
||||
// defined, not called nor assigned to a variable.
|
||||
// Doing those things won't fix the error.
|
||||
[&]<class... T>(T&&... rest)
|
||||
{
|
||||
plot(forward<T>(rest)...);
|
||||
};
|
||||
}
|
||||
int main()
|
||||
{
|
||||
auto Plot = [](auto&&...)
|
||||
{
|
||||
};
|
||||
test(Plot);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user