From b696698767ba45b4d61a93205167e2f1f744d3f1 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Mon, 6 Apr 2020 18:30:53 +0100 Subject: [PATCH] libstdc++: Make string_view::copy usable in constant expressions (PR 94498) PR libstdc++/94498 * include/bits/char_traits.h (__gnu_cxx::char_traits::move): Make it usable in constant expressions for C++20. (__gnu_cxx::char_traits::copy, __gnu_cxx::char_traits::assign): Add _GLIBCXX20_CONSTEXPR. (std::char_traits, std::char_traits) (std::char_traits): Make move, copy and assign usable in constant expressions for C++20. (std::char_traits, std::char_traits): Make move and copy usable in constant expressions for C++20. * include/std/string_view (basic_string_view::copy): Add _GLIBCXX20_CONSTEXPR. * testsuite/21_strings/basic_string_view/operations/copy/char/ constexpr.cc: New test. * testsuite/21_strings/basic_string_view/operations/copy/wchar_t/ constexpr.cc: New test. --- libstdc++-v3/ChangeLog | 19 ++++ libstdc++-v3/include/bits/char_traits.h | 101 ++++++++++++++---- libstdc++-v3/include/std/string_view | 1 + .../operations/copy/char/constexpr.cc | 32 ++++++ .../operations/copy/wchar_t/constexpr.cc | 32 ++++++ 5 files changed, 167 insertions(+), 18 deletions(-) create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc create mode 100644 libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index eb092792229..4d7b5780189 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,22 @@ +2020-04-06 Jonathan Wakely + + PR libstdc++/94498 + * include/bits/char_traits.h (__gnu_cxx::char_traits::move): Make it + usable in constant expressions for C++20. + (__gnu_cxx::char_traits::copy, __gnu_cxx::char_traits::assign): Add + _GLIBCXX20_CONSTEXPR. + (std::char_traits, std::char_traits) + (std::char_traits): Make move, copy and assign usable in + constant expressions for C++20. + (std::char_traits, std::char_traits): Make move + and copy usable in constant expressions for C++20. + * include/std/string_view (basic_string_view::copy): Add + _GLIBCXX20_CONSTEXPR. + * testsuite/21_strings/basic_string_view/operations/copy/char/ + constexpr.cc: New test. + * testsuite/21_strings/basic_string_view/operations/copy/wchar_t/ + constexpr.cc: New test. + 2020-04-05 Gerald Pfeifer * doc/xml/manual/appendix_contributing.xml: Refer to Git diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 2edb84ca3b8..65031d3ac83 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -113,13 +113,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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,17 +179,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + if (__s1 > __s2 && __s1 < __s2 + __n) + std::copy_backward(__s2, __s2 + __n, __s1); + else + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } +#endif return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, __n * sizeof(char_type))); } template + _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type* char_traits<_CharT>:: copy(char_type* __s1, const char_type* __s2, std::size_t __n) @@ -200,6 +212,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + _GLIBCXX20_CONSTEXPR typename char_traits<_CharT>::char_type* char_traits<_CharT>:: assign(char_type* __s, std::size_t __n, char_type __a) @@ -349,27 +362,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return static_cast(__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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif return static_cast(__builtin_memmove(__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 __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif return static_cast(__builtin_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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif return static_cast(__builtin_memset(__s, __a, __n)); } @@ -458,27 +483,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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 __gnu_cxx::char_traits::move(__s1, __s2, __n); +#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 __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#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 __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif return wmemset(__s, __a, __n); } @@ -567,27 +604,39 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return static_cast(__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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif return static_cast(__builtin_memmove(__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 __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif return static_cast(__builtin_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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif return static_cast(__builtin_memset(__s, __a, __n)); } @@ -680,25 +729,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif return (static_cast (__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) return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif return (static_cast (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); } - 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 +840,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION 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; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif return (static_cast (__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) return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif return (static_cast (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); } - 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) diff --git a/libstdc++-v3/include/std/string_view b/libstdc++-v3/include/std/string_view index 99a81bb04fa..ea1ccc9bb21 100644 --- a/libstdc++-v3/include/std/string_view +++ b/libstdc++-v3/include/std/string_view @@ -263,6 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [string.view.ops], string operations: + _GLIBCXX20_CONSTEXPR size_type copy(_CharT* __str, size_type __n, size_type __pos = 0) const { diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc new file mode 100644 index 00000000000..f3042c25dc4 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/char/constexpr.cc @@ -0,0 +1,32 @@ +// Copyright (C) 2020 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +constexpr bool +test01() +{ + std::string_view s = "Everything changes and nothing stands still."; + char buf[7]; + auto n = s.copy(buf, 7, 11); + return std::string_view(buf, n) == "changes"; +} + +static_assert( test01() ); diff --git a/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc new file mode 100644 index 00000000000..f48a17eade8 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/basic_string_view/operations/copy/wchar_t/constexpr.cc @@ -0,0 +1,32 @@ +// Copyright (C) 2020 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 +// . + +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +#include + +constexpr bool +test01() +{ + std::wstring_view s = L"Everything changes and nothing stands still."; + wchar_t buf[7]; + auto n = s.copy(buf, 7, 11); + return std::wstring_view(buf, n) == L"changes"; +} + +static_assert( test01() ); -- 2.30.2