[libcxx-commits] [libcxx] [libc++] Introduce _LIBCPP_COMPRESSED_ELEMENT (PR #134253)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Mon Sep 15 03:19:02 PDT 2025
https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/134253
>From 9feef3ea141001a178d7fcc9825b3ca299dbc0d3 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 3 Apr 2025 16:10:54 +0200
Subject: [PATCH] [libc++] Introduce _LIBCPP_COMPRESSED_ELEMENT
---
libcxx/docs/ReleaseNotes/22.rst | 7 +-
libcxx/include/__memory/compressed_pair.h | 6 ++
libcxx/include/ext/hash_map | 41 ++---------
libcxx/include/map | 46 ++----------
libcxx/include/tuple | 74 +++----------------
libcxx/include/unordered_map | 87 +++--------------------
6 files changed, 38 insertions(+), 223 deletions(-)
diff --git a/libcxx/docs/ReleaseNotes/22.rst b/libcxx/docs/ReleaseNotes/22.rst
index e56f0a88db138..bc89baff9e607 100644
--- a/libcxx/docs/ReleaseNotes/22.rst
+++ b/libcxx/docs/ReleaseNotes/22.rst
@@ -59,9 +59,10 @@ Improvements and New Features
by up to 2.5x
- The performance of ``erase(iterator, iterator)`` in the unordered containers has been improved by up to 1.9x
- The performance of ``map::insert_or_assign`` has been improved by up to 2x
-
- ``ofstream::write`` has been optimized to pass through large strings to system calls directly instead of copying them
in chunks into a buffer.
+- Multiple internal types have been refactored to use ``[[no_unique_address]]``, resulting in faster compile times and
+ reduced debug information.
Deprecations and Removals
-------------------------
@@ -89,5 +90,9 @@ ABI Affecting Changes
``_LIBCPP_ABI_NO_ITERATOR_BASES``. If you are using this flag and care about ABI stability, you should set
``_LIBCPP_ABI_NO_REVERSE_ITERATOR_SECOND_MEMBER`` as well.
+- The internal types ``__map_value_compare``, ``__tuple_leaf``, ``__unordered_map_hasher``, ``__unordered_map_equal``,
+ ``__hash_map_hasher`` and ``__hash_map_equal`` have been refactored to use ``_LIBCPP_COMPRESSED_ELEMENT`` instead of
+ potentially inheriting from the types they wrap. At this point in time we are not aware of any ABI breaks this causes.
+
Build System Changes
--------------------
diff --git a/libcxx/include/__memory/compressed_pair.h b/libcxx/include/__memory/compressed_pair.h
index 12163f4af61cf..d9d2720f9c9e4 100644
--- a/libcxx/include/__memory/compressed_pair.h
+++ b/libcxx/include/__memory/compressed_pair.h
@@ -80,6 +80,10 @@ class __compressed_pair_padding {
template <class _ToPad>
class __compressed_pair_padding<_ToPad, true> {};
+# define _LIBCPP_COMPRESSED_ELEMENT(T1, Initializer1) \
+ _LIBCPP_NO_UNIQUE_ADDRESS T1 Initializer1; \
+ _LIBCPP_NO_UNIQUE_ADDRESS ::std::__compressed_pair_padding<T1> _LIBCPP_CONCAT3(__padding_, __LINE__, _)
+
// TODO: Fix the ABI for GCC as well once https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121637 is fixed
# ifdef _LIBCPP_COMPILER_GCC
# define _LIBCPP_COMPRESSED_PAIR(T1, Initializer1, T2, Initializer2) \
@@ -121,6 +125,8 @@ class __compressed_pair_padding<_ToPad, true> {};
# endif
#else
+# define _LIBCPP_COMPRESSED_ELEMENT(T1, Initializer1) _LIBCPP_NO_UNIQUE_ADDRESS T1 Initializer1
+
# define _LIBCPP_COMPRESSED_PAIR(T1, Name1, T2, Name2) \
_LIBCPP_NO_UNIQUE_ADDRESS T1 Name1; \
_LIBCPP_NO_UNIQUE_ADDRESS T2 Name2
diff --git a/libcxx/include/ext/hash_map b/libcxx/include/ext/hash_map
index 46815eaffa8bd..722763b8df60a 100644
--- a/libcxx/include/ext/hash_map
+++ b/libcxx/include/ext/hash_map
@@ -224,21 +224,9 @@ _LIBCPP_WARNING("Use of the header <ext/hash_map> is deprecated. Migrate to <un
namespace __gnu_cxx {
-template <class _Tp, class _Hash, bool = std::is_empty<_Hash>::value && !std::__libcpp_is_final<_Hash>::value >
-class __hash_map_hasher : private _Hash {
-public:
- _LIBCPP_HIDE_FROM_ABI __hash_map_hasher() : _Hash() {}
- _LIBCPP_HIDE_FROM_ABI __hash_map_hasher(const _Hash& __h) : _Hash(__h) {}
- _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const { return *this; }
- _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Tp& __x) const { return static_cast<const _Hash&>(*this)(__x.first); }
- _LIBCPP_HIDE_FROM_ABI size_t operator()(const typename _Tp::first_type& __x) const {
- return static_cast<const _Hash&>(*this)(__x);
- }
-};
-
template <class _Tp, class _Hash>
-class __hash_map_hasher<_Tp, _Hash, false> {
- _Hash __hash_;
+class __hash_map_hasher {
+ _LIBCPP_COMPRESSED_ELEMENT(_Hash, __hash_);
public:
_LIBCPP_HIDE_FROM_ABI __hash_map_hasher() : __hash_() {}
@@ -248,30 +236,9 @@ public:
_LIBCPP_HIDE_FROM_ABI size_t operator()(const typename _Tp::first_type& __x) const { return __hash_(__x); }
};
-template <class _Tp, class _Pred, bool = std::is_empty<_Pred>::value && !std::__libcpp_is_final<_Pred>::value >
-class __hash_map_equal : private _Pred {
-public:
- _LIBCPP_HIDE_FROM_ABI __hash_map_equal() : _Pred() {}
- _LIBCPP_HIDE_FROM_ABI __hash_map_equal(const _Pred& __p) : _Pred(__p) {}
- _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const { return *this; }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const _Tp& __y) const {
- return static_cast<const _Pred&>(*this)(__x.first, __y.first);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const typename _Tp::first_type& __x, const _Tp& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y.first);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Tp& __x, const typename _Tp::first_type& __y) const {
- return static_cast<const _Pred&>(*this)(__x.first, __y);
- }
- _LIBCPP_HIDE_FROM_ABI bool
- operator()(const typename _Tp::first_type& __x, const typename _Tp::first_type& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y);
- }
-};
-
template <class _Tp, class _Pred>
-class __hash_map_equal<_Tp, _Pred, false> {
- _Pred __pred_;
+class __hash_map_equal {
+ _LIBCPP_COMPRESSED_ELEMENT(_Pred, __pred_);
public:
_LIBCPP_HIDE_FROM_ABI __hash_map_equal() : __pred_() {}
diff --git a/libcxx/include/map b/libcxx/include/map
index f428c781e5036..76a5062ac4991 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -633,47 +633,9 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Key,
- class _CP,
- class _Compare,
- bool = is_empty<_Compare>::value && !__libcpp_is_final<_Compare>::value>
-class __map_value_compare : private _Compare {
-public:
- _LIBCPP_HIDE_FROM_ABI __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value)
- : _Compare() {}
- _LIBCPP_HIDE_FROM_ABI __map_value_compare(_Compare __c) _NOEXCEPT_(is_nothrow_copy_constructible<_Compare>::value)
- : _Compare(__c) {}
- _LIBCPP_HIDE_FROM_ABI const _Compare& key_comp() const _NOEXCEPT { return *this; }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x.first, __y.first);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _Key& __y) const {
- return static_cast<const _Compare&>(*this)(__x.first, __y);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x, __y.first);
- }
- _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Compare>) {
- using std::swap;
- swap(static_cast<_Compare&>(*this), static_cast<_Compare&>(__y));
- }
-
-# if _LIBCPP_STD_VER >= 14
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _CP& __y) const {
- return static_cast<const _Compare&>(*this)(__x, __y.first);
- }
-
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _CP& __x, const _K2& __y) const {
- return static_cast<const _Compare&>(*this)(__x.first, __y);
- }
-# endif
-};
-
template <class _Key, class _CP, class _Compare>
-class __map_value_compare<_Key, _CP, _Compare, false> {
- _Compare __comp_;
+class __map_value_compare {
+ _LIBCPP_COMPRESSED_ELEMENT(_Compare, __comp_);
public:
_LIBCPP_HIDE_FROM_ABI __map_value_compare() _NOEXCEPT_(is_nothrow_default_constructible<_Compare>::value)
@@ -747,9 +709,9 @@ struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _
};
# endif // _LIBCPP_STD_VER >= 14
-template <class _Key, class _CP, class _Compare, bool __b>
+template <class _Key, class _CP, class _Compare>
inline _LIBCPP_HIDE_FROM_ABI void
-swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x, __map_value_compare<_Key, _CP, _Compare, __b>& __y)
+swap(__map_value_compare<_Key, _CP, _Compare>& __x, __map_value_compare<_Key, _CP, _Compare>& __y)
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
__x.swap(__y);
}
diff --git a/libcxx/include/tuple b/libcxx/include/tuple
index b0d0c38b115a2..c3cc35aeda891 100644
--- a/libcxx/include/tuple
+++ b/libcxx/include/tuple
@@ -229,6 +229,7 @@ template <class... Types>
# include <__fwd/pair.h>
# include <__fwd/tuple.h>
# include <__memory/allocator_arg_t.h>
+# include <__memory/compressed_pair.h>
# include <__memory/uses_allocator.h>
# include <__tuple/find_index.h>
# include <__tuple/ignore.h>
@@ -348,25 +349,25 @@ using __tuple_common_comparison_category _LIBCPP_NODEBUG =
// __tuple_leaf
-template <size_t _Ip, class _Hp, bool = is_empty<_Hp>::value && !__libcpp_is_final<_Hp>::value >
+template <size_t _Ip, class _Hp>
class __tuple_leaf;
-template <size_t _Ip, class _Hp, bool _Ep>
+template <size_t _Ip, class _Hp>
inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-swap(__tuple_leaf<_Ip, _Hp, _Ep>& __x, __tuple_leaf<_Ip, _Hp, _Ep>& __y) noexcept(__is_nothrow_swappable_v<_Hp>) {
+swap(__tuple_leaf<_Ip, _Hp>& __x, __tuple_leaf<_Ip, _Hp>& __y) noexcept(__is_nothrow_swappable_v<_Hp>) {
swap(__x.get(), __y.get());
}
-template <size_t _Ip, class _Hp, bool _Ep>
+template <size_t _Ip, class _Hp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void
-swap(const __tuple_leaf<_Ip, _Hp, _Ep>& __x,
- const __tuple_leaf<_Ip, _Hp, _Ep>& __y) noexcept(__is_nothrow_swappable_v<const _Hp>) {
+swap(const __tuple_leaf<_Ip, _Hp>& __x,
+ const __tuple_leaf<_Ip, _Hp>& __y) noexcept(__is_nothrow_swappable_v<const _Hp>) {
swap(__x.get(), __y.get());
}
-template <size_t _Ip, class _Hp, bool>
+template <size_t _Ip, class _Hp>
class __tuple_leaf {
- _Hp __value_;
+ _LIBCPP_COMPRESSED_ELEMENT(_Hp, __value_);
public:
_LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
@@ -442,63 +443,6 @@ public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Hp& get() const _NOEXCEPT { return __value_; }
};
-template <size_t _Ip, class _Hp>
-class __tuple_leaf<_Ip, _Hp, true> : private __remove_cv_t<_Hp> {
-public:
- _LIBCPP_CONSTEXPR_SINCE_CXX14 __tuple_leaf& operator=(const __tuple_leaf&) = delete;
-
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf() noexcept(is_nothrow_default_constructible<_Hp>::value) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 0>, const _Alloc&) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a)
- : _Hp(allocator_arg_t(), __a) {}
-
- template <class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a) : _Hp(__a) {}
-
- template <class _Tp,
- __enable_if_t< _And< _IsNotSame<__remove_cvref_t<_Tp>, __tuple_leaf>, is_constructible<_Hp, _Tp> >::value,
- int> = 0>
- _LIBCPP_HIDE_FROM_ABI
- _LIBCPP_CONSTEXPR_SINCE_CXX14 explicit __tuple_leaf(_Tp&& __t) noexcept(is_nothrow_constructible<_Hp, _Tp>::value)
- : _Hp(std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 0>, const _Alloc&, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 1>, const _Alloc& __a, _Tp&& __t)
- : _Hp(allocator_arg_t(), __a, std::forward<_Tp>(__t)) {}
-
- template <class _Tp, class _Alloc>
- _LIBCPP_HIDE_FROM_ABI constexpr explicit __tuple_leaf(integral_constant<int, 2>, const _Alloc& __a, _Tp&& __t)
- : _Hp(std::forward<_Tp>(__t), __a) {}
-
- __tuple_leaf(__tuple_leaf const&) = default;
- __tuple_leaf(__tuple_leaf&&) = default;
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int
- swap(__tuple_leaf& __t) noexcept(__is_nothrow_swappable_v<__tuple_leaf>) {
- std::swap(*this, __t);
- return 0;
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 int swap(const __tuple_leaf& __rhs) const
- noexcept(__is_nothrow_swappable_v<const __tuple_leaf>) {
- std::swap(*this, __rhs);
- return 0;
- }
-
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Hp& get() _NOEXCEPT { return static_cast<_Hp&>(*this); }
- _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 const _Hp& get() const _NOEXCEPT {
- return static_cast<const _Hp&>(*this);
- }
-};
-
template <class... _Tp>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 void __swallow(_Tp&&...) _NOEXCEPT {}
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index 9b02ecf0393d0..388c3c3552d47 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -643,34 +643,9 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
-template <class _Key,
- class _Cp,
- class _Hash,
- class _Pred,
- bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value>
-class __unordered_map_hasher : private _Hash {
-public:
- _LIBCPP_HIDE_FROM_ABI __unordered_map_hasher() _NOEXCEPT_(is_nothrow_default_constructible<_Hash>::value) : _Hash() {}
- _LIBCPP_HIDE_FROM_ABI __unordered_map_hasher(const _Hash& __h) _NOEXCEPT_(is_nothrow_copy_constructible<_Hash>::value)
- : _Hash(__h) {}
- _LIBCPP_HIDE_FROM_ABI const _Hash& hash_function() const _NOEXCEPT { return *this; }
- _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Cp& __x) const { return static_cast<const _Hash&>(*this)(__x.first); }
- _LIBCPP_HIDE_FROM_ABI size_t operator()(const _Key& __x) const { return static_cast<const _Hash&>(*this)(__x); }
-# if _LIBCPP_STD_VER >= 20
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI size_t operator()(const _K2& __x) const {
- return static_cast<const _Hash&>(*this)(__x);
- }
-# endif
- _LIBCPP_HIDE_FROM_ABI void swap(__unordered_map_hasher& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Hash>) {
- using std::swap;
- swap(static_cast<_Hash&>(*this), static_cast<_Hash&>(__y));
- }
-};
-
template <class _Key, class _Cp, class _Hash, class _Pred>
-class __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, false> {
- _Hash __hash_;
+class __unordered_map_hasher {
+ _LIBCPP_COMPRESSED_ELEMENT(_Hash, __hash_);
public:
_LIBCPP_HIDE_FROM_ABI __unordered_map_hasher() _NOEXCEPT_(is_nothrow_default_constructible<_Hash>::value)
@@ -692,60 +667,16 @@ public:
}
};
-template <class _Key, class _Cp, class _Hash, class _Pred, bool __b>
+template <class _Key, class _Cp, class _Hash, class _Pred>
inline _LIBCPP_HIDE_FROM_ABI void
-swap(__unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __x,
- __unordered_map_hasher<_Key, _Cp, _Hash, _Pred, __b>& __y) _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
+swap(__unordered_map_hasher<_Key, _Cp, _Hash, _Pred>& __x, __unordered_map_hasher<_Key, _Cp, _Hash, _Pred>& __y)
+ _NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
__x.swap(__y);
}
-template <class _Key,
- class _Cp,
- class _Pred,
- class _Hash,
- bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value>
-class __unordered_map_equal : private _Pred {
-public:
- _LIBCPP_HIDE_FROM_ABI __unordered_map_equal() _NOEXCEPT_(is_nothrow_default_constructible<_Pred>::value) : _Pred() {}
- _LIBCPP_HIDE_FROM_ABI __unordered_map_equal(const _Pred& __p) _NOEXCEPT_(is_nothrow_copy_constructible<_Pred>::value)
- : _Pred(__p) {}
- _LIBCPP_HIDE_FROM_ABI const _Pred& key_eq() const _NOEXCEPT { return *this; }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Cp& __y) const {
- return static_cast<const _Pred&>(*this)(__x.first, __y.first);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _Key& __y) const {
- return static_cast<const _Pred&>(*this)(__x.first, __y);
- }
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _Cp& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);
- }
-# if _LIBCPP_STD_VER >= 20
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Cp& __x, const _K2& __y) const {
- return static_cast<const _Pred&>(*this)(__x.first, __y);
- }
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Cp& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y.__get_value().first);
- }
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _Key& __x, const _K2& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y);
- }
- template <typename _K2>
- _LIBCPP_HIDE_FROM_ABI bool operator()(const _K2& __x, const _Key& __y) const {
- return static_cast<const _Pred&>(*this)(__x, __y);
- }
-# endif
- _LIBCPP_HIDE_FROM_ABI void swap(__unordered_map_equal& __y) _NOEXCEPT_(__is_nothrow_swappable_v<_Pred>) {
- using std::swap;
- swap(static_cast<_Pred&>(*this), static_cast<_Pred&>(__y));
- }
-};
-
template <class _Key, class _Cp, class _Pred, class _Hash>
-class __unordered_map_equal<_Key, _Cp, _Pred, _Hash, false> {
- _Pred __pred_;
+class __unordered_map_equal {
+ _LIBCPP_COMPRESSED_ELEMENT(_Pred, __pred_);
public:
_LIBCPP_HIDE_FROM_ABI __unordered_map_equal() _NOEXCEPT_(is_nothrow_default_constructible<_Pred>::value)
@@ -780,9 +711,9 @@ public:
}
};
-template <class _Key, class _Cp, class _Pred, class _Hash, bool __b>
+template <class _Key, class _Cp, class _Pred, class _Hash>
inline _LIBCPP_HIDE_FROM_ABI void
-swap(__unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __x, __unordered_map_equal<_Key, _Cp, _Pred, _Hash, __b>& __y)
+swap(__unordered_map_equal<_Key, _Cp, _Pred, _Hash>& __x, __unordered_map_equal<_Key, _Cp, _Pred, _Hash>& __y)
_NOEXCEPT_(_NOEXCEPT_(__x.swap(__y))) {
__x.swap(__y);
}
More information about the libcxx-commits
mailing list