[libc-commits] [libc] [libc] Split out src/__support/alloc-checker.h (PR #173104)

Roland McGrath via libc-commits libc-commits at lists.llvm.org
Fri Dec 19 13:36:37 PST 2025


https://github.com/frobtech updated https://github.com/llvm/llvm-project/pull/173104

>From 6d2eca94674b8712ae865e13254a5f8fb2135a50 Mon Sep 17 00:00:00 2001
From: Roland McGrath <mcgrathr at google.com>
Date: Fri, 19 Dec 2025 13:28:16 -0800
Subject: [PATCH] [libc] Split out src/__support/alloc-checker.h

This moves the libc-internal AllocChecker API out of
src/__support/CPP/new.h and updates CPP/README.md to state the
intent to keep src/__support/CPP and the LIBC_NAMESPACE::cpp
namespace a "pure" subset of standard C++ API polyfills.
---
 libc/docs/dev/code_style.rst                  |  1 +
 libc/src/__support/CPP/README.md              | 31 ++++++--
 libc/src/__support/CPP/new.h                  | 66 +---------------
 libc/src/__support/File/dir.cpp               |  1 +
 libc/src/__support/File/file.cpp              |  1 +
 libc/src/__support/File/linux/file.cpp        |  3 +-
 libc/src/__support/HashTable/table.h          |  1 +
 libc/src/__support/alloc-checker.h            | 77 +++++++++++++++++++
 libc/src/__support/blockstore.h               |  1 +
 .../posix_spawn_file_actions_addclose.cpp     |  1 +
 .../posix_spawn_file_actions_adddup2.cpp      |  1 +
 .../posix_spawn_file_actions_addopen.cpp      |  1 +
 libc/src/stdio/fopencookie.cpp                |  1 +
 libc/src/string/allocating_string_utils.h     |  1 +
 libc/src/string/strndup.cpp                   |  6 +-
 .../src/pthread/pthread_create_test.cpp       |  1 +
 libc/test/src/__support/File/file_test.cpp    |  4 +-
 libc/test/src/__support/hash_test.cpp         |  1 +
 18 files changed, 123 insertions(+), 76 deletions(-)
 create mode 100644 libc/src/__support/alloc-checker.h

diff --git a/libc/docs/dev/code_style.rst b/libc/docs/dev/code_style.rst
index 5eafff9ef9b3d..f88d82feea367 100644
--- a/libc/docs/dev/code_style.rst
+++ b/libc/docs/dev/code_style.rst
@@ -159,6 +159,7 @@ this:
 .. code-block:: c++
 
    #include "src/__support/CPP/new.h"
+   #include "src/__support/alloc-checker.h"
 
    ...
 
diff --git a/libc/src/__support/CPP/README.md b/libc/src/__support/CPP/README.md
index b470c3f1dc343..70e2939a33653 100644
--- a/libc/src/__support/CPP/README.md
+++ b/libc/src/__support/CPP/README.md
@@ -1,13 +1,28 @@
 This directory contains partial re-implementations of some C++ standard library
 utilities. They are for use with internal LLVM libc code and tests.
 
-More utilities can be added on an as needed basis. There are certain rules to
+More utilities can be added on an as-needed basis. There are certain rules to
 be followed for future changes and additions:
 
-1. Only two kind of headers can be included: Other headers from this directory,
-and free standing C headers.
-2. Free standing C headers are to be included as C headers and not as C++
-headers. That is, use `#include <stddef.h>` and not `#include <cstddef>`.
-3. The utilities should be defined in the namespace `LIBC_NAMESPACE::cpp`. The
-higher level namespace should have a `__` prefix to avoid symbol name pollution
-when the utilities are used in implementation of public functions.
+* Only certain kind of headers can be included:
+   * Other headers from this directory
+   * Free-standing C headers (`<stdint.h>` et al)
+   * A few basic `src/__support/macros` headers used pervasively in all libc code
+
+ * Free-standing C headers are to be included as C headers and not as C++
+   headers. That is, use `#include <stddef.h>` and not `#include <cstddef>`.
+   The [proxies](../../../hdr) can also be used, as in `#include "hdr/stdint_proxy.h"`.
+
+* The utilities should be defined in the namespace `LIBC_NAMESPACE::cpp`. The
+  higher level namespace should have a `__` prefix to avoid symbol name pollution
+  when the utilities are used in implementation of public functions.
+
+* Each "CPP/foo.h" provides an exact subset of the API from standard C++ <foo>,
+  just using `LIBC_NAMESPACE::cpp::foo` names in place of `std::foo` names. The
+  implementations here need not be perfect standard-conforming implementations,
+  but their behavior must match for whatever _is_ supported at compile time.
+  That is, if each were just declared with `using std::foo;` all the libc code
+  should work the same (functionally speaking, excluding namespace entanglements).
+
+* Additional APIs specific to libc internals belong elsewhere in `src/__support`,
+  not in `src/__support/CPP`.
diff --git a/libc/src/__support/CPP/new.h b/libc/src/__support/CPP/new.h
index 67344b09e3833..e529e05d858a4 100644
--- a/libc/src/__support/CPP/new.h
+++ b/libc/src/__support/CPP/new.h
@@ -1,4 +1,4 @@
-//===-- Libc specific custom operator new and delete ------------*- C++ -*-===//
+//===-- Libc-internal alternative to <new> ------------*- C++ -*-===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -9,13 +9,10 @@
 #ifndef LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H
 #define LLVM_LIBC_SRC___SUPPORT_CPP_NEW_H
 
-#include "hdr/func/aligned_alloc.h"
 #include "hdr/func/free.h"
-#include "hdr/func/malloc.h"
 #include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/__support/macros/properties/compiler.h"
-#include "src/__support/macros/properties/os.h"
 
 #include <stddef.h> // For size_t
 
@@ -29,78 +26,23 @@ enum class align_val_t : size_t {};
 } // namespace std
 
 namespace LIBC_NAMESPACE_DECL {
-
 namespace cpp {
+
 template <class T> [[nodiscard]] constexpr T *launder(T *p) {
   static_assert(__has_builtin(__builtin_launder),
                 "cpp::launder requires __builtin_launder");
   return __builtin_launder(p);
 }
-} // namespace cpp
-
-class AllocChecker {
-  bool success = false;
-
-  LIBC_INLINE AllocChecker &operator=(bool status) {
-    success = status;
-    return *this;
-  }
-
-public:
-  LIBC_INLINE AllocChecker() = default;
-
-  LIBC_INLINE operator bool() const { return success; }
-
-  LIBC_INLINE static void *alloc(size_t s, AllocChecker &ac) {
-    void *mem = ::malloc(s);
-    ac = (mem != nullptr);
-    return mem;
-  }
-
-  LIBC_INLINE static void *aligned_alloc(size_t s, std::align_val_t align,
-                                         AllocChecker &ac) {
-#ifdef LIBC_TARGET_OS_IS_WINDOWS
-    // std::aligned_alloc is not available on Windows because std::free on
-    // Windows cannot deallocate any over-aligned memory. Microsoft provides an
-    // alternative for std::aligned_alloc named _aligned_malloc, but it must be
-    // paired with _aligned_free instead of std::free.
-    void *mem = ::_aligned_malloc(static_cast<size_t>(align), s);
-#else
-    void *mem = ::aligned_alloc(static_cast<size_t>(align), s);
-#endif
-    ac = (mem != nullptr);
-    return mem;
-  }
-};
 
+} // namespace cpp
 } // namespace LIBC_NAMESPACE_DECL
 
-LIBC_INLINE void *operator new(size_t size,
-                               LIBC_NAMESPACE::AllocChecker &ac) noexcept {
-  return LIBC_NAMESPACE::AllocChecker::alloc(size, ac);
-}
-
-LIBC_INLINE void *operator new(size_t size, std::align_val_t align,
-                               LIBC_NAMESPACE::AllocChecker &ac) noexcept {
-  return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac);
-}
-
-LIBC_INLINE void *operator new[](size_t size,
-                                 LIBC_NAMESPACE::AllocChecker &ac) noexcept {
-  return LIBC_NAMESPACE::AllocChecker::alloc(size, ac);
-}
-
-LIBC_INLINE void *operator new[](size_t size, std::align_val_t align,
-                                 LIBC_NAMESPACE::AllocChecker &ac) noexcept {
-  return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac);
-}
-
 LIBC_INLINE void *operator new(size_t, void *p) { return p; }
 
 LIBC_INLINE void *operator new[](size_t, void *p) { return p; }
 
 // The ideal situation would be to define the various flavors of operator delete
-// inlinelike we do with operator new above. However, since we need operator
+// inline like we do with operator new above. However, since we need operator
 // delete prototypes to match those specified by the C++ standard, we cannot
 // define them inline as the C++ standard does not allow inline definitions of
 // replacement operator delete implementations. Note also that we assign a
diff --git a/libc/src/__support/File/dir.cpp b/libc/src/__support/File/dir.cpp
index aea8862c15f7f..eb33656808414 100644
--- a/libc/src/__support/File/dir.cpp
+++ b/libc/src/__support/File/dir.cpp
@@ -10,6 +10,7 @@
 
 #include "src/__support/CPP/mutex.h" // lock_guard
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/error_or.h"
 #include "src/__support/libc_errno.h" // For error macros
 #include "src/__support/macros/config.h"
diff --git a/libc/src/__support/File/file.cpp b/libc/src/__support/File/file.cpp
index 15ec1a23e2b8d..ccc7acf9387f5 100644
--- a/libc/src/__support/File/file.cpp
+++ b/libc/src/__support/File/file.cpp
@@ -13,6 +13,7 @@
 #include "hdr/types/off_t.h"
 #include "src/__support/CPP/new.h"
 #include "src/__support/CPP/span.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/libc_errno.h" // For error macros
 #include "src/__support/macros/config.h"
 #include "src/string/memory_utils/inline_memcpy.h"
diff --git a/libc/src/__support/File/linux/file.cpp b/libc/src/__support/File/linux/file.cpp
index 4594dadf1ccdf..28f819db83d49 100644
--- a/libc/src/__support/File/linux/file.cpp
+++ b/libc/src/__support/File/linux/file.cpp
@@ -15,7 +15,8 @@
 #include "src/__support/File/linux/lseekImpl.h"
 #include "src/__support/OSUtil/fcntl.h"
 #include "src/__support/OSUtil/syscall.h" // For internal syscall function.
-#include "src/__support/libc_errno.h"     // For error macros
+#include "src/__support/alloc-checker.h"
+#include "src/__support/libc_errno.h" // For error macros
 #include "src/__support/macros/config.h"
 
 #include "hdr/fcntl_macros.h" // For mode_t and other flags to the open syscall
diff --git a/libc/src/__support/HashTable/table.h b/libc/src/__support/HashTable/table.h
index 966ee0fcaf0ae..f42eead2efcf2 100644
--- a/libc/src/__support/HashTable/table.h
+++ b/libc/src/__support/HashTable/table.h
@@ -14,6 +14,7 @@
 #include "src/__support/CPP/bit.h" // bit_ceil
 #include "src/__support/CPP/new.h"
 #include "src/__support/HashTable/bitmask.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/hash.h"
 #include "src/__support/macros/attributes.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/__support/alloc-checker.h b/libc/src/__support/alloc-checker.h
new file mode 100644
index 0000000000000..ecef094453cc8
--- /dev/null
+++ b/libc/src/__support/alloc-checker.h
@@ -0,0 +1,77 @@
+//===-- Libc specific custom operator new and delete ------------*- C++ -*-===//
+//
+// 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 LLVM_LIBC_SRC___SUPPORT_ALLOC_CHECKER_H
+#define LLVM_LIBC_SRC___SUPPORT_ALLOC_CHECKER_H
+
+#include "hdr/func/aligned_alloc.h"
+#include "hdr/func/malloc.h"
+#include "src/__support/common.h"
+#include "src/__support/macros/config.h"
+#include "src/__support/macros/properties/os.h"
+
+namespace LIBC_NAMESPACE_DECL {
+
+class AllocChecker {
+  bool success = false;
+
+  LIBC_INLINE AllocChecker &operator=(bool status) {
+    success = status;
+    return *this;
+  }
+
+public:
+  LIBC_INLINE AllocChecker() = default;
+
+  LIBC_INLINE operator bool() const { return success; }
+
+  LIBC_INLINE static void *alloc(size_t s, AllocChecker &ac) {
+    void *mem = ::malloc(s);
+    ac = (mem != nullptr);
+    return mem;
+  }
+
+  LIBC_INLINE static void *aligned_alloc(size_t s, std::align_val_t align,
+                                         AllocChecker &ac) {
+#ifdef LIBC_TARGET_OS_IS_WINDOWS
+    // std::aligned_alloc is not available on Windows because std::free on
+    // Windows cannot deallocate any over-aligned memory. Microsoft provides an
+    // alternative for std::aligned_alloc named _aligned_malloc, but it must be
+    // paired with _aligned_free instead of std::free.
+    void *mem = ::_aligned_malloc(static_cast<size_t>(align), s);
+#else
+    void *mem = ::aligned_alloc(static_cast<size_t>(align), s);
+#endif
+    ac = (mem != nullptr);
+    return mem;
+  }
+};
+
+} // namespace LIBC_NAMESPACE_DECL
+
+LIBC_INLINE void *operator new(size_t size,
+                               LIBC_NAMESPACE::AllocChecker &ac) noexcept {
+  return LIBC_NAMESPACE::AllocChecker::alloc(size, ac);
+}
+
+LIBC_INLINE void *operator new(size_t size, std::align_val_t align,
+                               LIBC_NAMESPACE::AllocChecker &ac) noexcept {
+  return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac);
+}
+
+LIBC_INLINE void *operator new[](size_t size,
+                                 LIBC_NAMESPACE::AllocChecker &ac) noexcept {
+  return LIBC_NAMESPACE::AllocChecker::alloc(size, ac);
+}
+
+LIBC_INLINE void *operator new[](size_t size, std::align_val_t align,
+                                 LIBC_NAMESPACE::AllocChecker &ac) noexcept {
+  return LIBC_NAMESPACE::AllocChecker::aligned_alloc(size, align, ac);
+}
+
+#endif // LLVM_LIBC_SRC___SUPPORT_ALLOC_CHECKER_H
diff --git a/libc/src/__support/blockstore.h b/libc/src/__support/blockstore.h
index 61ee0ee80a2bf..af84262222c60 100644
--- a/libc/src/__support/blockstore.h
+++ b/libc/src/__support/blockstore.h
@@ -13,6 +13,7 @@
 #include "src/__support/CPP/array.h"
 #include "src/__support/CPP/new.h"
 #include "src/__support/CPP/type_traits.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/libc_assert.h"
 #include "src/__support/macros/config.h"
 
diff --git a/libc/src/spawn/posix_spawn_file_actions_addclose.cpp b/libc/src/spawn/posix_spawn_file_actions_addclose.cpp
index 9a575bd591632..04213a82ec726 100644
--- a/libc/src/spawn/posix_spawn_file_actions_addclose.cpp
+++ b/libc/src/spawn/posix_spawn_file_actions_addclose.cpp
@@ -10,6 +10,7 @@
 
 #include "file_actions.h"
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp b/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp
index 1ad45ed942bb9..569fc20e73d60 100644
--- a/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp
+++ b/libc/src/spawn/posix_spawn_file_actions_adddup2.cpp
@@ -10,6 +10,7 @@
 
 #include "file_actions.h"
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/spawn/posix_spawn_file_actions_addopen.cpp b/libc/src/spawn/posix_spawn_file_actions_addopen.cpp
index 9977fc2d0a218..23a8907596932 100644
--- a/libc/src/spawn/posix_spawn_file_actions_addopen.cpp
+++ b/libc/src/spawn/posix_spawn_file_actions_addopen.cpp
@@ -10,6 +10,7 @@
 
 #include "file_actions.h"
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/common.h"
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/stdio/fopencookie.cpp b/libc/src/stdio/fopencookie.cpp
index da8a132a4db6e..dafc7823e5fd9 100644
--- a/libc/src/stdio/fopencookie.cpp
+++ b/libc/src/stdio/fopencookie.cpp
@@ -13,6 +13,7 @@
 #include "hdr/types/off_t.h"
 #include "src/__support/CPP/new.h"
 #include "src/__support/File/file.h"
+#include "src/__support/alloc-checker.h"
 
 #include "src/__support/libc_errno.h"
 #include "src/__support/macros/config.h"
diff --git a/libc/src/string/allocating_string_utils.h b/libc/src/string/allocating_string_utils.h
index e2f61f77b0c75..dfaa794298889 100644
--- a/libc/src/string/allocating_string_utils.h
+++ b/libc/src/string/allocating_string_utils.h
@@ -11,6 +11,7 @@
 
 #include "src/__support/CPP/new.h"
 #include "src/__support/CPP/optional.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/macros/config.h" // LIBC_NAMESPACE_DECL
 #include "src/string/memory_utils/inline_memcpy.h"
 #include "src/string/string_utils.h"
diff --git a/libc/src/string/strndup.cpp b/libc/src/string/strndup.cpp
index b19d7c060baa1..40f473a0167fe 100644
--- a/libc/src/string/strndup.cpp
+++ b/libc/src/string/strndup.cpp
@@ -7,13 +7,13 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/string/strndup.h"
+#include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
+#include "src/__support/common.h"
 #include "src/__support/macros/config.h"
 #include "src/string/memory_utils/inline_memcpy.h"
 #include "src/string/string_utils.h"
 
-#include "src/__support/CPP/new.h"
-#include "src/__support/common.h"
-
 #include <stddef.h>
 
 namespace LIBC_NAMESPACE_DECL {
diff --git a/libc/test/integration/src/pthread/pthread_create_test.cpp b/libc/test/integration/src/pthread/pthread_create_test.cpp
index d436cc3270d9c..6fae8e747a204 100644
--- a/libc/test/integration/src/pthread/pthread_create_test.cpp
+++ b/libc/test/integration/src/pthread/pthread_create_test.cpp
@@ -27,6 +27,7 @@
 #include "src/__support/CPP/array.h"
 #include "src/__support/CPP/atomic.h"
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/threads/thread.h"
 
 #include "test/IntegrationTest/test.h"
diff --git a/libc/test/src/__support/File/file_test.cpp b/libc/test/src/__support/File/file_test.cpp
index 17dad4d5ac917..ed2200b879048 100644
--- a/libc/test/src/__support/File/file_test.cpp
+++ b/libc/test/src/__support/File/file_test.cpp
@@ -6,14 +6,14 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "hdr/types/size_t.h"
 #include "src/__support/CPP/new.h"
 #include "src/__support/File/file.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/error_or.h"
 #include "test/UnitTest/MemoryMatcher.h"
 #include "test/UnitTest/Test.h"
 
-#include "hdr/types/size_t.h"
-
 using ModeFlags = LIBC_NAMESPACE::File::ModeFlags;
 using MemoryView = LIBC_NAMESPACE::testing::MemoryView;
 using LIBC_NAMESPACE::ErrorOr;
diff --git a/libc/test/src/__support/hash_test.cpp b/libc/test/src/__support/hash_test.cpp
index 94c884cc7fb17..417a43a58b340 100644
--- a/libc/test/src/__support/hash_test.cpp
+++ b/libc/test/src/__support/hash_test.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "src/__support/CPP/new.h"
+#include "src/__support/alloc-checker.h"
 #include "src/__support/hash.h"
 #include "src/stdlib/rand.h"
 #include "src/stdlib/srand.h"



More information about the libc-commits mailing list