diff --git a/libstdc++-v3/include/bits/char_traits.h b/libstdc++-v3/include/bits/char_traits.h index 018eac28d0d723529ca623e2652ffb098cd1296d..3074e9bb77e25d2ecfeee8190bf686c4291fa933 100644 --- a/libstdc++-v3/include/bits/char_traits.h +++ b/libstdc++-v3/include/bits/char_traits.h @@ -227,19 +227,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION #if __cplusplus >= 202002L if (std::__is_constant_evaluated()) { - if (__s1 == __s2) // unlikely, but saves a lot of work - return __s1; - 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) + // Use __builtin_constant_p to avoid comparing unrelated pointers. + if (__builtin_constant_p(__s2 < __s1) + && __s1 > __s2 && __s1 < (__s2 + __n)) { do { diff --git a/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc new file mode 100644 index 0000000000000000000000000000000000000000..0fe765d53bcce4806bb39f8e6d9f9ce11150d568 --- /dev/null +++ b/libstdc++-v3/testsuite/21_strings/char_traits/requirements/113200.cc @@ -0,0 +1,20 @@ +// { dg-do compile { target c++20 } } + +// PR libstdc++/113200 +// char_traits::move is not constexpr when the argument is a string literal + +#include <string_view> + +template<std::size_t N> struct S +{ + char data_[ N ]; + + constexpr S( char const* p ): data_{} + { + std::char_traits<char>::move( data_, p, N ); + } +}; + +template<std::size_t N> S( char const(&)[N] ) -> S<N>; + +constexpr S s( "test" );