diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc index b6f6f0d02a5e8c4edab52ccc03c3026ae88e1c0f..c871a8ab86a807420a8f0a6c48662cfaf16440dc 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 0000000000000000000000000000000000000000..2c8ad40d10430bb54145f0b0713167af31d05e8e --- /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); +}