diff options
author | Patrick Palka <ppalka@redhat.com> | 2021-03-30 22:54:37 -0400 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2021-03-30 22:54:37 -0400 |
commit | 0bbf0edbfc782f8e4e416d5fbd1b52a515adb585 (patch) | |
tree | aeb995df7e895e1883c7959b486e5faf33d3f00b | |
parent | 08d2edae5d84209c0dcf327a13d4f6b4eacdb1ac (diff) | |
download | gcc-0bbf0edbfc782f8e4e416d5fbd1b52a515adb585.zip gcc-0bbf0edbfc782f8e4e416d5fbd1b52a515adb585.tar.gz gcc-0bbf0edbfc782f8e4e416d5fbd1b52a515adb585.tar.bz2 |
c++: placeholder type constraint and argument pack [PR99815]
When checking dependence of a placeholder type constraint, if the first
template argument of the constraint is an argument pack, we need to
expand it in order to properly separate the implicit 'auto' argument
from the rest.
gcc/cp/ChangeLog:
PR c++/99815
* pt.c (placeholder_type_constraint_dependent_p): Expand
argument packs to separate the first non-pack argument
from the rest.
gcc/testsuite/ChangeLog:
PR c++/99815
* g++.dg/cpp2a/concepts-placeholder5.C: New test.
-rw-r--r-- | gcc/cp/pt.c | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C | 32 |
2 files changed, 37 insertions, 0 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index a056ece..dc6f2f3 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -28189,6 +28189,11 @@ placeholder_type_constraint_dependent_p (tree t) tree id = unpack_concept_check (t); tree args = TREE_OPERAND (id, 1); tree first = TREE_VEC_ELT (args, 0); + if (ARGUMENT_PACK_P (first)) + { + args = expand_template_argument_pack (args); + first = TREE_VEC_ELT (args, 0); + } gcc_checking_assert (TREE_CODE (first) == WILDCARD_DECL || is_auto (first)); for (int i = 1; i < TREE_VEC_LENGTH (args); ++i) diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C new file mode 100644 index 0000000..eaea41a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C @@ -0,0 +1,32 @@ +// PR c++/99815 +// { dg-do compile { target c++20 } } + +template <class T, class U> +struct is_same { static constexpr bool value = false; }; + +template <class T> +struct is_same<T, T> { static constexpr bool value = true; }; + +template <class... Ts> +concept C = is_same<Ts...>::value; // { dg-error "wrong number" } + +template <class... Ts> void f() { + C<Ts...> auto x = 0; // { dg-error "constraints" } +} + +template void f<int>(); // { dg-bogus "" } +template void f<char>(); // { dg-message "required from here" } +template void f<>(); // { dg-message "required from here" } +template void f<int, int>(); // { dg-message "required from here" } + +template <class... Ts> void g() { + C<Ts..., int> auto x = 0; // { dg-error "constraints" } +} + +template void g<>(); // { dg-bogus "" } +template void g<int>(); // { dg-message "required from here" } + +template <class> void h() { + C<char> auto x = 0; // { dg-error "constraints" } + C<int> auto y = 0; +} |