]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: placeholder type constraint and argument pack [PR99815]
authorPatrick Palka <ppalka@redhat.com>
Wed, 31 Mar 2021 02:54:37 +0000 (22:54 -0400)
committerPatrick Palka <ppalka@redhat.com>
Wed, 31 Mar 2021 02:54:37 +0000 (22:54 -0400)
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.

gcc/cp/pt.c
gcc/testsuite/g++.dg/cpp2a/concepts-placeholder5.C [new file with mode: 0644]

index a056ecefd1dfdff805e3f31312b99ad4099909ea..dc6f2f37f9bb1548283fe7df1148c0a441251a76 100644 (file)
@@ -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 (file)
index 0000000..eaea41a
--- /dev/null
@@ -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;
+}