Commit 8744c37d by Tom Honermann Committed by Jason Merrill

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  <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.

gcc/testsuite/ChangeLog:

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.

From-SVN: r274123
parent 719f5a10
2019-08-05 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-08-05 Marek Polacek <polacek@redhat.com> 2019-08-05 Marek Polacek <polacek@redhat.com>
PR c++/91338 - Implement P1161R3: Deprecate a[b,c]. PR c++/91338 - Implement P1161R3: Deprecate a[b,c].
......
...@@ -28169,7 +28169,10 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, ...@@ -28169,7 +28169,10 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
{ {
tree parm_list = TREE_VEC_ELT (parameter_list, 0); tree parm_list = TREE_VEC_ELT (parameter_list, 0);
tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); 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 /* OK, C++20 string literal operator template. We don't need
to warn in lower dialects here because we will have already to warn in lower dialects here because we will have already
warned about the template parameter. */; warned about the template parameter. */;
...@@ -28183,7 +28186,7 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser, ...@@ -28183,7 +28186,7 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
tree type = INNERMOST_TEMPLATE_PARMS (parm_type); tree type = INNERMOST_TEMPLATE_PARMS (parm_type);
tree parm_list = TREE_VEC_ELT (parameter_list, 1); tree parm_list = TREE_VEC_ELT (parameter_list, 1);
tree parm = INNERMOST_TEMPLATE_PARMS (parm_list); tree parm = INNERMOST_TEMPLATE_PARMS (parm_list);
if (parm == error_mark_node if (TREE_CODE (parm) != PARM_DECL
|| TREE_TYPE (parm) != TREE_TYPE (type) || TREE_TYPE (parm) != TREE_TYPE (type)
|| !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))) || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
ok = false; ok = false;
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-08-05 Steven g. Kargl <kargl@gcc.gnu.org> 2019-08-05 Steven g. Kargl <kargl@gcc.gnu.org>
PR fortran/91372 PR fortran/91372
......
// 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 }
// 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" }
// 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);
// 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" }
// 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" }
// 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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment