aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2021-04-09 18:02:38 -0400
committerJason Merrill <jason@redhat.com>2021-04-10 00:06:55 -0400
commit1a19d334ce493ec2ce2daeac74beef63fd67e2bc (patch)
tree86eb0cba26a951cf3f65afb782d031b1b1a6e150
parente89055f90cff9fb6f565b9374e1ab74f805682fb (diff)
downloadgcc-1a19d334ce493ec2ce2daeac74beef63fd67e2bc.zip
gcc-1a19d334ce493ec2ce2daeac74beef63fd67e2bc.tar.gz
gcc-1a19d334ce493ec2ce2daeac74beef63fd67e2bc.tar.bz2
c++: deduction guide using alias [PR99180]
alias_ctad_tweaks was expecting that all deduction guides for the class would be suitable for deduction from the alias definition; in this case, the deduction guide uses 'true' and the alias B uses 'false', so deduction fails. But that's OK, we just don't use that deduction guide. I also noticed that we were giving up on deduction entirely if substitution failed for some guide; we should only give up on that particular deduction guide. We ought to give a better diagnostic about this case when deduction fails, but that can wait. gcc/cp/ChangeLog: PR c++/99180 PR c++/93295 PR c++/93867 PR c++/99118 PR c++/96873 * pt.c (alias_ctad_tweaks): Handle failure better. gcc/testsuite/ChangeLog: PR c++/99180 PR c++/93295 PR c++/93867 PR c++/95486 * g++.dg/cpp2a/class-deduction-alias5.C: New test. * g++.dg/cpp2a/class-deduction-alias6.C: New test. * g++.dg/cpp2a/class-deduction-alias7.C: New test. * g++.dg/cpp2a/class-deduction-alias8.C: New test.
-rw-r--r--gcc/cp/pt.c7
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias5.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias6.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias7.C32
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias8.C14
5 files changed, 79 insertions, 3 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b32833003..abd1ad4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29042,7 +29042,8 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
unsigned len = TREE_VEC_LENGTH (ftparms);
tree targs = make_tree_vec (len);
int err = unify (ftparms, targs, ret, utype, UNIFY_ALLOW_NONE, false);
- gcc_assert (!err);
+ if (err)
+ continue;
/* The number of parms for f' is the number of parms for A plus
non-deduced parms of f. */
@@ -29075,7 +29076,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
guideness, and explicit-specifier. */
tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain);
if (g == error_mark_node)
- return error_mark_node;
+ continue;
DECL_USE_TEMPLATE (g) = 0;
fprime = build_template_decl (g, gtparms, false);
DECL_TEMPLATE_RESULT (fprime) = g;
@@ -29089,7 +29090,7 @@ alias_ctad_tweaks (tree tmpl, tree uguides)
if (ci)
ci = tsubst_constraint_info (ci, targs, complain, in_decl);
if (ci == error_mark_node)
- return error_mark_node;
+ continue;
/* Add a constraint that the return type matches the instantiation of
A with the same template arguments. */
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias5.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias5.C
new file mode 100644
index 0000000..69143a3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias5.C
@@ -0,0 +1,18 @@
+// PR c++/99180
+// { dg-do compile { target c++17 } }
+
+template <bool, typename... Ts>
+struct A {
+ A(Ts...) {}
+};
+
+template <typename... Ts>
+using B = A<false, Ts...>;
+
+template <typename... Ts>
+A(Ts...) -> A<true, Ts...>;
+
+int main() {
+ B{}; // { dg-error "alias" "" { target c++17_down } }
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias6.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias6.C
new file mode 100644
index 0000000..26a38641
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias6.C
@@ -0,0 +1,11 @@
+// PR c++/93295
+// { dg-do compile { target c++20 } }
+
+template<typename T, bool B = false>
+struct Foo {
+ Foo(T) {}
+};
+
+template<typename T> Foo(T) -> Foo<T>;
+template<typename T> using Bar = Foo<T, true>;
+Bar b{0};
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias7.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias7.C
new file mode 100644
index 0000000..0d8bff7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias7.C
@@ -0,0 +1,32 @@
+// PR c++/93867
+// { dg-do compile { target c++20 } }
+
+template <typename CharT, unsigned N>
+struct basic_fixed_string
+{
+ constexpr basic_fixed_string(const CharT *p) {
+ for (int i = 0; i < N; ++i) {
+ m_data[i] = p[i];
+ }
+ }
+
+ CharT m_data[N] {};
+};
+
+template <typename CharT, unsigned N>
+basic_fixed_string(const CharT (&)[N]) -> basic_fixed_string<CharT,N>;
+
+template <unsigned N>
+using fixed_string = basic_fixed_string<char, N>;
+
+template <fixed_string path>
+constexpr int foo()
+{
+ return 42;
+}
+
+int main(int argc, char const *argv[])
+{
+ foo<"hello">();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias8.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias8.C
new file mode 100644
index 0000000..ec005956
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias8.C
@@ -0,0 +1,14 @@
+// PR c++/95486
+// { dg-do compile { target c++20 } }
+
+template<class T, class U>
+struct X { X(U) requires __is_same(U, int) {} };
+
+template<class U>
+X(U) -> X<char, U>;
+
+template<class U>
+using Y = X<void, U>;
+
+Y y{1};
+Y z{'a'}; // { dg-error "failed|no match" }