{
if (__n == 0)
return __s1;
-#ifdef __cpp_lib_is_constant_evaluated
+#if __cpp_lib_is_constant_evaluated
if (std::is_constant_evaluated())
{
- if (__s1 > __s2 && __s1 < __s2 + __n)
- std::copy_backward(__s2, __s2 + __n, __s1 + __n);
+ if (__s1 == __s2) // unlikely, but saves a lot of work
+ return __s1;
+#if __cpp_constexpr_dynamic_alloc
+ // The overlap detection below fails due to PR c++/89074,
+ // so use a temporary buffer instead.
+ char_type* __tmp = new char_type[__n];
+ copy(__tmp, __s2, __n);
+ copy(__s1, __tmp, __n);
+ delete[] __tmp;
+#else
+ const auto __end = __s2 + __n - 1;
+ bool __overlap = false;
+ for (std::size_t __i = 0; __i < __n - 1; ++__i)
+ {
+ if (__s1 + __i == __end)
+ {
+ __overlap = true;
+ break;
+ }
+ }
+ if (__overlap)
+ {
+ do
+ {
+ --__n;
+ assign(__s1[__n], __s2[__n]);
+ }
+ while (__n > 0);
+ }
else
- std::copy(__s2, __s2 + __n, __s1);
+ copy(__s1, __s2, __n);
+#endif
return __s1;
}
#endif
- return static_cast<_CharT*>(__builtin_memmove(__s1, __s2,
- __n * sizeof(char_type)));
+ __builtin_memmove(__s1, __s2, __n * sizeof(char_type));
+ return __s1;
}
template<typename _CharT>
-// { dg-options "-std=gnu++2a" }
-// { dg-do compile { target c++2a } }
+// { dg-options "-std=gnu++20" }
+// { dg-do compile { target c++20 } }
// Copyright (C) 2017-2020 Free Software Foundation, Inc.
//
test_move()
{
using char_type = typename CT::char_type;
+
+ // Overlapping strings
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};
+ if (s1[0] != char_type{1} || s1[1] != char_type{1} || s1[2] != char_type{2})
+ throw 1;
+ CT::move(s1, s1+1, 2);
+ if (s1[0] != char_type{1} || s1[1] != char_type{2} || s1[2] != char_type{2})
+ throw 2;
+
+ // Disjoint strings
+ char_type why_is_six_scared_of_seven[] = {4, 5, 6};
+ char_type because789[] = {7, 8, 9};
+ CT::move(why_is_six_scared_of_seven, because789, 3);
+ if (why_is_six_scared_of_seven[0] != char_type{7}
+ || why_is_six_scared_of_seven[1] != char_type{8}
+ || why_is_six_scared_of_seven[2] != char_type{9})
+ throw 3;
+
+ return true;
}
#ifndef __cpp_lib_constexpr_string