From ac001ddd0cb635dec0145bf577ac796894bda398 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Thu, 11 Feb 2021 19:45:22 -0500 Subject: [PATCH] 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. --- gcc/cp/pt.c | 38 ++++++++++++++-------- .../g++.dg/cpp2a/lambda-generic-variadic21.C | 19 +++++++++++ 2 files changed, 43 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic21.C 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 +T arg_T(decltype(Is)..., T, ...); + +template +inline constexpr auto get = + [](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.template operator()(v...); + } + }; + +static_assert( get<0>('\0', short{1}, 2, long{3}) == 0 ); -- 2.7.4