PR c++/88095, CTAD for literal operator templates per P0732
authorTom Honermann <tom@honermann.net>
Mon, 5 Aug 2019 19:34:23 +0000 (19:34 +0000)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 5 Aug 2019 19:34:23 +0000 (15:34 -0400)
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

gcc/cp/ChangeLog
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad-neg2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-ctad.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp-neg2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/udlit-class-nttp.C [new file with mode: 0644]

index 3e4900c34fecb655d8554acd961c3af952e20990..0c3bdffbcab2cb5218fa6f91d1882293969b1488 100644 (file)
@@ -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].
index 1a5ae147b84535c8468cccb38bf589486e1fc03e..dd2fe79c95a4b339c864b268ba0dac7488f8db41 100644 (file)
@@ -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;
index 917a75f54132afac2b2a6fb09260e6400325e5f8..34a919901ffdfa829d18e224fc82680d6f78a56a 100644 (file)
@@ -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
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 (file)
index 0000000..437fa9b
--- /dev/null
@@ -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 (file)
index 0000000..89bb5d3
--- /dev/null
@@ -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 (file)
index 0000000..f6877a9
--- /dev/null
@@ -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 (file)
index 0000000..8f7e3f2
--- /dev/null
@@ -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 (file)
index 0000000..2c00c5c
--- /dev/null
@@ -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 (file)
index 0000000..dcaca3e
--- /dev/null
@@ -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);