[libcxx-commits] [libcxx] [libc++] P2590R2: Explicit lifetime management (PR #107206)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 4 03:15:00 PDT 2024


https://github.com/phyBrackets updated https://github.com/llvm/llvm-project/pull/107206

>From f612feec0b62b4ed2c2f239776c4c8d43ee97364 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Wed, 4 Sep 2024 15:02:30 +0530
Subject: [PATCH 1/3] [libc++] P2590R2: Explicit lifetime management

---
 libcxx/include/CMakeLists.txt                 |   2 +
 libcxx/include/__memory/start_lifetime_as.h   |  50 +++++++
 .../__memory/start_lifetime_as_array.h        |  47 +++++++
 libcxx/include/memory                         |   2 +
 .../start_lifetime_as.pass.cpp                | 127 ++++++++++++++++++
 5 files changed, 228 insertions(+)
 create mode 100644 libcxx/include/__memory/start_lifetime_as.h
 create mode 100644 libcxx/include/__memory/start_lifetime_as_array.h
 create mode 100644 libcxx/test/std/utilities/memory/default.allocator/start_lifetime_as.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 32579272858a8e..629742cbaee764 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_array.h
+  __memory/start_lifetime_as.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 00000000000000..f661a709c06c42
--- /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 <class _Tp>
+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 <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* start_lifetime_as(void* __p) _NOEXCEPT {
+  return __start_lifetime_as_impl<_Tp>::__call(__p);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as(const void* __p) _NOEXCEPT {
+  return start_lifetime_as<_Tp>(const_cast<void*>(__p));
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp* start_lifetime_as(volatile void* __p) _NOEXCEPT {
+  return start_lifetime_as<_Tp>(const_cast<void*>(__p));
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp* start_lifetime_as(const volatile void* __p) _NOEXCEPT {
+  return start_lifetime_as<_Tp>(const_cast<void*>(__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 00000000000000..5b227870f7ed6c
--- /dev/null
+++ b/libcxx/include/__memory/start_lifetime_as_array.h
@@ -0,0 +1,47 @@
+// -*- 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 <cstddef>
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+template <class _Tp>
+_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 <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as_array(const void* __p, size_t __n) _NOEXCEPT {
+  return start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp*
+start_lifetime_as_array(volatile void* __p, size_t __n) _NOEXCEPT {
+  return start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
+}
+
+template <class _Tp>
+_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp*
+start_lifetime_as_array(const volatile void* __p, size_t __n) _NOEXCEPT {
+  return start_lifetime_as_array<_Tp>(const_cast<void*>(__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 b940a32c3ebe6c..3162bbb2b906a9 100644
--- a/libcxx/include/memory
+++ b/libcxx/include/memory
@@ -946,6 +946,8 @@ template<class Pointer = void, class Smart, class... Args>
 #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/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 00000000000000..e483516e77b46d
--- /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
+
+// <memory>
+
+// template <class T>
+// T* start_lifetime_as(void* p) noexcept;
+//
+// template <class T>
+// const T* start_lifetime_as(const void* p) noexcept;
+//
+// template <class T>
+// volatile T* start_lifetime_as(volatile void* p) noexcept;
+//
+// template <class T>
+// const volatile T* start_lifetime_as(const volatile void* p) noexcept;
+//
+// template <class T>
+// T* start_lifetime_as_array(void* p, size_t n) noexcept;
+//
+// template <class T>
+// const T* start_lifetime_as_array(const void* p, size_t n) noexcept;
+//
+// template <class T>
+// volatile T* start_lifetime_as_array(volatile void* p, size_t n) noexcept;
+//
+// template <class T>
+// const volatile T* start_lifetime_as_array(const volatile void* p, size_t n) noexcept;
+
+#include <memory>
+#include <type_traits>
+#include <cassert>
+
+#include "test_macros.h"
+
+struct S {
+  int x;
+  double y;
+};
+
+template <class T>
+void test_start_lifetime_as() {
+  alignas(T) char buffer[sizeof(T)];
+
+  {
+    T* ptr = std::start_lifetime_as<T>(buffer);
+    ASSERT_SAME_TYPE(decltype(ptr), T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as<T>(buffer));
+    assert(ptr == reinterpret_cast<T*>(buffer));
+  }
+
+  {
+    const T* cptr = std::start_lifetime_as<T>(static_cast<const void*>(buffer));
+    ASSERT_SAME_TYPE(decltype(cptr), const T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as<T>(static_cast<const void*>(buffer)));
+    assert(cptr == reinterpret_cast<const T*>(buffer));
+  }
+
+  {
+    volatile T* vptr = std::start_lifetime_as<T>(static_cast<volatile void*>(buffer));
+    ASSERT_SAME_TYPE(decltype(vptr), volatile T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as<T>(static_cast<volatile void*>(buffer)));
+    assert(vptr == reinterpret_cast<volatile T*>(buffer));
+  }
+
+  {
+    const volatile T* cvptr = std::start_lifetime_as<T>(static_cast<const volatile void*>(buffer));
+    ASSERT_SAME_TYPE(decltype(cvptr), const volatile T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as<T>(static_cast<const volatile void*>(buffer)));
+    assert(cvptr == reinterpret_cast<const volatile T*>(buffer));
+  }
+}
+
+template <class T>
+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<T>(buffer, count);
+    ASSERT_SAME_TYPE(decltype(ptr), T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as_array<T>(buffer, count));
+    assert(ptr == reinterpret_cast<T*>(buffer));
+  }
+
+  {
+    const T* cptr = std::start_lifetime_as_array<T>(static_cast<const void*>(buffer), count);
+    ASSERT_SAME_TYPE(decltype(cptr), const T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as_array<T>(static_cast<const void*>(buffer), count));
+    assert(cptr == reinterpret_cast<const T*>(buffer));
+  }
+
+  {
+    volatile T* vptr = std::start_lifetime_as_array<T>(static_cast<volatile void*>(buffer), count);
+    ASSERT_SAME_TYPE(decltype(vptr), volatile T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as_array<T>(static_cast<volatile void*>(buffer), count));
+    assert(vptr == reinterpret_cast<volatile T*>(buffer));
+  }
+
+  {
+    const volatile T* cvptr = std::start_lifetime_as_array<T>(static_cast<const volatile void*>(buffer), count);
+    ASSERT_SAME_TYPE(decltype(cvptr), const volatile T*);
+    ASSERT_NOEXCEPT(std::start_lifetime_as_array<T>(static_cast<const volatile void*>(buffer), count));
+    assert(cvptr == reinterpret_cast<const volatile T*>(buffer));
+  }
+}
+
+int main(int, char**) {
+  test_start_lifetime_as<char>();
+  test_start_lifetime_as<int>();
+  test_start_lifetime_as<double>();
+  test_start_lifetime_as<S>();
+
+  test_start_lifetime_as_array<char>();
+  test_start_lifetime_as_array<int>();
+  test_start_lifetime_as_array<double>();
+  test_start_lifetime_as_array<S>();
+
+  return 0;
+}
\ No newline at end of file

>From 73eeb1324eea8b9e5725bc15b41419c1d2874be9 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Wed, 4 Sep 2024 15:02:30 +0530
Subject: [PATCH 2/3] [libc++] P2590R2: Explicit lifetime management

---
 libcxx/include/__memory/start_lifetime_as.h       | 6 +++---
 libcxx/include/__memory/start_lifetime_as_array.h | 9 +++++----
 libcxx/include/module.modulemap                   | 2 ++
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/libcxx/include/__memory/start_lifetime_as.h b/libcxx/include/__memory/start_lifetime_as.h
index f661a709c06c42..2e3292657472ca 100644
--- a/libcxx/include/__memory/start_lifetime_as.h
+++ b/libcxx/include/__memory/start_lifetime_as.h
@@ -32,17 +32,17 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* start_lifetime_as(void* __p) _NOEXC
 
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as(const void* __p) _NOEXCEPT {
-  return start_lifetime_as<_Tp>(const_cast<void*>(__p));
+  return std::start_lifetime_as<_Tp>(const_cast<void*>(__p));
 }
 
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp* start_lifetime_as(volatile void* __p) _NOEXCEPT {
-  return start_lifetime_as<_Tp>(const_cast<void*>(__p));
+  return std::start_lifetime_as<_Tp>(const_cast<void*>(__p));
 }
 
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp* start_lifetime_as(const volatile void* __p) _NOEXCEPT {
-  return start_lifetime_as<_Tp>(const_cast<void*>(__p));
+  return std::start_lifetime_as<_Tp>(const_cast<void*>(__p));
 }
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__memory/start_lifetime_as_array.h b/libcxx/include/__memory/start_lifetime_as_array.h
index 5b227870f7ed6c..17272c318c2ab1 100644
--- a/libcxx/include/__memory/start_lifetime_as_array.h
+++ b/libcxx/include/__memory/start_lifetime_as_array.h
@@ -21,25 +21,26 @@
 _LIBCPP_BEGIN_NAMESPACE_STD
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR _Tp* start_lifetime_as_array(void* __p, [[maybe_unused]] size_t __n) _NOEXCEPT {
+_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 <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const _Tp* start_lifetime_as_array(const void* __p, size_t __n) _NOEXCEPT {
-  return start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
+  return std::start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
 }
 
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR volatile _Tp*
 start_lifetime_as_array(volatile void* __p, size_t __n) _NOEXCEPT {
-  return start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
+  return std::start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
 }
 
 template <class _Tp>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR const volatile _Tp*
 start_lifetime_as_array(const volatile void* __p, size_t __n) _NOEXCEPT {
-  return start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
+  return std::start_lifetime_as_array<_Tp>(const_cast<void*>(__p), __n);
 }
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index f193b5d95f49f5..d340d6b33ddae4 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] {

>From 8ba8c649f9871bf4cd632b6bbcdb3f7681932c57 Mon Sep 17 00:00:00 2001
From: Shivam Kunwar <shivam.kunwar at kdab.com>
Date: Wed, 4 Sep 2024 15:02:30 +0530
Subject: [PATCH 3/3] [libc++] P2590R2: Explicit lifetime management

---
 libcxx/include/CMakeLists.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 629742cbaee764..a9c6e2e4999537 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -542,8 +542,8 @@ set(files
   __memory/ranges_uninitialized_algorithms.h
   __memory/raw_storage_iterator.h
   __memory/shared_ptr.h
-  __memory/start_lifetime_as_array.h
   __memory/start_lifetime_as.h
+  __memory/start_lifetime_as_array.h
   __memory/swap_allocator.h
   __memory/temp_value.h
   __memory/temporary_buffer.h



More information about the libcxx-commits mailing list