Hi, Upon constexpr evaluation, char_traits move uses copy_backward, but its last argument should be to the range end rather than its beginning. I include the fix and a test.
This is my first patch, so if it looks OK, perhaps someone could commit for me. Regards, Paul Please consider the environment and think before you print. The University of the West of Scotland is a registered Scottish charity. Charity number SC002520. This e-mail and any attachment is for authorised use by the intended recipient(s) only. It may contain proprietary material, confidential information and/or be subject to legal privilege. It should not be copied, disclosed to, retained or used by, any other party. If you are not an intended recipient then please promptly delete this e-mail and any attachment and all copies and inform the sender. Please note that any views or opinions presented in this email are solely those of the author and do not necessarily represent those of the University of the West of Scotland. As a public body, the University of the West of Scotland may be required to make available emails as well as other written forms of information as a result of a request made under the Freedom of Information (Scotland) Act 2002.
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index ee252236a..b54dccd2d 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,9 @@ +2020-06-12 Paul Keir <paul.k...@uws.ac.uk> + + * include/bits/char_traits.h: constexpr char_traits + move with overlap was using copy_backward incorrectly. + * testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc: New test. + 2020-06-04 Jonathan Wakely <jwak...@redhat.com> * include/bits/iterator_concepts.h (__detail::__ptr, __detail::__ref) diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index c6da184e4..c623a6713 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -196,7 +196,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION if (std::is_constant_evaluated()) { if (__s1 > __s2 && __s1 < __s2 + __n) - std::copy_backward(__s2, __s2 + __n, __s1); + std::copy_backward(__s2, __s2 + __n, __s1 + __n); else std::copy(__s2, __s2 + __n, __s1); return __s1; diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc new file mode 100644 index 000000000..6358640c1 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/constexpr_functions_c++20.cc @@ -0,0 +1,52 @@ +// { dg-options "-std=gnu++2a" } +// { dg-do compile { target c++2a } } + +// Copyright (C) 2017-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 +// <http://www.gnu.org/licenses/>. + +#include <string> + +template<typename CT> + constexpr bool + test_move() + { + using char_type = typename CT::char_type; + char_type s1[3] = {1, 2, 3}; + CT::move(s1+1, s1, 2); + return s1[0]==char_type{1} && s1[1]==char_type{1} && s1[2]==char_type{2}; + } + +#ifndef __cpp_lib_constexpr_char_traits +# error Feature-test macro for constexpr char_traits is missing +#elif __cpp_lib_constexpr_char_traits != 201611 +# error Feature-test macro for constexpr char_traits has the wrong value +#endif + +static_assert( test_move<std::char_traits<char>>() ); +#ifdef _GLIBCXX_USE_WCHAR_T +static_assert( test_move<std::char_traits<wchar_t>>() ); +#endif +#ifdef _GLIBCXX_USE_CHAR8_T +static_assert( test_move<std::char_traits<char8_t>>() ); +#endif +static_assert( test_move<std::char_traits<char16_t>>() ); +static_assert( test_move<std::char_traits<char32_t>>() ); + +struct C { unsigned char c; }; +constexpr bool operator==(const C& c1, const C& c2) { return c1.c == c2.c; } +constexpr bool operator<(const C& c1, const C& c2) { return c1.c < c2.c; } +static_assert( test_move<std::char_traits<C>>() );