diff options
author | Patrick Palka <ppalka@redhat.com> | 2020-02-28 14:16:06 -0500 |
---|---|---|
committer | Patrick Palka <ppalka@redhat.com> | 2020-02-28 17:55:44 -0500 |
commit | ce33801fe4c2272b31c64288b34c67a61529ce37 (patch) | |
tree | 60a5ff84a1d13e63770f1fafbed63864e92043c2 /libstdc++-v3/include | |
parent | e82192021dd08291ee418cb33bb7af037952e963 (diff) | |
download | gcc-ce33801fe4c2272b31c64288b34c67a61529ce37.zip gcc-ce33801fe4c2272b31c64288b34c67a61529ce37.tar.gz gcc-ce33801fe4c2272b31c64288b34c67a61529ce37.tar.bz2 |
libstdc++: Fix bogus use of memcmp in ranges::lexicographical_compare (PR 93972)
We were enabling the memcmp optimization in ranges::lexicographical_compare for
signed integral types and for integral types wider than a byte. But memcmp
gives the wrong answer for arrays of such types. This patch fixes this issue by
refining the condition that enables the memcmp optimization. It's now
consistent with the corresponding condition used in
std::lexicographical_compare.
libstdc++-v3/ChangeLog:
PR libstdc++/93972
* include/bits/ranges_algo.h (__lexicographical_compare_fn::operator()):
Fix condition for when to use memcmp, making it consistent with the
corresponding condition used in std::lexicographical_compare.
* testsuite/25_algorithms/lexicographical_compare/93972.cc: New test.
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r-- | libstdc++-v3/include/bits/ranges_algo.h | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h index 05c0851..8fa4a8a 100644 --- a/libstdc++-v3/include/bits/ranges_algo.h +++ b/libstdc++-v3/include/bits/ranges_algo.h @@ -3466,9 +3466,13 @@ namespace ranges { using _ValueType1 = iter_value_t<_Iter1>; using _ValueType2 = iter_value_t<_Iter2>; + // This condition is consistent with the one in + // __lexicographical_compare_aux in <bits/stl_algobase.h>. constexpr bool __use_memcmp - = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) - && is_same_v<_ValueType1, _ValueType2> + = (__is_byte<_ValueType1>::__value + && __is_byte<_ValueType2>::__value + && !__gnu_cxx::__numeric_traits<_ValueType1>::__is_signed + && !__gnu_cxx::__numeric_traits<_ValueType2>::__is_signed && is_pointer_v<_Iter1> && is_pointer_v<_Iter2> && (is_same_v<_Comp, ranges::less> |