[libcxx-commits] [libcxx] 3456b2f - [libc++] Refactor __debug_three_way_comp
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Jun 13 14:25:16 PDT 2023
Author: Louis Dionne
Date: 2023-06-13T14:24:56-07:00
New Revision: 3456b2f60a08a6ab750d58817463a6701a416e3b
URL: https://github.com/llvm/llvm-project/commit/3456b2f60a08a6ab750d58817463a6701a416e3b
DIFF: https://github.com/llvm/llvm-project/commit/3456b2f60a08a6ab750d58817463a6701a416e3b.diff
LOG: [libc++] Refactor __debug_three_way_comp
This makes __debug_three_way_comp consistent with __debug_less and
in particular gets rid of a potential use-after-move caused by the
use of std::forward. In the previous version of the code, we would
call `__do_compare_assert` after forwarding the arguments into the
comparator, which could end up using the arguments after they've been
moved from.
This also simplifies how we call `__do_compare_assert` by using
`if constexpr` and adds a missing test for proxy iterators in
lexicographical_compare_three_way, which could have found this
issue.
Differential Revision: https://reviews.llvm.org/D152753
Added:
Modified:
libcxx/include/__algorithm/three_way_comp_ref_type.h
libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__algorithm/three_way_comp_ref_type.h b/libcxx/include/__algorithm/three_way_comp_ref_type.h
index ce1350a584470..5dc922fd2b254 100644
--- a/libcxx/include/__algorithm/three_way_comp_ref_type.h
+++ b/libcxx/include/__algorithm/three_way_comp_ref_type.h
@@ -29,16 +29,23 @@ struct __debug_three_way_comp {
_LIBCPP_HIDE_FROM_ABI constexpr __debug_three_way_comp(_Comp& __c) : __comp_(__c) {}
template <class _Tp, class _Up>
- _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp&& __x, _Up&& __y) {
- auto __r = __comp_(std::forward<_Tp>(__x), std::forward<_Up>(__y));
- __do_compare_assert(0, __y, __x, __r);
+ _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(const _Tp& __x, const _Up& __y) {
+ auto __r = __comp_(__x, __y);
+ if constexpr (__comparison_category<decltype(__comp_(__x, __y))>)
+ __do_compare_assert(__y, __x, __r);
+ return __r;
+ }
+
+ template <class _Tp, class _Up>
+ _LIBCPP_HIDE_FROM_ABI constexpr auto operator()(_Tp& __x, _Up& __y) {
+ auto __r = __comp_(__x, __y);
+ if constexpr (__comparison_category<decltype(__comp_(__x, __y))>)
+ __do_compare_assert(__y, __x, __r);
return __r;
}
template <class _LHS, class _RHS, class _Order>
- _LIBCPP_HIDE_FROM_ABI constexpr inline void __do_compare_assert(int, _LHS& __l, _RHS& __r, _Order __o)
- requires __comparison_category<decltype(std::declval<_Comp&>()(std::declval<_LHS&>(), std::declval<_RHS&>()))>
- {
+ _LIBCPP_HIDE_FROM_ABI constexpr void __do_compare_assert(_LHS& __l, _RHS& __r, _Order __o) {
_Order __expected = __o;
if (__o == _Order::less)
__expected = _Order::greater;
@@ -47,11 +54,7 @@ struct __debug_three_way_comp {
_LIBCPP_DEBUG_ASSERT(__comp_(__l, __r) == __expected, "Comparator does not induce a strict weak ordering");
(void)__l;
(void)__r;
- (void)__expected;
}
-
- template <class _LHS, class _RHS, class _Order>
- _LIBCPP_HIDE_FROM_ABI constexpr inline void __do_compare_assert(long, _LHS&, _RHS&, _Order) {}
};
// Pass the comparator by lvalue reference. Or in debug mode, using a
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
index 4c940ebf0b608..0bd1d74529530 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way.pass.cpp
@@ -19,6 +19,7 @@
#include <cassert>
#include <compare>
#include <concepts>
+#include <vector>
#include "test_macros.h"
#include "test_comparisons.h"
@@ -107,9 +108,17 @@ constexpr void test_comparison_categories() {
std::partial_ordering::unordered);
}
+// Check that it works with proxy iterators
+constexpr void test_proxy_iterators() {
+ std::vector<bool> vec(10, true);
+ auto result = std::lexicographical_compare_three_way(vec.begin(), vec.end(), vec.begin(), vec.end());
+ assert(result == std::strong_ordering::equal);
+}
+
constexpr bool test() {
test_iterator_types();
test_comparison_categories();
+ test_proxy_iterators();
return true;
}
diff --git a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
index d690f385fbe62..ebbf833a2ad07 100644
--- a/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
+++ b/libcxx/test/std/algorithms/alg.sorting/alg.three.way/lexicographical_compare_three_way_comp.pass.cpp
@@ -22,6 +22,7 @@
#include <compare>
#include <concepts>
#include <limits>
+#include <vector>
#include "test_iterators.h"
#include "test_macros.h"
@@ -162,10 +163,18 @@ constexpr void test_comparator_invocation_count() {
#endif
}
+// Check that it works with proxy iterators
+constexpr void test_proxy_iterators() {
+ std::vector<bool> vec(10, true);
+ auto result = std::lexicographical_compare_three_way(vec.begin(), vec.end(), vec.begin(), vec.end(), compare_last_digit_strong);
+ assert(result == std::strong_ordering::equal);
+}
+
constexpr bool test() {
test_iterator_types();
test_comparison_categories();
test_comparator_invocation_count();
+ test_proxy_iterators();
return true;
}
More information about the libcxx-commits
mailing list