[libcxx-commits] [libcxx] [libc++] Remove __libcpp_allocate (PR #220981)
Nikolas Klauser via libcxx-commits
libcxx-commits at lists.llvm.org
Thu Sep 3 08:54:39 PDT 2026
https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/220981
We use `__libcpp_allocate` and friends only in very specific circumstances. Instead of providing a private API we can make `std::allocator` the default API for the uses of `__libcpp_allocate`.
>From c58125faa1fce1d1a2ac2affa97380016e7fc26f Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 3 Sep 2026 17:53:02 +0200
Subject: [PATCH] [libc++] Remove __libcpp_allocate
---
libcxx/include/CMakeLists.txt | 1 -
libcxx/include/__memory/allocator.h | 32 +++++---
.../__memory/unique_temporary_buffer.h | 19 ++++-
libcxx/include/__new/allocate.h | 78 -------------------
libcxx/include/__utility/small_buffer.h | 6 +-
libcxx/include/module.modulemap.in | 5 --
libcxx/include/new | 1 -
libcxx/src/include/aligned_alloc.h | 2 +-
8 files changed, 40 insertions(+), 104 deletions(-)
delete mode 100644 libcxx/include/__new/allocate.h
diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index b559309929a67..43d48e74a2546 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -650,7 +650,6 @@ set(files
__mutex/tag_types.h
__mutex/unique_lock.h
__new/align_val_t.h
- __new/allocate.h
__new/destroying_delete_t.h
__new/exceptions.h
__new/global_new_delete.h
diff --git a/libcxx/include/__memory/allocator.h b/libcxx/include/__memory/allocator.h
index dd8c8647c178a..1c6e632f8d356 100644
--- a/libcxx/include/__memory/allocator.h
+++ b/libcxx/include/__memory/allocator.h
@@ -15,7 +15,7 @@
#include <__cstddef/size_t.h>
#include <__memory/addressof.h>
#include <__memory/allocator_traits.h>
-#include <__new/allocate.h>
+#include <__new/align_val_t.h>
#include <__new/exceptions.h>
#include <__type_traits/is_const.h>
#include <__type_traits/is_constant_evaluated.h>
@@ -86,11 +86,12 @@ class allocator
static_assert(sizeof(_Tp) >= 0, "cannot allocate memory for an incomplete type");
if (__n > allocator_traits<allocator>::max_size(*this))
std::__throw_bad_array_new_length();
- if (__libcpp_is_constant_evaluated()) {
- return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
- } else {
- return std::__libcpp_allocate<_Tp>(__element_count(__n));
- }
+#if _LIBCPP_HAS_ALIGNED_ALLOCATION
+ if _LIBCPP_CONSTEXPR (_LIBCPP_ALIGNOF(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ return static_cast<_Tp*>(
+ __builtin_operator_new(__n * sizeof(value_type), static_cast<align_val_t>(_LIBCPP_ALIGNOF(value_type))));
+#endif
+ return static_cast<_Tp*>(__builtin_operator_new(__n * sizeof(value_type)));
}
#if _LIBCPP_STD_VER >= 23
@@ -100,14 +101,23 @@ class allocator
}
#endif
+#if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
+# define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) __VA_ARGS__
+#else
+# define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) /* nothing */
+#endif
+
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void deallocate(_Tp* __p, size_t __n) _NOEXCEPT {
- if (__libcpp_is_constant_evaluated()) {
- ::operator delete(__p);
- } else {
- std::__libcpp_deallocate<_Tp>(__p, __element_count(__n));
- }
+#if _LIBCPP_HAS_ALIGNED_ALLOCATION
+ if (_LIBCPP_ALIGNOF(value_type) > __STDCPP_DEFAULT_NEW_ALIGNMENT__)
+ return __builtin_operator_delete(__p _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __n * sizeof(value_type)),
+ static_cast<align_val_t>(_LIBCPP_ALIGNOF(value_type)));
+#endif
+ return __builtin_operator_delete(__p _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __n * sizeof(value_type)));
}
+#undef _LIBCPP_ONLY_IF_SIZED_DEALLOCATION
+
// C++20 Removed members
#if _LIBCPP_STD_VER <= 17
_LIBCPP_DEPRECATED_IN_CXX17 typedef _Tp* pointer;
diff --git a/libcxx/include/__memory/unique_temporary_buffer.h b/libcxx/include/__memory/unique_temporary_buffer.h
index 32a3f0f081c00..9af94433407eb 100644
--- a/libcxx/include/__memory/unique_temporary_buffer.h
+++ b/libcxx/include/__memory/unique_temporary_buffer.h
@@ -16,7 +16,6 @@
#include <__cstddef/ptrdiff_t.h>
#include <__memory/allocator.h>
#include <__memory/unique_ptr.h>
-#include <__new/allocate.h>
#include <__new/global_new_delete.h>
#include <__type_traits/is_constant_evaluated.h>
@@ -26,6 +25,14 @@
_LIBCPP_BEGIN_NAMESPACE_STD
+#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
+template <class _Tp>
+inline const bool __is_overaligned_for_new = _LIBCPP_ALIGNOF(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__;
+#else
+template <class _Tp>
+inline const bool __is_overaligned_for_new = _LIBCPP_ALIGNOF(_Tp) > _LIBCPP_ALIGNOF(max_align_t);
+#endif
+
template <class _Tp>
struct __temporary_buffer_deleter {
ptrdiff_t __count_; // ignored in non-constant evaluation
@@ -40,7 +47,11 @@ struct __temporary_buffer_deleter {
return;
}
- std::__libcpp_deallocate_unsized<_Tp>(__ptr);
+#if _LIBCPP_HAS_ALIGNED_ALLOCATION
+ if _LIBCPP_CONSTEXPR (__is_overaligned_for_new<_Tp>)
+ return __builtin_operator_delete(__ptr, static_cast<align_val_t>(_LIBCPP_ALIGNOF(_Tp)));
+#endif
+ return __builtin_operator_delete(__ptr);
}
};
@@ -64,14 +75,14 @@ __allocate_unique_temporary_buffer(ptrdiff_t __count) {
__count = __max_count;
while (__count > 0) {
#if _LIBCPP_HAS_ALIGNED_ALLOCATION
- if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) {
+ if _LIBCPP_CONSTEXPR (__is_overaligned_for_new<_Tp>) {
align_val_t __al = align_val_t(_LIBCPP_ALIGNOF(_Tp));
__ptr = static_cast<_Tp*>(::operator new(__count * sizeof(_Tp), __al, nothrow));
} else {
__ptr = static_cast<_Tp*>(::operator new(__count * sizeof(_Tp), nothrow));
}
#else
- if (__is_overaligned_for_new(_LIBCPP_ALIGNOF(_Tp))) {
+ if _LIBCPP_CONSTEXPR (__is_overaligned_for_new<_Tp>) {
// Since aligned operator new is unavailable, constructs an empty buffer rather than one with invalid alignment.
return __unique_buffer_type();
}
diff --git a/libcxx/include/__new/allocate.h b/libcxx/include/__new/allocate.h
deleted file mode 100644
index b9bc2e1a50710..0000000000000
--- a/libcxx/include/__new/allocate.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef _LIBCPP___NEW_ALLOCATE_H
-#define _LIBCPP___NEW_ALLOCATE_H
-
-#include <__config>
-#include <__cstddef/max_align_t.h>
-#include <__cstddef/size_t.h>
-#include <__new/align_val_t.h>
-#include <__type_traits/type_identity.h>
-#include <__utility/element_count.h>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-# pragma GCC system_header
-#endif
-
-_LIBCPP_BEGIN_NAMESPACE_STD
-
-_LIBCPP_CONSTEXPR inline _LIBCPP_HIDE_FROM_ABI bool __is_overaligned_for_new(size_t __align) _NOEXCEPT {
-#ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
- return __align > __STDCPP_DEFAULT_NEW_ALIGNMENT__;
-#else
- return __align > _LIBCPP_ALIGNOF(max_align_t);
-#endif
-}
-
-template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_NO_CFI _Tp*
-__libcpp_allocate(__element_count __n, [[__maybe_unused__]] size_t __align = _LIBCPP_ALIGNOF(_Tp)) {
- size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
-#if _LIBCPP_HAS_ALIGNED_ALLOCATION
- if (__is_overaligned_for_new(__align))
- return static_cast<_Tp*>(__builtin_operator_new(__size, static_cast<align_val_t>(__align)));
-#endif
-
- return static_cast<_Tp*>(__builtin_operator_new(__size));
-}
-
-#if defined(__cpp_sized_deallocation) && __cpp_sized_deallocation >= 201309L
-# define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) __VA_ARGS__
-#else
-# define _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(...) /* nothing */
-#endif
-
-template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI void
-__libcpp_deallocate(__type_identity_t<_Tp>* __ptr,
- __element_count __n,
- [[__maybe_unused__]] size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
- [[__maybe_unused__]] size_t __size = static_cast<size_t>(__n) * sizeof(_Tp);
-#if _LIBCPP_HAS_ALIGNED_ALLOCATION
- if (__is_overaligned_for_new(__align))
- return __builtin_operator_delete(
- __ptr _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __size), static_cast<align_val_t>(__align));
-#endif
- return __builtin_operator_delete(__ptr _LIBCPP_ONLY_IF_SIZED_DEALLOCATION(, __size));
-}
-
-#undef _LIBCPP_ONLY_IF_SIZED_DEALLOCATION
-
-template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI void __libcpp_deallocate_unsized(
- __type_identity_t<_Tp>* __ptr, [[__maybe_unused__]] size_t __align = _LIBCPP_ALIGNOF(_Tp)) _NOEXCEPT {
-#if _LIBCPP_HAS_ALIGNED_ALLOCATION
- if (__is_overaligned_for_new(__align))
- return __builtin_operator_delete(__ptr, static_cast<align_val_t>(__align));
-#endif
- return __builtin_operator_delete(__ptr);
-}
-_LIBCPP_END_NAMESPACE_STD
-
-#endif // _LIBCPP___NEW_ALLOCATE_H
diff --git a/libcxx/include/__utility/small_buffer.h b/libcxx/include/__utility/small_buffer.h
index 132a57f0fefab..98577bbc0564c 100644
--- a/libcxx/include/__utility/small_buffer.h
+++ b/libcxx/include/__utility/small_buffer.h
@@ -12,8 +12,8 @@
#include <__config>
#include <__cstddef/byte.h>
#include <__cstddef/size_t.h>
+#include <__memory/allocator.h>
#include <__memory/construct_at.h>
-#include <__new/allocate.h>
#include <__new/launder.h>
#include <__type_traits/decay.h>
#include <__type_traits/is_trivially_constructible.h>
@@ -68,7 +68,7 @@ class __small_buffer {
if constexpr (__fits_in_buffer<_Stored>) {
return std::launder(reinterpret_cast<_Stored*>(__buffer_));
} else {
- byte* __allocation = reinterpret_cast<byte*>(std::__libcpp_allocate<_Stored>(__element_count(1)));
+ byte* __allocation = reinterpret_cast<byte*>(std::allocator<_Stored>().allocate(1));
std::construct_at(reinterpret_cast<byte**>(__buffer_), __allocation);
return std::launder(reinterpret_cast<_Stored*>(__allocation));
}
@@ -77,7 +77,7 @@ class __small_buffer {
template <class _Stored>
_LIBCPP_HIDE_FROM_ABI void __dealloc() noexcept {
if constexpr (!__fits_in_buffer<_Stored>)
- std::__libcpp_deallocate<_Stored>(__get<_Stored>(), __element_count(1));
+ std::allocator<_Stored>().deallocate(__get<_Stored>(), 1);
}
template <class _Stored, class... _Args>
diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in
index f0defc3040ef9..aaedf93a81aef 100644
--- a/libcxx/include/module.modulemap.in
+++ b/libcxx/include/module.modulemap.in
@@ -1781,11 +1781,6 @@ module std {
module new {
header "new"
module align_val_t { header "__new/align_val_t.h" }
- module allocate {
- header "__new/allocate.h"
- export std.utility.element_count // used as part of the API
- export * // TODO: Workaround for https://llvm.org/PR120108
- }
module destroying_delete_t { header "__new/destroying_delete_t.h" }
module exceptions { header "__new/exceptions.h" }
module global_new_delete {
diff --git a/libcxx/include/new b/libcxx/include/new
index 673e105bc5230..7b7be39537edc 100644
--- a/libcxx/include/new
+++ b/libcxx/include/new
@@ -91,7 +91,6 @@ void operator delete[](void* ptr, void*) noexcept; // const
#else
# include <__config>
# include <__new/align_val_t.h>
-# include <__new/allocate.h>
# include <__new/exceptions.h>
# include <__new/global_new_delete.h>
# include <__new/new_handler.h>
diff --git a/libcxx/src/include/aligned_alloc.h b/libcxx/src/include/aligned_alloc.h
index 2b69a344006a3..07d50eab7151e 100644
--- a/libcxx/src/include/aligned_alloc.h
+++ b/libcxx/src/include/aligned_alloc.h
@@ -23,7 +23,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// Low-level helpers to call the aligned allocation and deallocation functions
// on the target platform. This is used to implement libc++'s own memory
// allocation routines -- if you need to allocate memory inside the library,
-// chances are that you want to use `__libcpp_allocate` instead.
+// chances are that you want to use `allocator::allocate` instead.
//
// Returns the allocated memory, or `nullptr` on failure.
inline _LIBCPP_HIDE_FROM_ABI void* __libcpp_aligned_alloc(std::size_t __alignment, std::size_t __size) {
More information about the libcxx-commits
mailing list