Skip to content

Commit 5a305ce

Browse files
authored
[libc++] Use __is_pointer_in_range for char_traits checks (#72643)
This allows us to also check the constraints during constant evaluation.
1 parent 42204c9 commit 5a305ce

File tree

1 file changed

+23
-28
lines changed

1 file changed

+23
-28
lines changed

libcxx/include/__string/char_traits.h

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <__iterator/iterator_traits.h>
2121
#include <__string/constexpr_c_functions.h>
2222
#include <__type_traits/is_constant_evaluated.h>
23+
#include <__utility/is_pointer_in_range.h>
2324
#include <cstddef>
2425
#include <cstdint>
2526
#include <cstdio>
@@ -142,14 +143,12 @@ struct _LIBCPP_DEPRECATED_("char_traits<T> for T not equal to char, wchar_t, cha
142143
_LIBCPP_INLINE_VISIBILITY
143144
static _LIBCPP_CONSTEXPR_SINCE_CXX20
144145
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) {
145-
if (!__libcpp_is_constant_evaluated()) {
146-
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
147-
__s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
148-
}
149-
char_type* __r = __s1;
150-
for (; __n; --__n, ++__s1, ++__s2)
151-
assign(*__s1, *__s2);
152-
return __r;
146+
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
147+
"char_traits::copy: source and destination ranges overlap");
148+
char_type* __r = __s1;
149+
for (; __n; --__n, ++__s1, ++__s2)
150+
assign(*__s1, *__s2);
151+
return __r;
153152
}
154153
_LIBCPP_INLINE_VISIBILITY
155154
static _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -238,11 +237,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char>
238237

239238
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
240239
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
241-
if (!__libcpp_is_constant_evaluated())
242-
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
243-
__s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
244-
std::copy_n(__s2, __n, __s1);
245-
return __s1;
240+
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
241+
"char_traits::copy: source and destination ranges overlap");
242+
std::copy_n(__s2, __n, __s1);
243+
return __s1;
246244
}
247245

248246
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -310,11 +308,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<wchar_t>
310308

311309
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
312310
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
313-
if (!__libcpp_is_constant_evaluated())
314-
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
315-
__s2 < __s1 || __s2 >= __s1 + __n, "char_traits::copy overlapped range");
316-
std::copy_n(__s2, __n, __s1);
317-
return __s1;
311+
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
312+
"char_traits::copy: source and destination ranges overlap");
313+
std::copy_n(__s2, __n, __s1);
314+
return __s1;
318315
}
319316

320317
static inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -375,11 +372,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char8_t>
375372

376373
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
377374
char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
378-
if (!__libcpp_is_constant_evaluated())
379-
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
380-
__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
381-
std::copy_n(__s2, __n, __s1);
382-
return __s1;
375+
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
376+
"char_traits::copy: source and destination ranges overlap");
377+
std::copy_n(__s2, __n, __s1);
378+
return __s1;
383379
}
384380

385381
static _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
@@ -460,11 +456,10 @@ struct _LIBCPP_TEMPLATE_VIS char_traits<char16_t>
460456

461457
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
462458
static char_type* copy(char_type* __s1, const char_type* __s2, size_t __n) _NOEXCEPT {
463-
if (!__libcpp_is_constant_evaluated())
464-
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(
465-
__s2 < __s1 || __s2 >= __s1+__n, "char_traits::copy overlapped range");
466-
std::copy_n(__s2, __n, __s1);
467-
return __s1;
459+
_LIBCPP_ASSERT_NON_OVERLAPPING_RANGES(!std::__is_pointer_in_range(__s1, __s1 + __n, __s2),
460+
"char_traits::copy: source and destination ranges overlap");
461+
std::copy_n(__s2, __n, __s1);
462+
return __s1;
468463
}
469464

470465
_LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20

0 commit comments

Comments
 (0)