https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99181

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
      static _GLIBCXX_CONSTEXPR bool
      lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT
      {
        // LWG 467.
        return (static_cast<unsigned char>(__c1)
                < static_cast<unsigned char>(__c2));
      }

      static _GLIBCXX17_CONSTEXPR int
      compare(const char_type* __s1, const char_type* __s2, size_t __n)
      {
        if (__n == 0)
          return 0;
#if __cplusplus >= 201703L
        if (__builtin_constant_p(__n)
            && __constant_char_array_p(__s1, __n)
            && __constant_char_array_p(__s2, __n))
          return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
#endif
        return __builtin_memcmp(__s1, __s2, __n);
      }

Seems the std::char_traits<char>::lt specialization implements LWG467, and so
does std::char_traits<char>::compare when not in constant expression
evaluation,
but the C++17 case above will call __gnu_cxx::char_traits<char_type>::compare
which doesn't know about LWG 467.

--- libstdc++-v3/include/bits/char_traits.h.jj  2021-01-04 10:26:03.558953845
+0100
+++ libstdc++-v3/include/bits/char_traits.h     2021-02-22 10:42:08.197199781
+0100
@@ -349,7 +349,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        if (__builtin_constant_p(__n)
            && __constant_char_array_p(__s1, __n)
            && __constant_char_array_p(__s2, __n))
-         return __gnu_cxx::char_traits<char_type>::compare(__s1, __s2, __n);
+         {
+           for (std::size_t __i = 0; __i < __n; ++__i)
+             if (lt(__s1[__i], __s2[__i]))
+               return -1;
+             else if (lt(__s2[__i], __s1[__i]))
+               return 1;
+           return 0;
+         }
 #endif
        return __builtin_memcmp(__s1, __s2, __n);
       }

seems to fix this, but not sure if there isn't a better way.

Reply via email to