aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-04-24 00:14:29 -0400
committerPatrick Palka <ppalka@redhat.com>2021-04-24 00:14:29 -0400
commitbcd77b7b9f35bd5b559ed593c3b3e346c1e6f364 (patch)
treee88f062f4be1c92aecddaf6953f76ade32c1b36f /gcc
parent5f1a2cb9c2dc09eed53da5d5787d14bec700b10b (diff)
downloadgcc-bcd77b7b9f35bd5b559ed593c3b3e346c1e6f364.zip
gcc-bcd77b7b9f35bd5b559ed593c3b3e346c1e6f364.tar.gz
gcc-bcd77b7b9f35bd5b559ed593c3b3e346c1e6f364.tar.bz2
c++: do_class_deduction and dependent init [PR93383]
Here we're crashing during CTAD with a dependent initializer (performed from convert_template_argument) because one of the initializer's elements has an empty TREE_TYPE, which ends up making resolve_args unhappy. Besides the case where we're initializing one template placeholder from another, which is already specifically handled earlier in do_class_deduction, it seems we can't in general correctly resolve a template placeholder using a dependent initializer, so this patch makes the function just punt until instantiation time instead. gcc/cp/ChangeLog: PR c++/89565 PR c++/93383 PR c++/95291 PR c++/99200 PR c++/99683 * pt.c (do_class_deduction): Punt if the initializer is type-dependent. gcc/testsuite/ChangeLog: PR c++/89565 PR c++/93383 PR c++/95291 PR c++/99200 PR c++/99683 * g++.dg/cpp2a/nontype-class39.C: Remove dg-ice directive. * g++.dg/cpp2a/nontype-class45.C: New test. * g++.dg/cpp2a/nontype-class46.C: New test. * g++.dg/cpp2a/nontype-class47.C: New test. * g++.dg/cpp2a/nontype-class48.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.c4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class39.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class45.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class46.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class47.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/nontype-class48.C36
6 files changed, 94 insertions, 2 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 8d64fef..8c3c814 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29368,6 +29368,10 @@ do_class_deduction (tree ptype, tree tmpl, tree init,
return error_mark_node;
}
+ /* Wait until the initializer is non-dependent. */
+ if (type_dependent_expression_p (init))
+ return ptype;
+
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
index 512afad..9b4da4f 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class39.C
@@ -1,7 +1,5 @@
// PR c++/89565
// { dg-do compile { target c++20 } }
-// { dg-additional-options "-fchecking" }
-// { dg-ice "resolve_args" }
template <auto>
struct N{};
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C
new file mode 100644
index 0000000..e7addf5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class45.C
@@ -0,0 +1,32 @@
+// PR c++/99200
+// { dg-do compile { target c++20 } }
+
+template <int N>
+struct A
+{
+ constexpr A (const char (&s)[N]) { for (int i = 0; i < N; i++) v[i] = s[i]; v[N] = 0; }
+ char v[N + 1];
+};
+
+template <A s>
+struct B
+{
+ constexpr operator const char *() { return s.v; }
+};
+
+template <typename T>
+const char *
+foo ()
+{
+ return B<__PRETTY_FUNCTION__>{};
+}
+
+template <typename T>
+const char *
+bar ()
+{
+ return B<__FUNCTION__>{};
+}
+
+auto a = foo <int> ();
+auto b = bar <double> ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class46.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class46.C
new file mode 100644
index 0000000..d91e800
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class46.C
@@ -0,0 +1,11 @@
+// PR c++/93383
+// { dg-do compile { target c++20 } }
+
+template <int> struct A {};
+
+template <A a> struct B {
+ void foo(B<+a>);
+ void bar(B<a.x>);
+ template <class T> using type = B<T{}>;
+ template <class> static inline auto y = A{0}; // { dg-error "deduction|no match" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class47.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class47.C
new file mode 100644
index 0000000..1f31b9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class47.C
@@ -0,0 +1,11 @@
+// PR c++/95291
+// { dg-do compile { target c++20 } }
+
+template <typename T = int>
+class xy { };
+
+template <xy _size>
+struct window_root { };
+
+template <typename minion>
+struct flip_horizontally : window_root<minion::size> { };
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class48.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class48.C
new file mode 100644
index 0000000..9024436
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/nontype-class48.C
@@ -0,0 +1,36 @@
+// PR c++/99683
+// { dg-do compile { target c++20 } }
+
+template<auto V>
+struct nttp_tag {};
+
+template<typename T>
+struct type_tag {};
+
+
+/************************************************/
+template<bool is_type>
+struct use_ctad
+{
+ template<auto V> requires (!is_type)
+ constexpr use_ctad(nttp_tag<V>) {}
+};
+
+template<auto V>
+use_ctad(nttp_tag<V>) -> use_ctad<false>;
+
+/**********************************************/
+template<use_ctad t>
+struct wrapper
+{
+ template<typename Tag>
+ wrapper(Tag);
+};
+
+template<typename Tag>
+wrapper(Tag) -> wrapper<use_ctad{Tag()}>;
+
+int main()
+{
+ wrapper t{nttp_tag<42>{}};
+}