Skip to content

Commit 0e54039

Browse files
philnik777tstellar
authored andcommitted
[libc++] Fix ranges::binary_search() returning true for cases where the element is not in the range
Fixes llvm#61160 Reviewed By: ldionne, #libc Spies: libcxx-commits Differential Revision: https://reviews.llvm.org/D145287 (cherry picked from commit 3391246)
1 parent 7b4e71b commit 0e54039

File tree

4 files changed

+41
-2
lines changed

4 files changed

+41
-2
lines changed

libcxx/include/__algorithm/ranges_binary_search.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ struct __fn {
3636
_LIBCPP_NODISCARD_EXT _LIBCPP_HIDE_FROM_ABI constexpr
3737
bool operator()(_Iter __first, _Sent __last, const _Type& __value, _Comp __comp = {}, _Proj __proj = {}) const {
3838
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
39-
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
39+
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
4040
}
4141

4242
template <forward_range _Range, class _Type, class _Proj = identity,
@@ -46,7 +46,7 @@ struct __fn {
4646
auto __first = ranges::begin(__r);
4747
auto __last = ranges::end(__r);
4848
auto __ret = std::__lower_bound_impl<_RangeAlgPolicy>(__first, __last, __value, __comp, __proj);
49-
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__first));
49+
return __ret != __last && !std::invoke(__comp, __value, std::invoke(__proj, *__ret));
5050
}
5151
};
5252
} // namespace __binary_search

libcxx/test/std/algorithms/alg.sorting/alg.binary.search/binary.search/ranges.binary_search.pass.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,13 @@ constexpr void test_iterators() {
131131
auto range = std::ranges::subrange(It(a), Sent(It(a + 5)));
132132
assert(std::ranges::binary_search(range, 1));
133133
}
134+
135+
{ // check that false is returned when the element doesn't exist, but an element with a greater value is in the range
136+
int a[] = {1, 2, 4};
137+
assert(!std::ranges::binary_search(It(a), Sent(It(a + 3)), 3));
138+
auto range = std::ranges::subrange(It(a), Sent(It(a + 3)));
139+
assert(!std::ranges::binary_search(range, 3));
140+
}
134141
}
135142

136143
constexpr bool test() {

libcxx/test/std/algorithms/alg.sorting/alg.binary.search/lower.bound/ranges.lower_bound.pass.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,22 @@ constexpr void test_iterators() {
194194
assert(base(ret) == a);
195195
}
196196
}
197+
198+
{ // check that the middle of a range is returned when there are smaller and larger elements
199+
{
200+
int a[] = {1, 2, 3, 4, 6, 7, 8};
201+
auto ret = std::ranges::lower_bound(It(a), It(a + 7), 5);
202+
assert(base(ret) == a + 4);
203+
assert(*ret == 6);
204+
}
205+
{
206+
int a[] = {1, 2, 3, 4, 6, 7, 8};
207+
auto range = std::ranges::subrange(It(a), It(a + 7));
208+
auto ret = std::ranges::lower_bound(range, 5);
209+
assert(base(ret) == a + 4);
210+
assert(*ret == 6);
211+
}
212+
}
197213
}
198214

199215
constexpr bool test() {

libcxx/test/std/algorithms/alg.sorting/alg.binary.search/upper.bound/ranges.upper_bound.pass.cpp

+16
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,22 @@ constexpr void test_iterators() {
193193
assert(base(ret) == a + 1);
194194
}
195195
}
196+
197+
{ // check that the middle of a range is returned when there are smaller and larger elements
198+
{
199+
int a[] = {1, 2, 3, 4, 6, 7, 8};
200+
auto ret = std::ranges::upper_bound(It(a), It(a + 7), 5);
201+
assert(base(ret) == a + 4);
202+
assert(*ret == 6);
203+
}
204+
{
205+
int a[] = {1, 2, 3, 4, 6, 7, 8};
206+
auto range = std::ranges::subrange(It(a), It(a + 7));
207+
auto ret = std::ranges::upper_bound(range, 5);
208+
assert(base(ret) == a + 4);
209+
assert(*ret == 6);
210+
}
211+
}
196212
}
197213

198214
constexpr bool test() {

0 commit comments

Comments
 (0)