c++: variadic lambda template and empty pack [PR97246]
In get<0>, Is is empty, so the first parameter pack of the lambda is empty, but after the fix for PR94546 we were wrongly associating it with the partial instantiation of 'v'. gcc/cp/ChangeLog: PR c++/97246 PR c++/94546 * pt.c (extract_fnparm_pack): Check DECL_PACK_P here. (register_parameter_specializations): Not here. gcc/testsuite/ChangeLog: PR c++/97246 * g++.dg/cpp2a/lambda-generic-variadic21.C: New test.
This commit is contained in:
parent
3e2f329e94
commit
ac001ddd0c
38
gcc/cp/pt.c
38
gcc/cp/pt.c
@ -12302,29 +12302,40 @@ extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
|
||||
{
|
||||
/* Collect all of the extra "packed" parameters into an
|
||||
argument pack. */
|
||||
tree parmvec;
|
||||
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
|
||||
tree argpack;
|
||||
tree spec_parm = *spec_p;
|
||||
int i, len;
|
||||
int len;
|
||||
|
||||
for (len = 0; spec_parm; ++len, spec_parm = TREE_CHAIN (spec_parm))
|
||||
if (tmpl_parm
|
||||
&& !function_parameter_expanded_from_pack_p (spec_parm, tmpl_parm))
|
||||
break;
|
||||
|
||||
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
|
||||
parmvec = make_tree_vec (len);
|
||||
spec_parm = *spec_p;
|
||||
for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
|
||||
if (len == 1 && DECL_PACK_P (spec_parm))
|
||||
{
|
||||
tree elt = spec_parm;
|
||||
if (DECL_PACK_P (elt))
|
||||
elt = make_pack_expansion (elt);
|
||||
TREE_VEC_ELT (parmvec, i) = elt;
|
||||
/* The instantiation is still a parameter pack; don't wrap it in a
|
||||
NONTYPE_ARGUMENT_PACK. */
|
||||
argpack = spec_parm;
|
||||
spec_parm = DECL_CHAIN (spec_parm);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Fill in PARMVEC with all of the parameters. */
|
||||
tree parmvec = make_tree_vec (len);
|
||||
argpack = make_node (NONTYPE_ARGUMENT_PACK);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
tree elt = spec_parm;
|
||||
if (DECL_PACK_P (elt))
|
||||
elt = make_pack_expansion (elt);
|
||||
TREE_VEC_ELT (parmvec, i) = elt;
|
||||
spec_parm = DECL_CHAIN (spec_parm);
|
||||
}
|
||||
|
||||
/* Build the argument packs. */
|
||||
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
|
||||
/* Build the argument packs. */
|
||||
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
|
||||
}
|
||||
*spec_p = spec_parm;
|
||||
|
||||
return argpack;
|
||||
@ -25716,8 +25727,7 @@ register_parameter_specializations (tree pattern, tree inst)
|
||||
}
|
||||
for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
|
||||
{
|
||||
if (!DECL_PACK_P (tmpl_parm)
|
||||
|| (spec_parm && DECL_PACK_P (spec_parm)))
|
||||
if (!DECL_PACK_P (tmpl_parm))
|
||||
{
|
||||
register_local_specialization (spec_parm, tmpl_parm);
|
||||
spec_parm = DECL_CHAIN (spec_parm);
|
||||
|
19
gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C
Normal file
19
gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C
Normal file
@ -0,0 +1,19 @@
|
||||
// PR c++/97246
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
template <int... Is, typename T>
|
||||
T arg_T(decltype(Is)..., T, ...);
|
||||
|
||||
template <int I, int... Is>
|
||||
inline constexpr auto get =
|
||||
[]<typename... T>(decltype(Is)..., T... v, ...) {
|
||||
static_assert( sizeof...(T) == sizeof...(v) );
|
||||
if constexpr ( sizeof...(T) == 1 )
|
||||
return (v,...);
|
||||
else {
|
||||
using V = decltype(arg_T<__integer_pack(I)...>(v...));
|
||||
return get<I,__integer_pack(I)...>.template operator()<V>(v...);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert( get<0>('\0', short{1}, 2, long{3}) == 0 );
|
Loading…
Reference in New Issue
Block a user