From 19358ca38ca1b92022ceafaf552ec892c09d9e43 Mon Sep 17 00:00:00 2001 From: Hewill Kang Date: Sat, 3 Jan 2026 22:50:45 +0800 Subject: [PATCH] [libc++] Make sure `flat_set::key_compare` handle `boolean-testable` correctly (#132622) Also add test for `flat_multiset` to avoid regression. --------- Co-authored-by: Hui Xie Co-authored-by: A. Jiang --- libcxx/include/__flat_set/flat_set.h | 2 +- .../robust_against_nonbool.compile.pass.cpp | 44 +++++++++++++++++++ .../robust_against_nonbool.compile.pass.cpp | 44 +++++++++++++++++++ 3 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 libcxx/test/std/containers/container.adaptors/flat.multiset/robust_against_nonbool.compile.pass.cpp create mode 100644 libcxx/test/std/containers/container.adaptors/flat.set/robust_against_nonbool.compile.pass.cpp diff --git a/libcxx/include/__flat_set/flat_set.h b/libcxx/include/__flat_set/flat_set.h index dad747e7857c..57c3926e33b6 100644 --- a/libcxx/include/__flat_set/flat_set.h +++ b/libcxx/include/__flat_set/flat_set.h @@ -679,7 +679,7 @@ public: private: _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX26 bool __is_sorted_and_unique(auto&& __key_container) const { - auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) { return !__compare_(__x, __y); }; + auto __greater_or_equal_to = [this](const auto& __x, const auto& __y) -> bool { return !__compare_(__x, __y); }; return ranges::adjacent_find(__key_container, __greater_or_equal_to) == ranges::end(__key_container); } diff --git a/libcxx/test/std/containers/container.adaptors/flat.multiset/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multiset/robust_against_nonbool.compile.pass.cpp new file mode 100644 index 000000000000..e312ec676621 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/flat.multiset/robust_against_nonbool.compile.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// +// +// flat_multiset should support comparator that return a non-boolean value +// as long as the returned type is implicitly convertible to bool. + +#include +#include +#include + +#include "boolean_testable.h" + +void test() { + using Key = StrictComparable; + std::vector v; + std::flat_multiset m1; + std::flat_multiset m2(std::from_range, v, StrictBinaryPredicate); + std::flat_multiset m3(std::sorted_equivalent, v, StrictBinaryPredicate); + std::flat_multiset m4(m1.begin(), m1.end(), StrictBinaryPredicate); + m2.insert(m1.begin(), m1.end()); + m2.insert(std::sorted_equivalent, m1.begin(), m1.end()); + m2.insert_range(m1); + m3.insert(1); + m2.emplace(1); + m2.emplace_hint(m2.begin(), 1); + for (const auto& k : m2) { + (void)k; + } + (void)m2.find(Key{1}); + (void)m2.equal_range(Key{1}); + (void)(m2 == m2); + m2.erase(m2.begin()); + m2.erase(m2.begin(), m2.end()); + std::erase_if(m2, [](const StrictComparable&) -> const BooleanTestable& { return yes; }); +} diff --git a/libcxx/test/std/containers/container.adaptors/flat.set/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.set/robust_against_nonbool.compile.pass.cpp new file mode 100644 index 000000000000..84f96d38ed3f --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/flat.set/robust_against_nonbool.compile.pass.cpp @@ -0,0 +1,44 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +// REQUIRES: std-at-least-c++23 + +// +// +// flat_set should support comparator that return a non-boolean +// value as long as the returned type is implicitly convertible to bool. + +#include +#include +#include + +#include "boolean_testable.h" + +void test() { + using Key = StrictComparable; + std::vector v; + std::flat_set m1; + std::flat_set m2(std::from_range, v, StrictBinaryPredicate); + std::flat_set m3(std::sorted_unique, v, StrictBinaryPredicate); + std::flat_set m4(m1.begin(), m1.end(), StrictBinaryPredicate); + m2.insert(m1.begin(), m1.end()); + m2.insert(std::sorted_unique, m1.begin(), m1.end()); + m2.insert_range(m1); + m3.insert(1); + m2.emplace(1); + m2.emplace_hint(m2.begin(), 1); + for (const auto& k : m2) { + (void)k; + } + (void)m2.find(Key{1}); + (void)m2.equal_range(Key{1}); + (void)(m2 == m2); + m2.erase(m2.begin()); + m2.erase(m2.begin(), m2.end()); + std::erase_if(m2, [](const StrictComparable&) -> BooleanTestable const& { return yes; }); +}