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 so that we properly separate the implicit 'auto' argument from
the rest.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk?

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.
---
 gcc/cp/pt.c                                   |  5 +++
 .../g++.dg/cpp2a/concepts-placeholder5.C      | 32 +++++++++++++++++++
 2 files changed, 37 insertions(+)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a056ecefd1d..dc6f2f37f9b 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 00000000000..eaea41a36eb
--- /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;
+}
-- 
2.31.1.133.g84d06cdc06

Reply via email to