diff options
author | Jason Merrill <jason@redhat.com> | 2021-02-11 19:45:22 -0500 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2021-02-11 21:30:24 -0500 |
commit | ac001ddd0cb635dec0145bf577ac796894bda398 (patch) | |
tree | b2dd09bcb741231c42f1e6065a6d61c9ed0b566d | |
parent | 3e2f329e94830e7c1861c590f661c25f7465bb7c (diff) | |
download | gcc-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.c | 38 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C | 19 |
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 ); |