[libcxx-commits] [libcxx] b0668d8 - [libc++] Make sure that __desugars_to isn't tripped up by reference_wrapper, const and ref qualifiers (#132092)
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue Mar 25 11:29:09 PDT 2025
Author: Louis Dionne
Date: 2025-03-25T14:29:06-04:00
New Revision: b0668d859b237f6991f416b688cedb7389354fd8
URL: https://github.com/llvm/llvm-project/commit/b0668d859b237f6991f416b688cedb7389354fd8
DIFF: https://github.com/llvm/llvm-project/commit/b0668d859b237f6991f416b688cedb7389354fd8.diff
LOG: [libc++] Make sure that __desugars_to isn't tripped up by reference_wrapper, const and ref qualifiers (#132092)
Previously, const and ref qualification on an operation would cause
__desugars_to to report false, which would lead to unnecessary
pessimizations. The same holds for reference_wrapper.
In practice, const and ref qualifications on the operation itself are
not relevant to determining whether an operation desugars to something
else or not, so can be ignored.
We are not stripping volatile qualifiers from operations in this patch
because we feel that this requires additional discussion.
Fixes #129312
Added:
libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp
libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp
Modified:
libcxx/include/__algorithm/sort.h
libcxx/include/__algorithm/stable_sort.h
libcxx/include/__functional/reference_wrapper.h
libcxx/include/__type_traits/desugars_to.h
Removed:
################################################################################
diff --git a/libcxx/include/__algorithm/sort.h b/libcxx/include/__algorithm/sort.h
index 8dd0721f2c65f..4332b62544b40 100644
--- a/libcxx/include/__algorithm/sort.h
+++ b/libcxx/include/__algorithm/sort.h
@@ -34,7 +34,6 @@
#include <__type_traits/is_constant_evaluated.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_copyable.h>
-#include <__type_traits/remove_cvref.h>
#include <__utility/move.h>
#include <__utility/pair.h>
#include <climits>
@@ -52,8 +51,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
template <class _Compare, class _Iter, class _Tp = typename iterator_traits<_Iter>::value_type>
inline const bool __use_branchless_sort =
__libcpp_is_contiguous_iterator<_Iter>::value && __is_cheap_to_copy<_Tp> && is_arithmetic<_Tp>::value &&
- (__desugars_to_v<__less_tag, __remove_cvref_t<_Compare>, _Tp, _Tp> ||
- __desugars_to_v<__greater_tag, __remove_cvref_t<_Compare>, _Tp, _Tp>);
+ (__desugars_to_v<__less_tag, _Compare, _Tp, _Tp> || __desugars_to_v<__greater_tag, _Compare, _Tp, _Tp>);
namespace __detail {
diff --git a/libcxx/include/__algorithm/stable_sort.h b/libcxx/include/__algorithm/stable_sort.h
index 76d9e5557008f..c7f9780e3f627 100644
--- a/libcxx/include/__algorithm/stable_sort.h
+++ b/libcxx/include/__algorithm/stable_sort.h
@@ -29,7 +29,6 @@
#include <__type_traits/is_integral.h>
#include <__type_traits/is_same.h>
#include <__type_traits/is_trivially_assignable.h>
-#include <__type_traits/remove_cvref.h>
#include <__utility/move.h>
#include <__utility/pair.h>
@@ -246,8 +245,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX26 void __stable_sort(
}
#if _LIBCPP_STD_VER >= 17
- constexpr auto __default_comp =
- __desugars_to_v<__totally_ordered_less_tag, __remove_cvref_t<_Compare>, value_type, value_type >;
+ constexpr auto __default_comp = __desugars_to_v<__totally_ordered_less_tag, _Compare, value_type, value_type >;
constexpr auto __integral_value =
is_integral_v<value_type > && is_same_v< value_type&, __iter_reference<_RandomAccessIterator>>;
constexpr auto __allowed_radix_sort = __default_comp && __integral_value;
diff --git a/libcxx/include/__functional/reference_wrapper.h b/libcxx/include/__functional/reference_wrapper.h
index d6cd6428f22db..3678b5553c444 100644
--- a/libcxx/include/__functional/reference_wrapper.h
+++ b/libcxx/include/__functional/reference_wrapper.h
@@ -15,6 +15,7 @@
#include <__config>
#include <__functional/weak_result_type.h>
#include <__memory/addressof.h>
+#include <__type_traits/desugars_to.h>
#include <__type_traits/enable_if.h>
#include <__type_traits/invoke.h>
#include <__type_traits/is_const.h>
@@ -149,6 +150,11 @@ void ref(const _Tp&&) = delete;
template <class _Tp>
void cref(const _Tp&&) = delete;
+// Let desugars-to pass through std::reference_wrapper
+template <class _CanonicalTag, class _Operation, class... _Args>
+inline const bool __desugars_to_v<_CanonicalTag, reference_wrapper<_Operation>, _Args...> =
+ __desugars_to_v<_CanonicalTag, _Operation, _Args...>;
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___FUNCTIONAL_REFERENCE_WRAPPER_H
diff --git a/libcxx/include/__type_traits/desugars_to.h b/libcxx/include/__type_traits/desugars_to.h
index 452c70bfbad66..b67baae31b181 100644
--- a/libcxx/include/__type_traits/desugars_to.h
+++ b/libcxx/include/__type_traits/desugars_to.h
@@ -52,6 +52,18 @@ struct __totally_ordered_less_tag {};
template <class _CanonicalTag, class _Operation, class... _Args>
inline const bool __desugars_to_v = false;
+// For the purpose of determining whether something desugars to something else,
+// we disregard const and ref qualifiers on the operation itself.
+template <class _CanonicalTag, class _Operation, class... _Args>
+inline const bool __desugars_to_v<_CanonicalTag, _Operation const, _Args...> =
+ __desugars_to_v<_CanonicalTag, _Operation, _Args...>;
+template <class _CanonicalTag, class _Operation, class... _Args>
+inline const bool __desugars_to_v<_CanonicalTag, _Operation&, _Args...> =
+ __desugars_to_v<_CanonicalTag, _Operation, _Args...>;
+template <class _CanonicalTag, class _Operation, class... _Args>
+inline const bool __desugars_to_v<_CanonicalTag, _Operation&&, _Args...> =
+ __desugars_to_v<_CanonicalTag, _Operation, _Args...>;
+
_LIBCPP_END_NAMESPACE_STD
#endif // _LIBCPP___TYPE_TRAITS_DESUGARS_TO_H
diff --git a/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp b/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp
new file mode 100644
index 0000000000000..4ed6d15ee9e95
--- /dev/null
+++ b/libcxx/test/libcxx/type_traits/desugars_to.compile.pass.cpp
@@ -0,0 +1,42 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: FROZEN-CXX03-HEADERS-FIXME
+
+// This test requires variable templates
+// UNSUPPORTED: gcc && c++11
+
+#include <__type_traits/desugars_to.h>
+
+struct Tag {};
+struct Operation {};
+
+namespace std {
+template <>
+bool const __desugars_to_v<Tag, Operation> = true;
+}
+
+void tests() {
+ // Make sure that __desugars_to is false by default
+ {
+ struct Foo {};
+ static_assert(!std::__desugars_to_v<Tag, Foo>, "");
+ }
+
+ // Make sure that __desugars_to bypasses const and ref qualifiers on the operation
+ {
+ static_assert(std::__desugars_to_v<Tag, Operation>, ""); // no quals
+ static_assert(std::__desugars_to_v<Tag, Operation const>, "");
+
+ static_assert(std::__desugars_to_v<Tag, Operation&>, "");
+ static_assert(std::__desugars_to_v<Tag, Operation const&>, "");
+
+ static_assert(std::__desugars_to_v<Tag, Operation&&>, "");
+ static_assert(std::__desugars_to_v<Tag, Operation const&&>, "");
+ }
+}
diff --git a/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp b/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp
new file mode 100644
index 0000000000000..1ce88feeadf28
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/function.objects/refwrap/desugars_to.compile.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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: FROZEN-CXX03-HEADERS-FIXME
+
+// This test requires variable templates
+// UNSUPPORTED: gcc && c++11
+
+// <functional>
+
+// reference_wrapper
+
+// Ensure that std::reference_wrapper does not inhibit optimizations based on the
+// std::__desugars_to internal helper.
+
+#include <functional>
+#include <__type_traits/desugars_to.h>
+
+struct Operation {};
+struct Tag {};
+
+namespace std {
+template <>
+bool const __desugars_to_v<Tag, Operation> = true;
+}
+
+static_assert(std::__desugars_to_v<Tag, Operation>, "something is wrong with the test");
+
+// make sure we pass through reference_wrapper
+static_assert(std::__desugars_to_v<Tag, std::reference_wrapper<Operation> >, "");
+static_assert(std::__desugars_to_v<Tag, std::reference_wrapper<Operation const> >, "");
More information about the libcxx-commits
mailing list