Message ID | 58ee7adc-9dd6-f1df-5934-87e6185d24dd@honermann.net |
---|---|
State | New |
Headers | show |
Series | : Fix PR c++/88095, class template argument deduction for literal operator templates per P0732 for C++2a | expand |
On 8/2/19 9:59 AM, Tom Honermann wrote: > This patch fixes PR c++/88095: > - Bug 88095 - class nontype template parameter UDL string literals > doesn't accepts deduction placeholder > - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88095. > > It also addresses a latent issue; literal operator templates with > template parameter packs of literal class type were previously accepted. > The patch corrects this and adds a test (udlit-class-nttp-neg.C). > > In the change to gcc/cp/parser.c, it is not clear to me whether the > 'TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM' comparison is > necessary; it might be that 'CLASS_PLACEHOLDER_TEMPLATE' suffices on its > own. template_placeholder_p would be a shorter way to write these, but I think even better would be to just change CLASS_TYPE_P to MAYBE_CLASS_TYPE_P. I'll make that change and commit the patch, since it looks like you don't have commit access yet. > If accepted, I'd like to request this change be applied to gcc 9 as it > is needed for one of the char8_t remediation approaches documented in > P1423, and may be helpful for existing code bases impacted by the > char8_t changes adopted via P0482 for C++20. > - https://wg21.link/p1423#emulate Seems reasonable. It may be too late to make 9.2 at this point, though. Jason
On 8/5/19 3:05 PM, Jason Merrill wrote: > On 8/2/19 9:59 AM, Tom Honermann wrote: >> This patch fixes PR c++/88095: >> - Bug 88095 - class nontype template parameter UDL string literals >> doesn't accepts deduction placeholder >> - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88095. >> >> It also addresses a latent issue; literal operator templates with >> template parameter packs of literal class type were previously >> accepted. The patch corrects this and adds a test >> (udlit-class-nttp-neg.C). >> >> In the change to gcc/cp/parser.c, it is not clear to me whether the >> 'TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM' comparison is >> necessary; it might be that 'CLASS_PLACEHOLDER_TEMPLATE' suffices on >> its own. > > template_placeholder_p would be a shorter way to write these, but I > think even better would be to just change CLASS_TYPE_P to > MAYBE_CLASS_TYPE_P. I'll make that change and commit the patch, since > it looks like you don't have commit access yet. Thanks, and correct, I don't have commit access yet (and I'm not sure that I should! :) ) > >> If accepted, I'd like to request this change be applied to gcc 9 as >> it is needed for one of the char8_t remediation approaches documented >> in P1423, and may be helpful for existing code bases impacted by the >> char8_t changes adopted via P0482 for C++20. >> - https://wg21.link/p1423#emulate > > Seems reasonable. It may be too late to make 9.2 at this point, though. Is there anything I can/should do to request inclusion? Tom. > > Jason
On Tue, Aug 6, 2019 at 11:10 AM Tom Honermann <tom@honermann.net> wrote: > On 8/5/19 3:05 PM, Jason Merrill wrote: > > On 8/2/19 9:59 AM, Tom Honermann wrote: > >> This patch fixes PR c++/88095: > >> - Bug 88095 - class nontype template parameter UDL string literals > >> doesn't accepts deduction placeholder > >> - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=88095. > >> > >> It also addresses a latent issue; literal operator templates with > >> template parameter packs of literal class type were previously > >> accepted. The patch corrects this and adds a test > >> (udlit-class-nttp-neg.C). > >> > >> In the change to gcc/cp/parser.c, it is not clear to me whether the > >> 'TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM' comparison is > >> necessary; it might be that 'CLASS_PLACEHOLDER_TEMPLATE' suffices on > >> its own. > > > > template_placeholder_p would be a shorter way to write these, but I > > think even better would be to just change CLASS_TYPE_P to > > MAYBE_CLASS_TYPE_P. I'll make that change and commit the patch, since > > it looks like you don't have commit access yet. > Thanks, and correct, I don't have commit access yet (and I'm not sure > that I should! :) ) > > > >> If accepted, I'd like to request this change be applied to gcc 9 as > >> it is needed for one of the char8_t remediation approaches documented > >> in P1423, and may be helpful for existing code bases impacted by the > >> char8_t changes adopted via P0482 for C++20. > >> - https://wg21.link/p1423#emulate > > > > Seems reasonable. It may be too late to make 9.2 at this point, though. > > Is there anything I can/should do to request inclusion? Appeal to Jakub on the 9.2 freeze thread in the gcc mailing list. Jason
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c9091f523c5..a406bba41c5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-08-02 Tom Honermann <tom@honermann.net> + + * parser.c (cp_parser_template_declaration_after_parameters): Enable + class template argument deduction for non-type template parameters in + literal operator templates. + 2019-07-16 Jason Merrill <jason@redhat.com> * parser.c (make_location): Add overload taking cp_lexer* as last diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 1a5da1dd8e8..86f895e96a3 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -28105,7 +28105,10 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, { tree parm_list = TREE_VEC_ELT (parameter_list, 0); tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); - if (CLASS_TYPE_P (TREE_TYPE (parm))) + if ((CLASS_TYPE_P (TREE_TYPE (parm)) + || (TREE_CODE (TREE_TYPE (parm)) == TEMPLATE_TYPE_PARM + && CLASS_PLACEHOLDER_TEMPLATE (TREE_TYPE (parm)))) + && !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) /* OK, C++20 string literal operator template. We don't need to warn in lower dialects here because we will have already warned about the template parameter. */; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f47604da85..c8613deaae6 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2019-08-02 Tom Honermann <tom@honermann.net> + + PR c++/88095 + * g++.dg/cpp2a/udlit-class-nttp-ctad.C: New test. + * g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C: New test. + * g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C: New test. + * g++.dg/cpp2a/udlit-class-nttp.C: New test. + * g++.dg/cpp2a/udlit-class-nttp-neg.C: New test. + * g++.dg/cpp2a/udlit-class-nttp-neg2.C: New test. + 2019-07-18 Jan Hubicka <hubicka@ucw.cz> * g++.dg/lto/alias-5_0.C: New testcase. diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C new file mode 100644 index 00000000000..437fa9b5ab8 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C @@ -0,0 +1,24 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate handling of failed class template argument deduction. +// { dg-do compile { target c++2a } } + +namespace std { +using size_t = decltype(sizeof(int)); +} + +template <typename CharT, std::size_t N> +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +// Missing deduction guide. + +template <fixed_string fs> +constexpr std::size_t operator"" _udl() { + return decltype(fs)::length; +} + +static_assert("test"_udl == 5); // { dg-error "15:no matching function for call to" } + // { dg-error "15:class template argument deduction failed" "" { target *-*-* } .-1 } diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C new file mode 100644 index 00000000000..89bb5d39d7d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C @@ -0,0 +1,20 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate rejection of class template parameter packs. +// { dg-do compile { target c++2a } } + +namespace std { +using size_t = decltype(sizeof(int)); +} + +template <typename CharT, std::size_t N> +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +template <typename CharT, std::size_t N> +fixed_string(const CharT (&str)[N]) -> fixed_string<CharT, N>; + +template <fixed_string...> +int operator"" _udl(); // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" } diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C new file mode 100644 index 00000000000..f6877a960c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C @@ -0,0 +1,24 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate support for class template argument deduction. +// { dg-do compile { target c++2a } } + +namespace std { +using size_t = decltype(sizeof(int)); +} + +template <typename CharT, std::size_t N> +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +template <typename CharT, std::size_t N> +fixed_string(const CharT (&str)[N]) -> fixed_string<CharT, N>; + +template <fixed_string fs> +constexpr std::size_t operator"" _udl() { + return decltype(fs)::length; +} + +static_assert("test"_udl == 5); diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C new file mode 100644 index 00000000000..8f7e3f29511 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C @@ -0,0 +1,12 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate that parameter packs are rejected. +// { dg-do compile { target c++2a } } + +struct literal_class { + constexpr literal_class(...) { } + // auto operator<=> (const fixed_string&) = default; +}; + +template <literal_class...> +int operator"" _udl(); // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" } diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C new file mode 100644 index 00000000000..2c00c5c6b88 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C @@ -0,0 +1,13 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate that non-literal class types are rejected. +// { dg-do compile { target c++2a } } + +struct non_literal_class { + constexpr non_literal_class(...) { } + ~non_literal_class() {} + // auto operator<=> (const non_literal_fixed_string&) = default; +}; + +template <non_literal_class> // { dg-error "11:is not a valid type for a template non-type parameter because it is not literal" } +int operator"" _udl(); // { dg-error "5:literal operator template .int operator\"\"_udl\\(\\). has invalid parameter list" } diff --git a/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C new file mode 100644 index 00000000000..dcaca3e4070 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C @@ -0,0 +1,16 @@ +// PR c++/88095 +// Test class non-type template parameters for literal operator templates. +// Validate basic support. +// { dg-do compile { target c++2a } } + +struct literal_class { + constexpr literal_class(...) { } + // auto operator<=> (const fixed_string&) = default; +}; + +template <literal_class> +constexpr int operator"" _udl() { + return 1; +} + +static_assert("test"_udl == 1);