diff options
author | Patrick Palka <ppalka@redhat.com> | 2022-04-12 12:58:18 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2022-04-12 19:31:48 -0400 |
commit | 051d304ce8e2173bd0cb721ed91d4a1fefa61d87 (patch) | |
tree | eb7db618e1a6eecf3e6db2d8a7b07b5fb61ff1ff | |
parent | d3950a70da6814206eef1946c289b5652ecc9986 (diff) | |
download | gcc-051d304ce8e2173bd0cb721ed91d4a1fefa61d87.zip gcc-051d304ce8e2173bd0cb721ed91d4a1fefa61d87.tar.gz gcc-051d304ce8e2173bd0cb721ed91d4a1fefa61d87.tar.bz2 |
c++: requires-expr in pack expansion using pack [PR103105]
Here after dependent substitution of {Ts...} into the alias 'wrap',
since we never partially instantiate a requires-expr, we end up with a
requires-expr whose REQUIRES_EXPR_EXTRA_ARGS contains an
ARGUMENT_PACK_SELECT (which just resolves to the parameter pack Ts).
Then when hashing the resulting dependent specialization of A, we crash
from iterative_hash_template_arg since it deliberately doesn't handle
ARGUMENT_PACK_SELECT.
Like in r12-7102-gdb5f1c17031ad8, it seems the right fix here is to
resolve ARGUMENT_PACK_SELECT arguments before storing them into an
extra args tree (such as REQUIRES_EXPR).
PR c++/103105
gcc/cp/ChangeLog:
* pt.c (build_extra_args): Call preserve_args.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/concepts-requires29.C: New test.
* g++.dg/cpp2a/concepts-requires29a.C: New test.
(cherry picked from commit e2c7070ac7740508a7c49bfee9f895e216a272d6)
-rw-r--r-- | gcc/cp/pt.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-requires29.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-requires29a.C | 23 |
3 files changed, 42 insertions, 1 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index da289c2..40a3f19 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -13007,7 +13007,7 @@ build_extra_args (tree pattern, tree args, tsubst_flags_t complain) { /* Make a copy of the extra arguments so that they won't get changed out from under us. */ - tree extra = copy_template_args (args); + tree extra = preserve_args (copy_template_args (args), /*cow_p=*/false); if (local_specializations) if (tree locals = extract_local_specs (pattern, complain)) extra = tree_cons (NULL_TREE, extra, locals); diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires29.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires29.C new file mode 100644 index 0000000..2cf6943 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires29.C @@ -0,0 +1,18 @@ +// PR c++/103105 +// { dg-do compile { target c++20 } } + +template<bool> struct A; + +template<class... Ts> +using wrap = A<1 != (0 + ... + requires { Ts(); })>; + +template<class... Ts> using type = wrap<Ts...>; + +using ty0 = type<>; +using ty0 = A<true>; + +using ty1 = type<int>; +using ty1 = A<false>; + +using ty2 = type<int, int>; +using ty2 = A<true>; diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires29a.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires29a.C new file mode 100644 index 0000000..84c2269 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires29a.C @@ -0,0 +1,23 @@ +// PR c++/103105 +// { dg-do compile { target c++20 } } + +template<class...> struct list; + +template<bool> struct A; + +template<class T, class... Ts> +using wrap = A<1 != (0 + ... + requires { T() = Ts(); })>; + +template<class... Ts> using type = list<wrap<Ts, Ts...>...>; + +using ty0 = type<>; +using ty0 = list<>; + +using ty1 = type<int>; +using ty1 = list<A<true>>; + +using ty2 = type<int, int>; +using ty2 = list<A<true>, A<true>>; + +using ty3 = type<int, int, int>; +using ty3 = list<A<true>, A<true>, A<true>>; |