From e0f56c01092be3319f73d076e484640feb8dd22c Mon Sep 17 00:00:00 2001 From: Hewill Kang Date: Mon, 24 Mar 2025 01:09:36 +0800 Subject: [PATCH 1/4] [libc++] Make sure compare handle boolean-testable correctly --- libcxx/include/__flat_map/flat_map.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/include/__flat_map/flat_map.h b/libcxx/include/__flat_map/flat_map.h index a0594ed9dc411..2f32497ab20d3 100644 --- a/libcxx/include/__flat_map/flat_map.h +++ b/libcxx/include/__flat_map/flat_map.h @@ -846,7 +846,7 @@ class flat_map { __compare_(std::forward<_CompArg>(__comp)...) {} _LIBCPP_HIDE_FROM_ABI 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); } @@ -870,7 +870,7 @@ class flat_map { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); auto __append_start_offset = __containers_.keys.size() - __num_of_appended; auto __end = __zv.end(); - auto __compare_key = [this](const auto& __p1, const auto& __p2) { + auto __compare_key = [this](const auto& __p1, const auto& __p2) -> bool { return __compare_(std::get<0>(__p1), std::get<0>(__p2)); }; if constexpr (!_WasSorted) { From 436ae2ed9977bf87c4e5b5b04cc13477416f20db Mon Sep 17 00:00:00 2001 From: Hewill Kang Date: Mon, 24 Mar 2025 01:17:57 +0800 Subject: [PATCH 2/4] [libc++] Make sure compare handle boolean-testable correctly --- libcxx/include/__flat_map/flat_multimap.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/include/__flat_map/flat_multimap.h b/libcxx/include/__flat_map/flat_multimap.h index ea77fb5d79bd2..664dc0eed1bb6 100644 --- a/libcxx/include/__flat_map/flat_multimap.h +++ b/libcxx/include/__flat_map/flat_multimap.h @@ -777,7 +777,7 @@ class flat_multimap { auto __zv = ranges::views::zip(__containers_.keys, __containers_.values); auto __append_start_offset = __containers_.keys.size() - __num_appended; auto __end = __zv.end(); - auto __compare_key = [this](const auto& __p1, const auto& __p2) { + auto __compare_key = [this](const auto& __p1, const auto& __p2) -> bool { return __compare_(std::get<0>(__p1), std::get<0>(__p2)); }; if constexpr (!_WasSorted) { From 393d9e6b6a85378523983cd33cb052dc0414080f Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 17 May 2025 08:16:20 +0100 Subject: [PATCH 3/4] Added Unit Tests --- .../robust_against_nonbool.compile.pass.cpp | 50 +++++++++++++++++++ .../robust_against_nonbool.compile.pass.cpp | 46 +++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp create mode 100644 libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp new file mode 100644 index 0000000000000..905efe1bdb4ea --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp @@ -0,0 +1,50 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// +// +// flat_map should support comparator that return a non-boolean +// value as long as the returned type is implicitly convertible to bool. + +#include +#include + +#include "boolean_testable.h" + +void test() { + using Key = StrictComparable; + using Value = StrictComparable; + std::flat_map m1; + std::flat_map m2(std::from_range, m1, StrictBinaryPredicate); + std::flat_map m3(std::sorted_unique, m1.keys(), m1.values(), StrictBinaryPredicate); + std::flat_map 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); + (void)m2.at(2); + m3[1] = 2; + m3.insert_or_assign(1, 2); + m4.try_emplace(1, 2); + m2.emplace(1, 2); + m2.emplace_hint(m2.begin(), 1, 2); + for (const auto& [k, v] : m2) { + (void)k; + (void)v; + } + (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, [](std::pair&, const StrictComparable&>) -> BooleanTestable const& { + return yes; + }); +} diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp new file mode 100644 index 0000000000000..96f83568b5aa9 --- /dev/null +++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp @@ -0,0 +1,46 @@ +//===----------------------------------------------------------------------===// +// +// 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 +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20 + +// +// +// flat_multimap should support comparator that return a non-boolean +// value as long as the returned type is implicitly convertible to bool. + +#include +#include + +#include "boolean_testable.h" + +void test() { + using Key = StrictComparable; + using Value = StrictComparable; + std::flat_multimap m1; + std::flat_multimap m2(std::from_range, m1, StrictBinaryPredicate); + std::flat_multimap m3(std::sorted_equivalent, m1.keys(), m1.values(), StrictBinaryPredicate); + std::flat_multimap 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); + m2.emplace(1, 2); + m2.emplace_hint(m2.begin(), 1, 2); + for (const auto& [k, v] : m2) { + (void)k; + (void)v; + } + (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, [](std::pair&, const StrictComparable&>) -> BooleanTestable const& { + return yes; + }); +} From 986530c2595f1e6f6c5d3f50c623ec6deff1fead Mon Sep 17 00:00:00 2001 From: Hui Xie Date: Sat, 17 May 2025 11:48:38 +0100 Subject: [PATCH 4/4] CI --- .../flat.map/robust_against_nonbool.compile.pass.cpp | 1 + .../flat.multimap/robust_against_nonbool.compile.pass.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp index 905efe1bdb4ea..8b9e631bcdaff 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.map/robust_against_nonbool.compile.pass.cpp @@ -14,6 +14,7 @@ // value as long as the returned type is implicitly convertible to bool. #include +#include #include #include "boolean_testable.h" diff --git a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp index 96f83568b5aa9..e4be75d83c50c 100644 --- a/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp +++ b/libcxx/test/std/containers/container.adaptors/flat.multimap/robust_against_nonbool.compile.pass.cpp @@ -15,6 +15,7 @@ #include #include +#include #include "boolean_testable.h"