diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index 32579272858a8..a9c6e2e499953 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -542,6 +542,8 @@ set(files __memory/ranges_uninitialized_algorithms.h __memory/raw_storage_iterator.h __memory/shared_ptr.h + __memory/start_lifetime_as.h + __memory/start_lifetime_as_array.h __memory/swap_allocator.h __memory/temp_value.h __memory/temporary_buffer.h diff --git a/libcxx/include/__memory/start_lifetime_as.h b/libcxx/include/__memory/start_lifetime_as.h new file mode 100644 index 0000000000000..2e3292657472c --- /dev/null +++ b/libcxx/include/__memory/start_lifetime_as.h @@ -0,0 +1,50 @@ +// -*- 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 _LIBCPP___MEMORY_START_LIFETIME_AS_H +#define _LIBCPP___MEMORY_START_LIFETIME_AS_H + +#include <__config> +#include <__type_traits/is_array.h> +#include <__type_traits/remove_all_extents.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct _LIBCPP_TEMPLATE_VIS __start_lifetime_as_impl { + _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR _Tp* __call(void* __p) _NOEXCEPT { return static_cast<_Tp*>(__p); } +}; + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* start_lifetime_as(void* __p) _NOEXCEPT { + return __start_lifetime_as_impl<_Tp>::__call(__p); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as(const void* __p) _NOEXCEPT { + return std::start_lifetime_as<_Tp>(const_cast(__p)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp* start_lifetime_as(volatile void* __p) _NOEXCEPT { + return std::start_lifetime_as<_Tp>(const_cast(__p)); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp* start_lifetime_as(const volatile void* __p) _NOEXCEPT { + return std::start_lifetime_as<_Tp>(const_cast(__p)); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_START_LIFETIME_AS_H diff --git a/libcxx/include/__memory/start_lifetime_as_array.h b/libcxx/include/__memory/start_lifetime_as_array.h new file mode 100644 index 0000000000000..17272c318c2ab --- /dev/null +++ b/libcxx/include/__memory/start_lifetime_as_array.h @@ -0,0 +1,48 @@ +// -*- 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 _LIBCPP___MEMORY_START_LIFETIME_AS_ARRAY_H +#define _LIBCPP___MEMORY_START_LIFETIME_AS_ARRAY_H + +#include <__config> +#include <__memory/start_lifetime_as.h> +#include + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* +start_lifetime_as_array(void* __p, [[__maybe_unused__]] size_t __n) _NOEXCEPT { + return static_cast<_Tp*>(__p); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as_array(const void* __p, size_t __n) _NOEXCEPT { + return std::start_lifetime_as_array<_Tp>(const_cast(__p), __n); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp* +start_lifetime_as_array(volatile void* __p, size_t __n) _NOEXCEPT { + return std::start_lifetime_as_array<_Tp>(const_cast(__p), __n); +} + +template +_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp* +start_lifetime_as_array(const volatile void* __p, size_t __n) _NOEXCEPT { + return std::start_lifetime_as_array<_Tp>(const_cast(__p), __n); +} + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___MEMORY_START_LIFETIME_AS_ARRAY_H diff --git a/libcxx/include/memory b/libcxx/include/memory index b940a32c3ebe6..3162bbb2b906a 100644 --- a/libcxx/include/memory +++ b/libcxx/include/memory @@ -946,6 +946,8 @@ template #include <__memory/pointer_traits.h> #include <__memory/raw_storage_iterator.h> #include <__memory/shared_ptr.h> +#include <__memory/start_lifetime_as.h> +#include <__memory/start_lifetime_as_array.h> #include <__memory/temporary_buffer.h> #include <__memory/uninitialized_algorithms.h> #include <__memory/unique_ptr.h> diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap index f193b5d95f49f..d340d6b33ddae 100644 --- a/libcxx/include/module.modulemap +++ b/libcxx/include/module.modulemap @@ -1543,6 +1543,8 @@ module std_private_memory_shared_ptr [system] { header "__memory/shared_ptr.h" export std_private_memory_uninitialized_algorithms } +module std_private_memory_start_lifetime_as_array [system] { header "__memory/start_lifetime_as_array.h" } +module std_private_memory_start_lifetime_as [system] { header "__memory/start_lifetime_as.h" } module std_private_memory_swap_allocator [system] { header "__memory/swap_allocator.h" } module std_private_memory_temp_value [system] { header "__memory/temp_value.h" } module std_private_memory_temporary_buffer [system] { diff --git a/libcxx/test/std/utilities/memory/default.allocator/start_lifetime_as.pass.cpp b/libcxx/test/std/utilities/memory/default.allocator/start_lifetime_as.pass.cpp new file mode 100644 index 0000000000000..e483516e77b46 --- /dev/null +++ b/libcxx/test/std/utilities/memory/default.allocator/start_lifetime_as.pass.cpp @@ -0,0 +1,127 @@ +//===----------------------------------------------------------------------===// +// +// 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: c++03, c++11, c++14, c++17 + +// + +// template +// T* start_lifetime_as(void* p) noexcept; +// +// template +// const T* start_lifetime_as(const void* p) noexcept; +// +// template +// volatile T* start_lifetime_as(volatile void* p) noexcept; +// +// template +// const volatile T* start_lifetime_as(const volatile void* p) noexcept; +// +// template +// T* start_lifetime_as_array(void* p, size_t n) noexcept; +// +// template +// const T* start_lifetime_as_array(const void* p, size_t n) noexcept; +// +// template +// volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept; +// +// template +// const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept; + +#include +#include +#include + +#include "test_macros.h" + +struct S { + int x; + double y; +}; + +template +void test_start_lifetime_as() { + alignas(T) char buffer[sizeof(T)]; + + { + T* ptr = std::start_lifetime_as(buffer); + ASSERT_SAME_TYPE(decltype(ptr), T*); + ASSERT_NOEXCEPT(std::start_lifetime_as(buffer)); + assert(ptr == reinterpret_cast(buffer)); + } + + { + const T* cptr = std::start_lifetime_as(static_cast(buffer)); + ASSERT_SAME_TYPE(decltype(cptr), const T*); + ASSERT_NOEXCEPT(std::start_lifetime_as(static_cast(buffer))); + assert(cptr == reinterpret_cast(buffer)); + } + + { + volatile T* vptr = std::start_lifetime_as(static_cast(buffer)); + ASSERT_SAME_TYPE(decltype(vptr), volatile T*); + ASSERT_NOEXCEPT(std::start_lifetime_as(static_cast(buffer))); + assert(vptr == reinterpret_cast(buffer)); + } + + { + const volatile T* cvptr = std::start_lifetime_as(static_cast(buffer)); + ASSERT_SAME_TYPE(decltype(cvptr), const volatile T*); + ASSERT_NOEXCEPT(std::start_lifetime_as(static_cast(buffer))); + assert(cvptr == reinterpret_cast(buffer)); + } +} + +template +void test_start_lifetime_as_array() { + constexpr size_t count = 5; + alignas(T) char buffer[sizeof(T) * count]; + + { + T* ptr = std::start_lifetime_as_array(buffer, count); + ASSERT_SAME_TYPE(decltype(ptr), T*); + ASSERT_NOEXCEPT(std::start_lifetime_as_array(buffer, count)); + assert(ptr == reinterpret_cast(buffer)); + } + + { + const T* cptr = std::start_lifetime_as_array(static_cast(buffer), count); + ASSERT_SAME_TYPE(decltype(cptr), const T*); + ASSERT_NOEXCEPT(std::start_lifetime_as_array(static_cast(buffer), count)); + assert(cptr == reinterpret_cast(buffer)); + } + + { + volatile T* vptr = std::start_lifetime_as_array(static_cast(buffer), count); + ASSERT_SAME_TYPE(decltype(vptr), volatile T*); + ASSERT_NOEXCEPT(std::start_lifetime_as_array(static_cast(buffer), count)); + assert(vptr == reinterpret_cast(buffer)); + } + + { + const volatile T* cvptr = std::start_lifetime_as_array(static_cast(buffer), count); + ASSERT_SAME_TYPE(decltype(cvptr), const volatile T*); + ASSERT_NOEXCEPT(std::start_lifetime_as_array(static_cast(buffer), count)); + assert(cvptr == reinterpret_cast(buffer)); + } +} + +int main(int, char**) { + test_start_lifetime_as(); + test_start_lifetime_as(); + test_start_lifetime_as(); + test_start_lifetime_as(); + + test_start_lifetime_as_array(); + test_start_lifetime_as_array(); + test_start_lifetime_as_array(); + test_start_lifetime_as_array(); + + return 0; +} \ No newline at end of file