[PATCH] libstdc++: Fix bogus use of memcmp in ranges::lexicographical_compare (PR 93972)
Jonathan Wakely
jwakely@redhat.com
Fri Feb 28 21:53:00 GMT 2020
On 28/02/20 14:59 -0500, Patrick Palka wrote:
>We were enabling the memcmp optimization in ranges::lexicographical_compare for
>signed integral types and for integral types larger 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.
>---
> libstdc++-v3/include/bits/ranges_algo.h | 8 +-
> .../lexicographical_compare/93972.cc | 169 ++++++++++++++++++
> 2 files changed, 175 insertions(+), 2 deletions(-)
> create mode 100644 libstdc++-v3/testsuite/25_algorithms/lexicographical_compare/93972.cc
>
>diff --git a/libstdc++-v3/include/bits/ranges_algo.h b/libstdc++-v3/include/bits/ranges_algo.h
>index 05c0851d411..8fa4a8a9161 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
I think this could be:
&& !is_signed_v<_ValueType1>
&& !is_signed_v<_ValueType2>
because this code doesn't need to be valid for C++98. But on the other
hand, there's value in being consistent with the condition in
std::lexicographical_compare.
OK for master, thanks for the quick fix.
More information about the Libstdc++
mailing list