]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Implement UDL changes from P0732R2.
authorJason Merrill <jason@redhat.com>
Mon, 5 Nov 2018 07:47:05 +0000 (02:47 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 5 Nov 2018 07:47:05 +0000 (02:47 -0500)
Implementing the UDL changes was pretty straightforward; I simplified
cp_parser_userdef_string_literal using the releasing_vec type from mangle.c.

While looking at this, I realized that the string UDL template taking a
character pack that we implemented for C++14 didn't actually make it into
C++14, so I've added a pedwarn for it and no longer suggest it in the
diagnostic about an invalid UDL template.

* cp-tree.h (struct releasing_vec): Move from mangle.c.
Add get_ref method.
* parser.c (cp_parser_userdef_string_literal): Use it.  Handle
passing the string to a single template parameter of class type.
(cp_parser_template_declaration_after_parameters): Allow it.
Pedwarn about the character pack template that was proposed but not
accepted for C++14, and don't suggest it.

From-SVN: r265790

12 files changed:
gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/mangle.c
gcc/cp/parser.c
gcc/testsuite/g++.dg/cpp0x/udlit-overflow.C
gcc/testsuite/g++.dg/cpp1y/pr58708.C
gcc/testsuite/g++.dg/cpp1y/pr59867.C
gcc/testsuite/g++.dg/cpp1y/udlit-char-template-sfinae.C
gcc/testsuite/g++.dg/cpp1y/udlit-char-template-vs-std-literal-operator.C
gcc/testsuite/g++.dg/cpp1y/udlit-char-template.C
gcc/testsuite/g++.dg/cpp1y/udlit-char-template2.C
gcc/testsuite/g++.dg/cpp2a/nontype-class6.C [new file with mode: 0644]

index 95149b19656a7326eb471ac14719c615557a0b87..b0dc668d9df4c61da4026ed54142b02230f2713d 100644 (file)
@@ -1,5 +1,14 @@
 2018-11-04  Jason Merrill  <jason@redhat.com>
 
+       Implement UDL changes from P0732R2.
+       * cp-tree.h (struct releasing_vec): Move from mangle.c.
+       Add get_ref method.
+       * parser.c (cp_parser_userdef_string_literal): Use it.  Handle
+       passing the string to a single template parameter of class type.
+       (cp_parser_template_declaration_after_parameters): Allow it.
+       Pedwarn about the character pack template that was proposed but not
+       accepted for C++14, and don't suggest it.
+
        Implement P0732R2, class types in non-type template parameters.
        * error.c (dump_simple_decl): Look through a template parm object.
        * mangle.c (write_template_arg): Likewise.
index 61b431e5f9d816721b6d880e7b19a7ba2c79c54e..a895d0042abadf7a8f63fc337ed6dffb8f0ee85d 100644 (file)
@@ -871,6 +871,34 @@ struct named_decl_hash : ggc_remove <tree>
   static void mark_deleted (value_type) { gcc_unreachable (); }
 };
 
+/* Simplified unique_ptr clone to release a tree vec on exit.  */
+
+struct releasing_vec
+{
+  typedef vec<tree, va_gc> vec_t;
+
+  releasing_vec (vec_t *v): v(v) { }
+  releasing_vec (): v(make_tree_vector ()) { }
+
+  /* Copy ops are deliberately declared but not defined,
+     copies must always be elided.  */
+  releasing_vec (const releasing_vec &);
+  releasing_vec &operator= (const releasing_vec &);
+
+  vec_t &operator* () const { return *v; }
+  vec_t *operator-> () const { return v; }
+  vec_t *get() const { return v; }
+  operator vec_t *() const { return v; }
+  tree& operator[] (unsigned i) const { return (*v)[i]; }
+
+  /* Necessary for use with vec** and vec*& interfaces.  */
+  vec_t *&get_ref () { return v; }
+
+  ~releasing_vec() { release_tree_vector (v); }
+private:
+  vec_t *v;
+};
+
 struct GTY(()) tree_template_decl {
   struct tree_decl_common common;
   tree arguments;
index 1b323015dedf4485eba4cf54cbe943889537fa80..b9d8ee2011606f8dfa250187fe5c203817bbe8a5 100644 (file)
@@ -1545,30 +1545,6 @@ write_abi_tags (tree tags)
   release_tree_vector (vec);
 }
 
-/* Simplified unique_ptr clone to release a tree vec on exit.  */
-
-struct releasing_vec
-{
-  typedef vec<tree, va_gc> vec_t;
-
-  releasing_vec (vec_t *v): v(v) { }
-  releasing_vec (): v(make_tree_vector ()) { }
-
-  /* Copy constructor is deliberately declared but not defined,
-     copies must always be elided.  */
-  releasing_vec (const releasing_vec &);
-
-  vec_t &operator* () const { return *v; }
-  vec_t *operator-> () const { return v; }
-  vec_t *get () const { return v; }
-  operator vec_t *() const { return v; }
-  tree& operator[] (unsigned i) const { return (*v)[i]; }
-
-  ~releasing_vec() { release_tree_vector (v); }
-private:
-  vec_t *v;
-};
-
 /* True iff the TREE_LISTS T1 and T2 of ABI tags are equivalent.  */
 
 static bool
index 5ea8e8ca0124cfea3c807d557f2a577b1078fbed..30a47662f5561b6aa3231e85bcd4466d09c4ccdc 100644 (file)
@@ -4565,40 +4565,47 @@ cp_parser_userdef_string_literal (tree literal)
   tree value = USERDEF_LITERAL_VALUE (literal);
   int len = TREE_STRING_LENGTH (value)
        / TREE_INT_CST_LOW (TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (value)))) - 1;
-  tree decl, result;
-  vec<tree, va_gc> *args;
+  tree decl;
 
   /* Build up a call to the user-defined operator.  */
   /* Lookup the name we got back from the id-expression.  */
-  args = make_tree_vector ();
+  releasing_vec rargs;
+  vec<tree, va_gc> *&args = rargs.get_ref();
   vec_safe_push (args, value);
   vec_safe_push (args, build_int_cst (size_type_node, len));
   decl = lookup_literal_operator (name, args);
 
   if (decl && decl != error_mark_node)
-    {
-      result = finish_call_expr (decl, &args, false, true,
-                                tf_warning_or_error);
-      release_tree_vector (args);
-      return result;
-    }
-  release_tree_vector (args);
+    return finish_call_expr (decl, &args, false, true,
+                            tf_warning_or_error);
 
-  /* Look for a template function with typename parameter CharT
-     and parameter pack CharT...  Call the function with
-     template parameter characters representing the string.  */
-  args = make_tree_vector ();
+  /* Look for a suitable template function, either (C++20) with a single
+     parameter of class type, or (N3599) with typename parameter CharT and
+     parameter pack CharT...  */
+  args->truncate (0);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
-      tree tmpl_args = make_string_pack (value);
+      /* Use resolve_nondeduced_context to try to choose one form of template
+        or the other.  */
+      tree tmpl_args = make_tree_vec (1);
+      TREE_VEC_ELT (tmpl_args, 0) = value;
       decl = lookup_template_function (decl, tmpl_args);
-      result = finish_call_expr (decl, &args, false, true,
-                                tf_warning_or_error);
-      release_tree_vector (args);
-      return result;
+      tree res = resolve_nondeduced_context (decl, tf_none);
+      if (DECL_P (res))
+       decl = res;
+      else
+       {
+         TREE_OPERAND (decl, 1) = make_string_pack (value);
+         res = resolve_nondeduced_context (decl, tf_none);
+         if (DECL_P (res))
+           decl = res;
+       }
+      if (!DECL_P (decl) && cxx_dialect > cxx17)
+       TREE_OPERAND (decl, 1) = tmpl_args;
+      return finish_call_expr (decl, &args, false, true,
+                              tf_warning_or_error);
     }
-  release_tree_vector (args);
 
   error ("unable to find string literal operator %qD with %qT, %qT arguments",
         name, TREE_TYPE (value), size_type_node);
@@ -27222,8 +27229,12 @@ 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 (TREE_TYPE (parm) != char_type_node
-                 || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
+             if (CLASS_TYPE_P (TREE_TYPE (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.  */;
+             else if (TREE_TYPE (parm) != char_type_node
+                      || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
            }
          else if (num_parms == 2 && cxx_dialect >= cxx14)
@@ -27236,20 +27247,25 @@ cp_parser_template_declaration_after_parameters (cp_parser* parser,
                  || TREE_TYPE (parm) != TREE_TYPE (type)
                  || !TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm)))
                ok = false;
+             else
+               /* http://cplusplus.github.io/EWG/ewg-active.html#66  */
+               pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wpedantic,
+                        "ISO C++ did not adopt string literal operator templa"
+                        "tes taking an argument pack of characters");
            }
          else
            ok = false;
        }
       if (!ok)
        {
-         if (cxx_dialect >= cxx14)
-           error ("literal operator template %qD has invalid parameter list."
-                  "  Expected non-type template argument pack <char...>"
-                  " or <typename CharT, CharT...>",
+         if (cxx_dialect > cxx17)
+           error ("literal operator template %qD has invalid parameter list;"
+                  "  Expected non-type template parameter pack <char...> "
+                  "  or single non-type parameter of class type",
                   decl);
          else
            error ("literal operator template %qD has invalid parameter list."
-                  "  Expected non-type template argument pack <char...>",
+                  "  Expected non-type template parameter pack <char...>",
                   decl);
        }
     }
index 057978c32752f60e99599d2e6172d6077a07c322..1b9888b7159d2f24bff3837c6513271006469c37 100644 (file)
@@ -1,19 +1,19 @@
 // { dg-do compile { target c++11 } }
-// PR c++/52654\r
-\r
-int\r
-operator"" _w(const char*)\r
-{ return 0; }\r
-\r
-template<char...>\r
-  int\r
-  operator"" _tw()\r
-  { return 0; }\r
-\r
-int i = 12345678901234567890123456789012345678901234567890_w;\r
-int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w;\r
-int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w;\r
-\r
-int ti = 12345678901234567890123456789012345678901234567890_tw;\r
-int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw;\r
-int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw;\r
+// PR c++/52654
+
+int
+operator"" _w(const char*)
+{ return 0; }
+
+template<char...>
+  int
+  operator"" _tw()
+  { return 0; }
+
+int i = 12345678901234567890123456789012345678901234567890_w;
+int j = 12345678901234567890123456789.012345678901234567890e+1234567890_w;
+int k = 12345678901234567890123456789.012345678901234567890e-1234567890_w;
+
+int ti = 12345678901234567890123456789012345678901234567890_tw;
+int tj = 12345678901234567890123456789.012345678901234567890e+1234567890_tw;
+int tk = 12345678901234567890123456789.012345678901234567890e-1234567890_tw;
index b46e54bbca3e3dddc6a9f315d64719bc0b44e132..f1fc3b4622762b63dd883fcab14b6f79ac73fe37 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do run { target c++14 } }
+// { dg-options -w }
 
 template<typename, typename>
   struct is_same
index 2c4f1d046bf30099e74efa85b7b01d9643975f62..ee468aabb2b4426556e39ea4542918cf55234f62 100644 (file)
@@ -1,5 +1,6 @@
 // PR c++/59867
 // { dg-do compile { target c++14 } }
+// { dg-options -w }
 
 using namespace std;
 
index a9c577fd110f073d4c42738e3c4679215d891730..b523858e9c0934675d60ab2869e6c9035d1a7dff 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do run { target c++14 } }
+// { dg-options -w }
 
 #include <cassert>
 
index 6e3ffe4ecd359cabbce287180110758a5d32ad4e..c5a67c96cf6b4f184bbe4d531f47e226ba83b94d 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do run { target c++14 } }
+// { dg-options -w }
 
 #include <cassert>
 
index 989b9babd1f61052494552ca01727fd2b5c70d8d..6b7b5ecec6fffcefd72659076bce5a3fe76c37ca 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do compile { target c++14 } }
+// { dg-options -w }
 
 template<typename CharT, CharT... String>
   int
index 06c13261156e046532e548f4ce51c1130768c8a2..d3c4c67ea26b73e4c25e293ce4b6e9792856dae7 100644 (file)
@@ -1,5 +1,6 @@
 // PR c++/85864
 // { dg-do compile { target c++14 } }
+// { dg-options -w }
 
 template<class T, T... S> struct String_template {};
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/nontype-class6.C b/gcc/testsuite/g++.dg/cpp2a/nontype-class6.C
new file mode 100644 (file)
index 0000000..246fab6
--- /dev/null
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++2a } }
+
+struct A {
+  char ar[10];
+  constexpr A (const char *p) : ar()
+  {
+    for (int i = 0; i < 10; ++i)
+      if ((ar[i] = p[i]) == 0)
+       break;
+  }
+  // auto operator<=> (const A&) = default;
+};
+
+template <A a> constexpr A operator "" _sh() { return a; }
+
+constexpr auto a = "foo"_sh;
+static_assert (a.ar[0] == 'f');