This patch (naively) extends the PR93907 fix to also apply to variadic concepts invoked with a type argument pack. Without this, we ICE on the below testcase (a variadic version of concepts-using2.C) in the same manner as we used to on concepts-using2.C before r10-7133.
Patch series bootstrapped and regtested on x86_64-pc-linux-gnu, and also tested against cmcstl2 and range-v3. gcc/cp/ChangeLog: PR c++/93907 * constraint.cc (tsubst_parameter_mapping): Also canonicalize the type arguments of a TYPE_ARGUMENT_PACk. gcc/testsuite/ChangeLog: PR c++/93907 * g++.dg/cpp2a/concepts-using3.C: New test, based off of concepts-using2.C. --- gcc/cp/constraint.cc | 10 ++++ gcc/testsuite/g++.dg/cpp2a/concepts-using3.C | 52 ++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-using3.C diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index b6f6f0d02a5..c871a8ab86a 100644 --- a/gcc/cp/constraint.cc +++ b/gcc/cp/constraint.cc @@ -2252,6 +2252,16 @@ tsubst_parameter_mapping (tree map, tree args, subst_info info) new_arg = tsubst_template_arg (arg, args, complain, in_decl); if (TYPE_P (new_arg)) new_arg = canonicalize_type_argument (new_arg, complain); + if (TREE_CODE (new_arg) == TYPE_ARGUMENT_PACK) + { + tree pack_args = ARGUMENT_PACK_ARGS (new_arg); + for (int i = 0; i < TREE_VEC_LENGTH (pack_args); i++) + { + tree& pack_arg = TREE_VEC_ELT (pack_args, i); + if (TYPE_P (pack_arg)) + pack_arg = canonicalize_type_argument (pack_arg, complain); + } + } } if (new_arg == error_mark_node) return error_mark_node; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C new file mode 100644 index 00000000000..2c8ad40d104 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-using3.C @@ -0,0 +1,52 @@ +// PR c++/93907 +// { dg-options -std=gnu++20 } + +// This testcase is a variadic version of concepts-using2.C; the only +// difference is that 'cd' and 'ce' are now variadic concepts. + +template <int a> struct c { + static constexpr int d = a; + typedef c e; +}; +template <typename> struct f; +template <typename b> using g = typename f<b>::e; +struct b; +template <typename b> struct f { using e = b; }; +template <typename ai> struct m { typedef g<ai> aj; }; +template <typename b> struct n { typedef typename m<b>::aj e; }; +template <typename b> using an = typename n<b>::e; +template <typename> constexpr bool ao = c<true>::d; +template <typename> constexpr bool i = c<1>::d; +template <typename> concept bb = i<b>; +#ifdef __SIZEOF_INT128__ +using cc = __int128; +#else +using cc = long long; +#endif +template <typename...> concept cd = bb<cc>; +template <typename... bt> concept ce = requires { requires cd<bt...>; }; +template <typename bt> concept h = ce<bt>; +template <typename bt> concept l = h<bt>; +template <typename> concept cl = ao<b>; +template <typename b> concept cp = requires(b j) { + requires h<an<decltype(j.begin())>>; +}; +struct o { + template <cl b> requires cp<b> auto operator()(b) {} +}; +template <typename b> using cm = decltype(o{}(b())); +template <typename bt> concept ct = l<bt>; +template <typename da> concept dd = ct<cm<da>>; +template <typename da> concept de = dd<da>; +struct { + template <de da, typename b> void operator()(da, b); +} di; +struct p { + void begin(); +}; +template <typename> using df = p; +template <int> void q() { + df<int> k; + int d; + di(k, d); +} -- 2.29.2.154.g7f7ebe054a