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
This commit is contained in:
parent
719f5a10e7
commit
8744c37d54
@ -1,3 +1,9 @@
|
||||
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>
|
||||
|
||||
PR c++/91338 - Implement P1161R3: Deprecate a[b,c].
|
||||
|
@ -28169,7 +28169,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. */;
|
||||
@ -28183,7 +28186,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;
|
||||
|
@ -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-08-05 Steven g. Kargl <kargl@gcc.gnu.org>
|
||||
|
||||
PR fortran/91372
|
||||
|
24
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C
Normal file
24
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C
Normal file
@ -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 }
|
20
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C
Normal file
20
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C
Normal file
@ -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" }
|
24
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C
Normal file
24
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C
Normal file
@ -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);
|
12
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C
Normal file
12
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C
Normal file
@ -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" }
|
13
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
Normal file
13
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C
Normal file
@ -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" }
|
16
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C
Normal file
16
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C
Normal file
@ -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);
|
Loading…
Reference in New Issue
Block a user