[libstdc++] More
diff mbox series

Message ID bb581959-8bd5-b603-ebf2-f7e2eaa512db@verizon.net
State New
Headers show
Series
  • [libstdc++] More
Related show

Commit Message

Ian Lance Taylor via gcc-patches Nov. 16, 2019, 3:17 a.m. UTC
First of all, the redo of the iterator portion in response to 
https://gcc.gnu.org/ml/gcc-patches/2019-11/msg01467.html passed testing.

This patch contains constexpr char_traits. I also found an old extension 
that had been left out of the constexpr bandwagon that I caught up.

This patch also includes constexpr string_view::copy which depends on 
teh type_traits.

This gets all of p1032 except string::copy (although constexpr 
char_traits should almost enable this too once constexpr string is in).  
I'm done.

This passes on x86_64-linux.

OK?

Comments

Jonathan Wakely Nov. 25, 2019, 9:15 p.m. UTC | #1
On 15/11/19 22:17 -0500, Ed Smith-Rowland via libstdc++ wrote:
>Index: include/bits/stl_algobase.h
>===================================================================
>--- include/bits/stl_algobase.h	(revision 278318)
>+++ include/bits/stl_algobase.h	(working copy)
>@@ -107,6 +107,50 @@
>     }
> 
>   /*
>+   * A constexpr wrapper for __builtin_memmove.

This should say __builtin_memcpy.

>+   * @param __num The number of elements of type _Tp (not bytes).
>+   */
>+  template<typename _Tp>
>+    _GLIBCXX14_CONSTEXPR
>+    inline void*
>+    __memcpy(_Tp* __dst, const _Tp* __src, size_t __num)
>+    {
>+#ifdef __cpp_lib_is_constant_evaluated
>+      if (std::is_constant_evaluated())
>+	{
>+	  for(; __num > 0; --__num)
>+	    *__dst++ = *__src++;
>+	  return __dst;
>+	}
>+      else
>+#endif
>+	return __builtin_memcpy(__dst, __src, sizeof(_Tp) * __num);
>+      return __dst;
>+    }
>+
>+  /*
>+   * A constexpr wrapper for __builtin_memmove.

And this should say __builtin_memset.

>+   * @param __num The number of elements of type _Tp (not bytes).
>+   */
>+  template<typename _Tp>
>+    _GLIBCXX14_CONSTEXPR
>+    inline void*
>+    __memset(_Tp* __dst, _Tp __a, size_t __num)
>+    {
>+#ifdef __cpp_lib_is_constant_evaluated
>+      if (std::is_constant_evaluated())
>+	{
>+	  for(; __num > 0; --__num)
>+	    *__dst = __a;
>+	  return __dst;
>+	}
>+      else
>+#endif
>+	return __builtin_memset(__dst, __a, sizeof(_Tp) * __num);
>+      return __dst;
>+    }

OK for trunk with those two comment fixes. Thanks.
François Dumont Nov. 26, 2019, 6:30 a.m. UTC | #2
I have a patch for the same location so here is my remark that might 
make my patch useless.

Maybe you can even merge it with yours Ed, here it is:

https://gcc.gnu.org/ml/libstdc++/2019-10/msg00072.html

On 11/25/19 10:15 PM, Jonathan Wakely wrote:
> On 15/11/19 22:17 -0500, Ed Smith-Rowland via libstdc++ wrote:
>> Index: include/bits/stl_algobase.h
>> ===================================================================
>> --- include/bits/stl_algobase.h    (revision 278318)
>> +++ include/bits/stl_algobase.h    (working copy)
>> @@ -107,6 +107,50 @@
>>     }
>>
>>   /*
>> +   * A constexpr wrapper for __builtin_memmove.
>
> This should say __builtin_memcpy.
>
>> +   * @param __num The number of elements of type _Tp (not bytes).
>> +   */
>> +  template<typename _Tp>
>> +    _GLIBCXX14_CONSTEXPR
>> +    inline void*
>> +    __memcpy(_Tp* __dst, const _Tp* __src, size_t __num)
>> +    {
>> +#ifdef __cpp_lib_is_constant_evaluated
>> +      if (std::is_constant_evaluated())
>> +    {
>> +      for(; __num > 0; --__num)

for (; __num != 0; --__num)

and make __num prtdiff_t.

would be better here as this way the compiler is able to report bad 
usages rather than silently do nothing.


>> +        *__dst++ = *__src++;
>> +      return __dst;
>> +    }
>> +      else
>> +#endif
>> +    return __builtin_memcpy(__dst, __src, sizeof(_Tp) * __num);
>> +      return __dst;
>> +    }
>> +
>> +  /*
>> +   * A constexpr wrapper for __builtin_memmove.
>
> And this should say __builtin_memset.
>
>> +   * @param __num The number of elements of type _Tp (not bytes).
>> +   */
>> +  template<typename _Tp>
>> +    _GLIBCXX14_CONSTEXPR
>> +    inline void*
>> +    __memset(_Tp* __dst, _Tp __a, size_t __num)
>> +    {
>> +#ifdef __cpp_lib_is_constant_evaluated
>> +      if (std::is_constant_evaluated())
>> +    {
>> +      for(; __num > 0; --__num)
>> +        *__dst = __a;
>> +      return __dst;
>> +    }
>> +      else
>> +#endif
>> +    return __builtin_memset(__dst, __a, sizeof(_Tp) * __num);
>> +      return __dst;
>> +    }
>
> OK for trunk with those two comment fixes. Thanks.
>
>
>

Patch
diff mbox series

Index: include/bits/char_traits.h
===================================================================
--- include/bits/char_traits.h	(revision 278318)
+++ include/bits/char_traits.h	(working copy)
@@ -113,13 +113,13 @@ 
       static _GLIBCXX14_CONSTEXPR const char_type*
       find(const char_type* __s, std::size_t __n, const char_type& __a);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, std::size_t __n);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, std::size_t __n);
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, std::size_t __n, char_type __a);
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -179,18 +179,17 @@ 
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     move(char_type* __s1, const char_type* __s2, std::size_t __n)
     {
       if (__n == 0)
 	return __s1;
-      return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
-						    __n * sizeof(char_type)));
+      return static_cast<_CharT*>(std::__memmove<true>(__s1, __s2, __n));
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     copy(char_type* __s1, const char_type* __s2, std::size_t __n)
     {
@@ -200,7 +199,7 @@ 
     }
 
   template<typename _CharT>
-    typename char_traits<_CharT>::char_type*
+    _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type*
     char_traits<_CharT>::
     assign(char_type* __s, std::size_t __n, char_type __a)
     {
@@ -349,28 +348,28 @@ 
 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+	return static_cast<char_type*>(std::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+	return static_cast<char_type*>(std::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
-	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+	return static_cast<char_type*>(std::__memset(__s, __a, __n));
       }
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -458,27 +457,42 @@ 
 	return wmemchr(__s, __a, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>(std::__memmove<true>(__s1, __s2, __n));
+	else
+#endif
 	return wmemmove(__s1, __s2, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>(std::__memcpy(__s1, __s2, __n));
+	else
+#endif
 	return wmemcpy(__s1, __s2, __n);
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
+#ifdef __cpp_lib_is_constant_evaluated
+	if (std::is_constant_evaluated())
+	  return static_cast<char_type*>(std::__memset(__s, __a, __n));
+	else
+#endif
 	return wmemset(__s, __a, __n);
       }
 
@@ -567,28 +581,28 @@ 
 	return static_cast<const char_type*>(__builtin_memchr(__s, __a, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memmove(__s1, __s2, __n));
+	return static_cast<char_type*>(std::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return static_cast<char_type*>(__builtin_memcpy(__s1, __s2, __n));
+	return static_cast<char_type*>(std::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	if (__n == 0)
 	  return __s;
-	return static_cast<char_type*>(__builtin_memset(__s, __a, __n));
+	return static_cast<char_type*>(std::__memset(__s, __a, __n));
       }
 
       static _GLIBCXX_CONSTEXPR char_type
@@ -680,25 +694,23 @@ 
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+	return static_cast<char_type*>(std::__memmove<true>(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+	return static_cast<char_type*>(std::__memcpy(__s1, __s2, __n));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
@@ -783,25 +795,23 @@ 
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))));
+	return (static_cast<char_type*>(std::__memmove<true>(__s1, __s2, __n)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       { 
 	if (__n == 0)
 	  return __s1;
-	return (static_cast<char_type*>
-		(__builtin_memcpy(__s1, __s2, __n * sizeof(char_type))));
+	return (static_cast<char_type*>(std::__memcpy(__s1, __s2, __n)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
Index: include/bits/stl_algobase.h
===================================================================
--- include/bits/stl_algobase.h	(revision 278318)
+++ include/bits/stl_algobase.h	(working copy)
@@ -107,6 +107,50 @@ 
     }
 
   /*
+   * A constexpr wrapper for __builtin_memmove.
+   * @param __num The number of elements of type _Tp (not bytes).
+   */
+  template<typename _Tp>
+    _GLIBCXX14_CONSTEXPR
+    inline void*
+    __memcpy(_Tp* __dst, const _Tp* __src, size_t __num)
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	{
+	  for(; __num > 0; --__num)
+	    *__dst++ = *__src++;
+	  return __dst;
+	}
+      else
+#endif
+	return __builtin_memcpy(__dst, __src, sizeof(_Tp) * __num);
+      return __dst;
+    }
+
+  /*
+   * A constexpr wrapper for __builtin_memmove.
+   * @param __num The number of elements of type _Tp (not bytes).
+   */
+  template<typename _Tp>
+    _GLIBCXX14_CONSTEXPR
+    inline void*
+    __memset(_Tp* __dst, _Tp __a, size_t __num)
+    {
+#ifdef __cpp_lib_is_constant_evaluated
+      if (std::is_constant_evaluated())
+	{
+	  for(; __num > 0; --__num)
+	    *__dst = __a;
+	  return __dst;
+	}
+      else
+#endif
+	return __builtin_memset(__dst, __a, sizeof(_Tp) * __num);
+      return __dst;
+    }
+
+  /*
    * A constexpr wrapper for __builtin_memcmp.
    * @param __num The number of elements of type _Tp (not bytes).
    */
Index: include/ext/pod_char_traits.h
===================================================================
--- include/ext/pod_char_traits.h	(revision 278318)
+++ include/ext/pod_char_traits.h	(working copy)
@@ -56,7 +56,7 @@ 
       value_type	value;
 
       template<typename V2>
-        static char_type
+        static _GLIBCXX_CONSTEXPR char_type
         from(const V2& v)
         {
 	  char_type ret = { static_cast<value_type>(v) };
@@ -64,7 +64,7 @@ 
 	}
 
       template<typename V2>
-        static V2
+        static _GLIBCXX_CONSTEXPR V2
         to(const char_type& c)
         {
 	  V2 ret = { static_cast<V2>(c.value) };
@@ -74,13 +74,13 @@ 
     };
 
   template<typename _Value, typename _Int, typename _St>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator==(const character<_Value, _Int, _St>& lhs,
 	       const character<_Value, _Int, _St>& rhs)
     { return lhs.value == rhs.value; }
 
   template<typename _Value, typename _Int, typename _St>
-    inline bool
+    inline _GLIBCXX_CONSTEXPR bool
     operator<(const character<_Value, _Int, _St>& lhs,
 	      const character<_Value, _Int, _St>& rhs)
     { return lhs.value < rhs.value; }
@@ -102,19 +102,19 @@ 
       typedef fpos<state_type>				pos_type;
       typedef streamoff					off_type;
 
-      static void
+      static _GLIBCXX14_CONSTEXPR void
       assign(char_type& __c1, const char_type& __c2)
       { __c1 = __c2; }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       eq(const char_type& __c1, const char_type& __c2)
       { return __c1 == __c2; }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       lt(const char_type& __c1, const char_type& __c2)
       { return __c1 < __c2; }
 
-      static int
+      static _GLIBCXX14_CONSTEXPR int
       compare(const char_type* __s1, const char_type* __s2, size_t __n)
       {
 	for (size_t __i = 0; __i < __n; ++__i)
@@ -123,7 +123,7 @@ 
 	return 0;
       }
 
-      static size_t
+      static _GLIBCXX14_CONSTEXPR size_t
       length(const char_type* __s)
       {
 	const char_type* __p = __s;
@@ -132,7 +132,7 @@ 
 	return (__p - __s);
       }
 
-      static const char_type*
+      static _GLIBCXX14_CONSTEXPR const char_type*
       find(const char_type* __s, size_t __n, const char_type& __a)
       {
 	for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p)
@@ -141,7 +141,7 @@ 
 	return 0;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       move(char_type* __s1, const char_type* __s2, size_t __n)
       { 
 	if (__n == 0)
@@ -150,7 +150,7 @@ 
 	  (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)));
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       copy(char_type* __s1, const char_type* __s2, size_t __n)
       {
 	if (__n == 0)
@@ -159,7 +159,7 @@ 
 	return __s1;
       }
 
-      static char_type*
+      static _GLIBCXX20_CONSTEXPR char_type*
       assign(char_type* __s, size_t __n, char_type __a)
       {
 	std::fill_n(__s, __n, __a);
@@ -166,19 +166,19 @@ 
         return __s;
       }
 
-      static char_type
+      static _GLIBCXX_CONSTEXPR char_type
       to_char_type(const int_type& __i)
       { return char_type::template from(__i); }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       to_int_type(const char_type& __c)
       { return char_type::template to<int_type>(__c); }
 
-      static bool
+      static _GLIBCXX_CONSTEXPR bool
       eq_int_type(const int_type& __c1, const int_type& __c2)
       { return __c1 == __c2; }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       eof() 
       {
 	int_type __r = { static_cast<typename __gnu_cxx::__conditional_type
@@ -187,7 +187,7 @@ 
 	return __r;
       }
 
-      static int_type
+      static _GLIBCXX_CONSTEXPR int_type
       not_eof(const int_type& __c)
       { return eq_int_type(__c, eof()) ? int_type() : __c; }
     };
Index: testsuite/21_strings/char_traits/requirements/char/constexpr.cc
===================================================================
--- testsuite/21_strings/char_traits/requirements/char/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/char_traits/requirements/char/constexpr.cc	(working copy)
@@ -0,0 +1,42 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+
+constexpr bool
+test()
+{
+  auto ok = true;
+
+  char casv[8]{"ello, W"};
+
+  char das[8]{};
+  std::char_traits<char>::move(das, casv, 7);
+  std::char_traits<char>::copy(das, casv, 7);
+  std::char_traits<char>::assign(das, 7, 'x');
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc
===================================================================
--- testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/char_traits/requirements/wchar_t/constexpr.cc	(working copy)
@@ -0,0 +1,42 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string>
+
+constexpr bool
+test()
+{
+  auto ok = true;
+
+  wchar_t cawsv[8]{L"ello, W"};
+
+  wchar_t wdas[8]{};
+  std::char_traits<wchar_t>::move(wdas, cawsv, 7);
+  std::char_traits<wchar_t>::copy(wdas, cawsv, 7);
+  std::char_traits<wchar_t>::assign(wdas, 7, L'x');
+
+  return ok;
+}
+
+int
+main()
+{
+  static_assert(test());
+}
Index: include/std/string_view
===================================================================
--- include/std/string_view	(revision 278318)
+++ include/std/string_view	(working copy)
@@ -252,6 +252,7 @@ 
 
       // [string.view.ops], string operations:
 
+      _GLIBCXX20_CONSTEXPR
       size_type
       copy(_CharT* __str, size_type __n, size_type __pos = 0) const
       {
Index: testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc
===================================================================
--- testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc	(working copy)
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string_view>
+
+constexpr bool
+test_string_view()
+{
+  auto ok = true;
+
+  constexpr std::string_view sv = "Hello, World!!!";
+  char casv[8]{};
+  sv.copy(casv, 7, 1);
+
+  ok = ok && (casv[0] == 'e');
+
+  return ok;
+}
+
+static_assert(test_string_view());
Index: testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc
===================================================================
--- testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc	(nonexistent)
+++ testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc	(working copy)
@@ -0,0 +1,37 @@ 
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+//
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <string_view>
+
+constexpr bool
+test_string_view()
+{
+  auto ok = true;
+
+  constexpr std::wstring_view wsv = L"Hello, World!!!";
+  wchar_t cawsv[8]{};
+  wsv.copy(cawsv, 7, 1);
+
+  ok = ok && (cawsv[0] == L'e');
+
+  return ok;
+}
+
+static_assert(test_string_view());