diff options
author | Jason Merrill <jason@redhat.com> | 2021-04-09 18:02:38 -0400 |
---|---|---|
committer | Jason Merrill <jason@redhat.com> | 2021-04-10 00:06:55 -0400 |
commit | 1a19d334ce493ec2ce2daeac74beef63fd67e2bc (patch) | |
tree | 86eb0cba26a951cf3f65afb782d031b1b1a6e150 | |
parent | e89055f90cff9fb6f565b9374e1ab74f805682fb (diff) | |
download | gcc-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.c | 7 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/class-deduction-alias5.C | 18 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/class-deduction-alias6.C | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/class-deduction-alias7.C | 32 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/class-deduction-alias8.C | 14 |
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" } |