From: Tom Honermann Date: Mon, 12 Aug 2019 17:46:37 +0000 (+0000) Subject: PR c++/88095, CTAD for literal operator templates per P0732 X-Git-Tag: releases/gcc-9.3.0~743 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6e21f7d2cc16e7189e78fbe85c1617d1240268e1;p=thirdparty%2Fgcc.git PR c++/88095, CTAD for literal operator templates per P0732 This patch fixes PR c++/88095: class nontype template parameter UDL string literals doesn't accepts deduction placeholder 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). This fix 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. gcc/cp/ChangeLog: 2019-08-02 Tom Honermann * parser.c (cp_parser_template_declaration_after_parameters): Enable class template argument deduction for non-type template parameters in literal operator templates. gcc/testsuite/ChangeLog: 2019-08-02 Tom Honermann 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. From-SVN: r274317 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 67ce26866bb9..925341d5d473 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2019-08-12 Tom Honermann + + * parser.c (cp_parser_template_declaration_after_parameters): Enable + class template argument deduction for non-type template parameters + in literal operator templates. + 2019-08-12 Jason Merrill PR c++/91378 - ICE with noexcept and auto return type. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a7218e752b16..24d41600f215 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -27911,7 +27911,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 (TREE_CODE (parm) != PARM_DECL) + ok = false; + else if (MAYBE_CLASS_TYPE_P (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. */; @@ -27925,7 +27928,7 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, tree type = INNERMOST_TEMPLATE_PARMS (parm_type); tree parm_list = TREE_VEC_ELT (parameter_list, 1); tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); - if (parm == error_mark_node + if (TREE_CODE (parm) != PARM_DECL || TREE_TYPE (parm) != TREE_TYPE (type) || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) ok = false; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index bc11ae4ae0b0..bb6a5b78f64c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,13 @@ +2019-08-02 Tom Honermann + + 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-08-12 Release Manager * GCC 9.2.0 released. 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 000000000000..437fa9b5ab89 --- /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 +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +// Missing deduction guide. + +template +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 000000000000..0f56b50871bf --- /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 +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +template +fixed_string(const CharT (&str)[N]) -> fixed_string; + +template +int operator"" _udl(); // { dg-error "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 000000000000..f6877a960c95 --- /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 +struct fixed_string { + constexpr static std::size_t length = N; + constexpr fixed_string(...) { } + // auto operator<=> (const fixed_string&) = default; +}; +template +fixed_string(const CharT (&str)[N]) -> fixed_string; + +template +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 000000000000..b5f110bf59b0 --- /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 +int operator"" _udl(); // { dg-error "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 000000000000..20e97fcc6a5e --- /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 // { dg-error "11:is not a valid type for a template non-type parameter because it is not literal" } +int operator"" _udl(); // { dg-error "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 000000000000..dcaca3e40701 --- /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 +constexpr int operator"" _udl() { + return 1; +} + +static_assert("test"_udl == 1);