[libc++] [LIBCXX-DEBUG-FIXME] Constexpr char_traits::copy mustn't compare unrelated pointers.
Now that __builtin_is_constant_evaluated() is present on all supported
compilers, we can use it to skip the UB-inducing assert in cases where
the computation might be happening at constexpr time.
Differential Revision: https://reviews.llvm.org/D101674
NOKEYCHECK=True
GitOrigin-RevId: df81bb71aa452c677984fbeb7c34e8a77ec3e83b
diff --git a/include/__string b/include/__string
index a23e7c9..a968fc0 100644
--- a/include/__string
+++ b/include/__string
@@ -265,7 +265,9 @@
_CharT*
char_traits<_CharT>::copy(char_type* __s1, const char_type* __s2, size_t __n)
{
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
char_type* __r = __s1;
for (; __n; --__n, ++__s1, ++__s2)
assign(*__s1, *__s2);
@@ -348,7 +350,9 @@
static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
{
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
return __libcpp_is_constant_evaluated()
? _VSTD::__copy_constexpr(__s1, __s2, __n)
: __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
@@ -451,7 +455,9 @@
static inline _LIBCPP_CONSTEXPR_AFTER_CXX17
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
{
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
return __libcpp_is_constant_evaluated()
? _VSTD::__copy_constexpr(__s1, __s2, __n)
: __n == 0 ? __s1 : _VSTD::wmemcpy(__s1, __s2, __n);
@@ -582,8 +588,10 @@
static _LIBCPP_CONSTEXPR_AFTER_CXX17
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
- {
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ {
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
return __libcpp_is_constant_evaluated()
? _VSTD::__copy_constexpr(__s1, __s2, __n)
: __n == 0 ? __s1 : (char_type*)_VSTD::memcpy(__s1, __s2, __n);
@@ -759,7 +767,9 @@
char16_t*
char_traits<char16_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
{
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
char_type* __r = __s1;
for (; __n; --__n, ++__s1, ++__s2)
assign(*__s1, *__s2);
@@ -879,7 +889,9 @@
char32_t*
char_traits<char32_t>::copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT
{
- _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ if (!__libcpp_is_constant_evaluated()) {
+ _LIBCPP_ASSERT(__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
+ }
char_type* __r = __s1;
for (; __n; --__n, ++__s1, ++__s2)
assign(*__s1, *__s2);