aboutsummaryrefslogtreecommitdiff
path: root/gcc/testsuite/g++.dg/cpp23
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2023-12-14 10:18:48 -0500
committerPatrick Palka <ppalka@redhat.com>2023-12-14 10:18:48 -0500
commit83088b331cde0843d65d316e554873ef6d7b6bca (patch)
tree1754c8a755e1ffcc6fb44de99142316005ef6506 /gcc/testsuite/g++.dg/cpp23
parentd782ec8362eadc3169286eb1e39c631effd02323 (diff)
downloadgcc-83088b331cde0843d65d316e554873ef6d7b6bca.zip
gcc-83088b331cde0843d65d316e554873ef6d7b6bca.tar.gz
gcc-83088b331cde0843d65d316e554873ef6d7b6bca.tar.bz2
c++: Implement P2582R1, CTAD from inherited constructors
This patch implements C++23 class template argument deduction from inherited constructors, the mechanism for which relies on alias CTAD which we already fully support. The process for transforming the return type of an inherited guide is specified in terms of a partially specialized class template, but this patch implements it in a simpler way, effectively performing ahead of time deduction instead of instantiation time deduction. I wasn't able to find an example for which this implementation strategy makes a difference, but I didn't look very hard. Support seems good enough to advertise as complete but there doesn't seem to be a feature-test macro update for this feature yet. There should be no functional change before C++23 mode. There's a couple of FIXMEs, one in inherited_ctad_tweaks for recognizing more forms of inherited constructors, and one in deduction_guides_for for making the cache aware of base-class dependencies. gcc/cp/ChangeLog: * cp-tree.h (type_targs_deducible_from): Adjust return type. * pt.cc (alias_ctad_tweaks): Also handle C++23 inherited CTAD. (inherited_ctad_tweaks): Define. (type_targs_deducible_from): Return the deduced arguments or NULL_TREE instead of a bool. Handle 'tmpl' being a TREE_LIST representing a synthetic alias template. (ctor_deduction_guides_for): Do inherited_ctad_tweaks for each USING_DECL in C++23 mode. (deduction_guides_for): Add FIXME for stale cache entries in light of inherited CTAD. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/class-deduction67.C: Accept in C++23 mode. * g++.dg/cpp23/class-deduction-inherited1.C: New test. * g++.dg/cpp23/class-deduction-inherited2.C: New test. * g++.dg/cpp23/class-deduction-inherited3.C: New test. * g++.dg/cpp23/class-deduction-inherited4.C: New test.
Diffstat (limited to 'gcc/testsuite/g++.dg/cpp23')
-rw-r--r--gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C32
4 files changed, 112 insertions, 0 deletions
diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C
new file mode 100644
index 0000000..5fd1270
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited1.C
@@ -0,0 +1,38 @@
+// Modified example from P2582R1
+// { dg-do compile { target c++23 } }
+
+template <typename T> struct B {
+ B(T);
+};
+B(bool) -> B<char>;
+template <typename T> struct C : public B<T> {
+ using B<T>::B;
+};
+template <typename T> struct D : public B<T> {};
+
+C c(42); // OK, deduces C<int>
+using ty1 = decltype(c);
+using ty1 = C<int>;
+
+D d(42); // { dg-error "deduction|no match" }
+
+C c2(true); // OK, deduces C<char>
+using ty2 = decltype(c2);
+using ty2 = C<char>;
+
+template <typename T> struct E : public B<int> {
+ using B<int>::B;
+};
+
+E e(42); // { dg-error "deduction|no match" }
+
+template <typename T, typename U, typename V> struct F {
+ F(T, U, V);
+};
+template <typename T, typename U> struct G : F<U, T, int> {
+ using F<U, T, int>::F;
+};
+
+G g(true, 'a', 1); // OK, deduces G<char, bool>
+using ty3 = decltype(g);
+using ty3 = G<char, bool>;
diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C
new file mode 100644
index 0000000..cb3c595
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited2.C
@@ -0,0 +1,26 @@
+// { dg-do compile { target c++23 } }
+
+template<class T, class U, class V> struct F {
+ F(T, U, V); // #1
+ F(T*, U*, V*); // #2
+ template<class W>
+ F(int, int, W); // #3
+};
+
+F(bool, bool, bool) -> F<bool*, void*, int>;
+
+template<class T, class U> struct G : F<U, T, int> {
+ using F<U, T, int>::F;
+};
+
+using ty1 = decltype(G(true, 'a', 1)); // uses #1
+using ty1 = G<char, bool>;
+
+using ty2 = decltype(G((bool*)0, (char*)0, (int*)0)); // uses #2
+using ty2 = G<char, bool>;
+
+using ty3 = decltype(G(0, 0, 0)); // uses #3
+using ty3 = G<int, int>;
+
+using ty4 = decltype(G(true, true, true)); // uses #4
+using ty4 = G<void*, bool*>;
diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C
new file mode 100644
index 0000000..57e323b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited3.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++23 } }
+
+template<class T>
+struct A {
+ A(T);
+ template<class U> A(T, U);
+};
+
+template<class T>
+struct B : A<const T> {
+ using A<const T>::A;
+};
+
+using type = decltype(B(0));
+using type = decltype(B(0, 0));
+using type = B<int>;
diff --git a/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C
new file mode 100644
index 0000000..5e3a7f4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/class-deduction-inherited4.C
@@ -0,0 +1,32 @@
+// { dg-do compile { target c++23 } }
+
+template<class T>
+struct A { A(T); };
+
+template<class T>
+struct B : A<T> {
+ using B::A::A; // FIXME: we don't notice this inherited ctor
+};
+
+using ty1 = decltype(B(0)); // { dg-bogus "" "" { xfail *-*-* } }
+using ty1 = B<int>;
+
+template<class T=void>
+struct C : A<int> {
+ using A<int>::A; // FIXME: we don't notice this one either
+};
+
+using ty2 = decltype(C(0)); // { dg-bogus "" "" { xfail *-*-* } }
+using ty2 = C<void>;
+
+template<class T>
+struct D : A<T> {
+ using A<T>::A;
+};
+
+using ty3 = decltype(D(0));
+using ty3 = D<int>;
+
+A(int) -> A<char>; // FIXME: we need to rebuild the guides of D
+using ty4 = decltype(D(0));
+using ty4 = D<char>; // { dg-bogus "conflicting" "" { xfail *-*-* } }