aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-02-11 19:45:22 -0500
committerJason Merrill <jason@redhat.com>2021-02-11 21:30:24 -0500
commitac001ddd0cb635dec0145bf577ac796894bda398 (patch)
treeb2dd09bcb741231c42f1e6065a6d61c9ed0b566d
parent3e2f329e94830e7c1861c590f661c25f7465bb7c (diff)
downloadgcc-ac001ddd0cb635dec0145bf577ac796894bda398.zip
gcc-ac001ddd0cb635dec0145bf577ac796894bda398.tar.gz
gcc-ac001ddd0cb635dec0145bf577ac796894bda398.tar.bz2
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.
-rw-r--r--gcc/cp/pt.c38
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C19
2 files changed, 43 insertions, 14 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 37c45a2..50cdb00 100644
--- a/gcc/cp/pt.c
+++ b/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);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C
new file mode 100644
index 0000000..d6b5656
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C
@@ -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 );