[libcxx-commits] [libcxx] [libc++] Fix passing through object to comparisons in __tree (PR #186341)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Mar 18 08:12:00 PDT 2026


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/186341

>From 784b4e83a75c8dacf7eec78ceba9bd9a4217ffd2 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Wed, 11 Mar 2026 15:00:04 +0100
Subject: [PATCH 1/3] [libc++] Fix passing through object to comparisons in
 __tree

---
 libcxx/include/__tree                         |  4 +--
 libcxx/include/string                         | 33 ++++++++++++-------
 ..._transparently_comparable.compile.pass.cpp | 24 ++++++++++++++
 3 files changed, 48 insertions(+), 13 deletions(-)
 create mode 100644 libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp

diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 2c059a92473c7..bb8c4f3f8c623 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -1881,9 +1881,9 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) {
   }
 
   __node_base_pointer* __node_ptr = __root_ptr();
-  auto&& __transparent            = std::__as_transparent<_Key>(value_comp());
+  auto&& __transparent            = std::__as_transparent<key_type>(value_comp());
   auto __comp =
-      __lazy_synth_three_way_comparator<__make_transparent_t<_Key, _Compare>, _Key, value_type>(__transparent);
+      __lazy_synth_three_way_comparator<__make_transparent_t<key_type, _Compare>, _Key, value_type>(__transparent);
 
   while (true) {
     auto __comp_res = __comp(__v, __nd->__get_value());
diff --git a/libcxx/include/string b/libcxx/include/string
index c59684c32a3fe..fc14e27787944 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -625,6 +625,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
 #  include <__string/char_traits.h>
 #  include <__string/extern_template_lists.h>
 #  include <__type_traits/conditional.h>
+#  include <__type_traits/desugars_to.h>
 #  include <__type_traits/enable_if.h>
 #  include <__type_traits/is_allocator.h>
 #  include <__type_traits/is_array.h>
@@ -2602,19 +2603,29 @@ struct __default_three_way_comparator<basic_string<_CharT, _Traits, _Alloc>, bas
 };
 #  endif
 
-template <class _Comparator, class _CharT, class _Traits, class _Alloc>
-inline const bool __is_transparently_comparable_v<_Comparator,
-                                                  basic_string<_CharT, _Traits, _Alloc>,
-                                                  const _CharT*,
-                                                  __enable_if_t<__is_generic_transparent_comparator_v<_Comparator> > > =
-    true;
+template <class _Comparator, class _CharT2, class _CharT, class _Traits, class _Alloc>
+inline const bool __is_transparently_comparable_v<_Comparator, basic_string<_CharT, _Traits, _Alloc>, _CharT2*> =
+    is_same<_CharT, __remove_cv_t<_CharT2> >::value &&
+    (__desugars_to_v<__less_tag,
+                     _Comparator,
+                     basic_string<_CharT, _Traits, _Alloc>,
+                     basic_string<_CharT, _Traits, _Alloc> > ||
+     __desugars_to_v<__greater_tag,
+                     _Comparator,
+                     basic_string<_CharT, _Traits, _Alloc>,
+                     basic_string<_CharT, _Traits, _Alloc> >);
+
+template <class _Comparator, class _CharT2, class _CharT, class _Traits, class _Alloc>
+inline const bool __is_transparently_comparable_v<_Comparator, _CharT2*, basic_string<_CharT, _Traits, _Alloc> > =
+    __is_transparently_comparable_v<_Comparator, basic_string<_CharT, _Traits, _Alloc>, _CharT2*>;
 
 template <class _Comparator, class _CharT, class _Traits, class _Alloc, size_t _Np>
-inline const bool __is_transparently_comparable_v<_Comparator,
-                                                  basic_string<_CharT, _Traits, _Alloc>,
-                                                  _CharT[_Np],
-                                                  __enable_if_t<__is_generic_transparent_comparator_v<_Comparator> > > =
-    true;
+inline const bool __is_transparently_comparable_v<_Comparator, basic_string<_CharT, _Traits, _Alloc>, _CharT[_Np]> =
+    __is_transparently_comparable_v<_Comparator, basic_string<_CharT, _Traits, _Alloc>, const _CharT*>;
+
+template <class _Comparator, class _CharT, class _Traits, class _Alloc, size_t _Np>
+inline const bool __is_transparently_comparable_v<_Comparator, _CharT[_Np], basic_string<_CharT, _Traits, _Alloc> > =
+    __is_transparently_comparable_v<_Comparator, basic_string<_CharT, _Traits, _Alloc>, const _CharT*>;
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _InputIterator,
diff --git a/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
new file mode 100644
index 0000000000000..87f83b3d784aa
--- /dev/null
+++ b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
@@ -0,0 +1,24 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Check that `__is_transparently_comparable_v` is true when we expect it to be
+
+#include <functional>
+#include <string>
+#include <__type_traits/desugars_to.h>
+
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, const char*>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char*>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char[5]>);
+
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, const char*, std::string>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char*, std::string>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char[5], std::string>);
+
+static_assert(
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, std::string, char[5]>);

>From 7cff534ba54abe361923b11eb6118487e685fa3e Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 18 Mar 2026 10:58:45 -0400
Subject: [PATCH 2/3] Add slight coverage

---
 .../is_transparently_comparable.compile.pass.cpp            | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
index 87f83b3d784aa..79113e05f7ab8 100644
--- a/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
+++ b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
@@ -22,3 +22,9 @@ static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char[
 
 static_assert(
     !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, std::string, char[5]>);
+static_assert(
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, char[5], std::string>);
+static_assert(
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, std::string, char const*>);
+static_assert(
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, char const*, std::string>);

>From 6eaaab2a5c1b925bf07f0ab6db76a82f6ecc0deb Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Wed, 18 Mar 2026 11:11:43 -0400
Subject: [PATCH 3/3] Make tests work with older standards

---
 ..._transparently_comparable.compile.pass.cpp | 22 ++++++++++---------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
index 79113e05f7ab8..8ab8cb0be8418 100644
--- a/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
+++ b/libcxx/test/libcxx/type_traits/is_transparently_comparable.compile.pass.cpp
@@ -12,19 +12,21 @@
 #include <string>
 #include <__type_traits/desugars_to.h>
 
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, const char*>);
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char*>);
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char[5]>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, const char*>, "");
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char*>, "");
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, std::string, char[5]>, "");
 
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, const char*, std::string>);
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char*, std::string>);
-static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char[5], std::string>);
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, const char*, std::string>, "");
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char*, std::string>, "");
+static_assert(std::__is_transparently_comparable_v<std::less<std::string>, char[5], std::string>, "");
 
 static_assert(
-    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, std::string, char[5]>);
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string> >, std::string, char[5]>, "");
 static_assert(
-    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, char[5], std::string>);
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string> >, char[5], std::string>, "");
 static_assert(
-    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, std::string, char const*>);
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string> >, std::string, char const*>,
+    "");
 static_assert(
-    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string>>, char const*, std::string>);
+    !std::__is_transparently_comparable_v<std::less<std::reference_wrapper<std::string> >, char const*, std::string>,
+    "");



More information about the libcxx-commits mailing list