[libcxx-commits] [libcxx] [libc++] Expand test coverage for converting comparators in associative containers (PR #187133)
Louis Dionne via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Mar 18 07:34:25 PDT 2026
https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/187133
>From c80b76f5c0d357dba97d3a32550cb322fa43f9a2 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Tue, 17 Mar 2026 17:34:39 -0400
Subject: [PATCH 1/2] [libc++] Expand test coverage for converting comparators
in associative containers
This is in preparation for fixing #187105.
---
...lookup_with_converting_comparator.pass.cpp | 68 +++++++++++++++++++
.../associative/map/map.ops/find.pass.cpp | 13 ----
2 files changed, 68 insertions(+), 13 deletions(-)
create mode 100644 libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
diff --git a/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp b/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
new file mode 100644
index 0000000000000..f7e3285194d2d
--- /dev/null
+++ b/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
@@ -0,0 +1,68 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// Make sure that lookup methods on ordered associative containers work properly
+// with comparators that require an implicit conversion on lookup. Using a
+// comparator like less<S> with reference_wrapper<S> as the key type causes an
+// implicit conversion from reference_wrapper<S> to const S& during comparison.
+//
+// Potential heterogeneous lookup optimizations must not break this by making the
+// comparator "transparent" when doing so would remove that conversion.
+//
+// This is a regression test for https://llvm.org/PR179319.
+
+#include <cassert>
+#include <functional>
+#include <map>
+#include <set>
+
+#include "test_macros.h"
+
+struct S {
+ int i_;
+
+ S(int i) : i_(i) {}
+ bool operator<(S lhs) const { return lhs.i_ < i_; }
+};
+
+template <class Container>
+void test(Container& c) {
+ S v(1);
+ assert(c.find(v) == c.end());
+ assert(c.count(v) == 0);
+ assert(c.lower_bound(v) == c.end());
+ assert(c.upper_bound(v) == c.end());
+ assert(c.equal_range(v).first == c.end());
+ assert(c.equal_range(v).second == c.end());
+#if TEST_STD_VER >= 20
+ assert(!c.contains(v));
+#endif
+}
+
+int main(int, char**) {
+ {
+ std::map<std::reference_wrapper<S>, void*, std::less<S>> m;
+ test(m);
+ }
+ {
+ std::multimap<std::reference_wrapper<S>, void*, std::less<S>> m;
+ test(m);
+ }
+ {
+ std::set<std::reference_wrapper<S>, std::less<S>> s;
+ test(s);
+ }
+ {
+ std::multiset<std::reference_wrapper<S>, std::less<S>> s;
+ test(s);
+ }
+
+ return 0;
+}
diff --git a/libcxx/test/std/containers/associative/map/map.ops/find.pass.cpp b/libcxx/test/std/containers/associative/map/map.ops/find.pass.cpp
index 85811046c0048..b0e8b5ee8ba9e 100644
--- a/libcxx/test/std/containers/associative/map/map.ops/find.pass.cpp
+++ b/libcxx/test/std/containers/associative/map/map.ops/find.pass.cpp
@@ -222,18 +222,5 @@ int main(int, char**) {
assert(r == std::next(m.begin(), 8));
}
#endif
- { // Make sure we only make the comparator transparent if it's not converting the arguments
- struct S {
- int i_;
-
- S(int i) : i_(i) {}
- bool operator<(S lhs) const { return lhs.i_ < i_; }
- };
- // less<S> causes an implicit conversion from reference_wrapper<S> to const S&, making the `<` lookup succeed
- std::map<std::reference_wrapper<S>, void*, std::less<S> > m;
- S v(1);
- assert(m.find(v) == m.end());
- }
-
return 0;
}
>From 52f9a67685132bb0b2c5a6d69fc09f04ff0c0399 Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 18 Mar 2026 10:33:24 -0400
Subject: [PATCH 2/2] Also add coverage for const
---
...lookup_with_converting_comparator.pass.cpp | 37 ++++++++++++++-----
1 file changed, 28 insertions(+), 9 deletions(-)
diff --git a/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp b/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
index f7e3285194d2d..6310ac333945b 100644
--- a/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
+++ b/libcxx/test/std/containers/associative/lookup_with_converting_comparator.pass.cpp
@@ -33,17 +33,36 @@ struct S {
};
template <class Container>
-void test(Container& c) {
- S v(1);
- assert(c.find(v) == c.end());
- assert(c.count(v) == 0);
- assert(c.lower_bound(v) == c.end());
- assert(c.upper_bound(v) == c.end());
- assert(c.equal_range(v).first == c.end());
- assert(c.equal_range(v).second == c.end());
+void test(Container& container) {
+ // non-const
+ {
+ Container& c = container;
+ S v(1);
+ assert(c.find(v) == c.end());
+ assert(c.count(v) == 0);
+ assert(c.lower_bound(v) == c.end());
+ assert(c.upper_bound(v) == c.end());
+ assert(c.equal_range(v).first == c.end());
+ assert(c.equal_range(v).second == c.end());
#if TEST_STD_VER >= 20
- assert(!c.contains(v));
+ assert(!c.contains(v));
#endif
+ }
+
+ // const
+ {
+ Container const& c = container;
+ S v(1);
+ assert(c.find(v) == c.end());
+ assert(c.count(v) == 0);
+ assert(c.lower_bound(v) == c.end());
+ assert(c.upper_bound(v) == c.end());
+ assert(c.equal_range(v).first == c.end());
+ assert(c.equal_range(v).second == c.end());
+#if TEST_STD_VER >= 20
+ assert(!c.contains(v));
+#endif
+ }
}
int main(int, char**) {
More information about the libcxx-commits
mailing list