c++: Fix ICE with variadic concepts and aliases [PR93907]
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. 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.
This commit is contained in:
parent
32ff3309ae
commit
71a8040716
2 changed files with 62 additions and 0 deletions
|
@ -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;
|
||||
|
|
52
gcc/testsuite/g++.dg/cpp2a/concepts-using3.C
Normal file
52
gcc/testsuite/g++.dg/cpp2a/concepts-using3.C
Normal file
|
@ -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);
|
||||
}
|
Loading…
Add table
Reference in a new issue