diff mbox series

: Fix PR c++/88095, class template argument deduction for literal operator templates per P0732 for C++2a

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

Commit Message

Tom Honermann Aug. 2, 2019, 1:59 p.m. UTC
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.

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

Tested on x86_64-linux.

Thanks to Jeff Snyder for providing an initial patch in the 88059 PR.

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.

Comments

Jason Merrill Aug. 5, 2019, 7:05 p.m. UTC | #1
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
Tom Honermann Aug. 6, 2019, 3:10 p.m. UTC | #2
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
Jason Merrill Aug. 6, 2019, 3:12 p.m. UTC | #3
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 mbox series

Patch

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);