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 ` and not `#include `. -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 (`` 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 ` and not `#include `. + 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++ , + 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 ------------*- 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 // For size_t @@ -29,78 +26,23 @@ enum class align_val_t : size_t {}; } // namespace std namespace LIBC_NAMESPACE_DECL { - namespace cpp { + template [[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(align), s); -#else - void *mem = ::aligned_alloc(static_cast(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(align), s); +#else + void *mem = ::aligned_alloc(static_cast(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 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"