From: Patrick Palka Date: Sat, 24 Apr 2021 04:14:29 +0000 (-0400) Subject: c++: do_class_deduction and dependent init [PR93383] X-Git-Tag: basepoints/gcc-13~8213 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=bcd77b7b9f35bd5b559ed593c3b3e346c1e6f364;p=thirdparty%2Fgcc.git 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. --- diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8d64fef957d9..8c3c814ce559 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 512afad8e4fa..9b4da4f02ea0 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 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 000000000000..e7addf5f2912 --- /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 +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 +struct B +{ + constexpr operator const char *() { return s.v; } +}; + +template +const char * +foo () +{ + return B<__PRETTY_FUNCTION__>{}; +} + +template +const char * +bar () +{ + return B<__FUNCTION__>{}; +} + +auto a = foo (); +auto b = bar (); 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 000000000000..d91e800424fc --- /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 struct A {}; + +template struct B { + void foo(B<+a>); + void bar(B); + template using type = B; + template 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 000000000000..1f31b9bd5306 --- /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 +class xy { }; + +template +struct window_root { }; + +template +struct flip_horizontally : window_root { }; 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 000000000000..9024436cad85 --- /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 +struct nttp_tag {}; + +template +struct type_tag {}; + + +/************************************************/ +template +struct use_ctad +{ + template requires (!is_type) + constexpr use_ctad(nttp_tag) {} +}; + +template +use_ctad(nttp_tag) -> use_ctad; + +/**********************************************/ +template +struct wrapper +{ + template + wrapper(Tag); +}; + +template +wrapper(Tag) -> wrapper; + +int main() +{ + wrapper t{nttp_tag<42>{}}; +}