[libcxx-commits] [libcxx] [libc++] Make sure LWG2070 is implemented as a DR (PR #65998)

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Wed Sep 13 12:57:43 PDT 2023


https://github.com/ldionne updated https://github.com/llvm/llvm-project/pull/65998:

>From f0bbb92110a269bcb4594c31a612691be8c9a72a Mon Sep 17 00:00:00 2001
From: Louis Dionne <ldionne.2 at gmail.com>
Date: Mon, 11 Sep 2023 14:56:33 -0400
Subject: [PATCH] [libc++] Make sure LWG2070 is implemented as a DR

When we implemented C++20's P0674R1, we didn't enable the part of P0674R1
that was resolving LWG2070 as a DR. This patch fixes that and makes sure
that we consistently go through the allocator when constructing and
destroying the underlying object in std::allocate_shared.

Fixes #54365.
---
 libcxx/include/__memory/shared_ptr.h          | 50 ++++++++++---------
 ...s.cpp => allocate_shared.lwg2070.pass.cpp} | 23 +++++----
 .../allocate_shared.pass.cpp                  | 23 ---------
 3 files changed, 39 insertions(+), 57 deletions(-)
 rename libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/{allocate_shared_construct.pass.cpp => allocate_shared.lwg2070.pass.cpp} (90%)

diff --git a/libcxx/include/__memory/shared_ptr.h b/libcxx/include/__memory/shared_ptr.h
index 845882ad31134d2..6be2f22184590ae 100644
--- a/libcxx/include/__memory/shared_ptr.h
+++ b/libcxx/include/__memory/shared_ptr.h
@@ -285,23 +285,23 @@ template <class _Tp, class _Alloc>
 struct __shared_ptr_emplace
     : __shared_weak_count
 {
-    template<class ..._Args>
+    template <class... _Args, class _Allocator = _Alloc, __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
+    _LIBCPP_HIDE_FROM_ABI
+    explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...)
+        : __storage_(_VSTD::move(__a))
+    {
+        static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
+        ::new ((void*)__get_elem()) _Tp;
+    }
+
+    template <class... _Args, class _Allocator = _Alloc, __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
     _LIBCPP_HIDE_FROM_ABI
     explicit __shared_ptr_emplace(_Alloc __a, _Args&& ...__args)
         : __storage_(_VSTD::move(__a))
     {
-#if _LIBCPP_STD_VER >= 20
-        if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
-            static_assert(sizeof...(_Args) == 0, "No argument should be provided to the control block when using _for_overwrite");
-            ::new ((void*)__get_elem()) _Tp;
-        } else {
-            using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
-            _TpAlloc __tmp(*__get_alloc());
-            allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...);
-        }
-#else
-        ::new ((void*)__get_elem()) _Tp(_VSTD::forward<_Args>(__args)...);
-#endif
+        using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
+        _TpAlloc __tmp(*__get_alloc());
+        allocator_traits<_TpAlloc>::construct(__tmp, __get_elem(), _VSTD::forward<_Args>(__args)...);
     }
 
     _LIBCPP_HIDE_FROM_ABI
@@ -311,18 +311,20 @@ struct __shared_ptr_emplace
     _Tp* __get_elem() _NOEXCEPT { return __storage_.__get_elem(); }
 
 private:
-    _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override {
-#if _LIBCPP_STD_VER >= 20
-        if constexpr (is_same_v<typename _Alloc::value_type, __for_overwrite_tag>) {
-            __get_elem()->~_Tp();
-        } else {
-            using _TpAlloc = typename __allocator_traits_rebind<_Alloc, _Tp>::type;
-            _TpAlloc __tmp(*__get_alloc());
-            allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
-        }
-#else
+    template <class _Allocator = _Alloc, __enable_if_t<is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
+    _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
         __get_elem()->~_Tp();
-#endif
+    }
+
+    template <class _Allocator = _Alloc, __enable_if_t<!is_same<typename _Allocator::value_type, __for_overwrite_tag>::value, int> = 0>
+    _LIBCPP_HIDE_FROM_ABI void __on_zero_shared_impl() _NOEXCEPT {
+        using _TpAlloc = typename __allocator_traits_rebind<_Allocator, _Tp>::type;
+        _TpAlloc __tmp(*__get_alloc());
+        allocator_traits<_TpAlloc>::destroy(__tmp, __get_elem());
+    }
+
+    _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared() _NOEXCEPT override {
+        __on_zero_shared_impl();
     }
 
     _LIBCPP_HIDE_FROM_ABI_VIRTUAL void __on_zero_shared_weak() _NOEXCEPT override {
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_construct.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.lwg2070.pass.cpp
similarity index 90%
rename from libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_construct.pass.cpp
rename to libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.lwg2070.pass.cpp
index 4281cc1aa9e0db8..bf86327848d2ee9 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_construct.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.lwg2070.pass.cpp
@@ -6,8 +6,6 @@
 //
 //===----------------------------------------------------------------------===//
 
-// UNSUPPORTED: c++03, c++11, c++14, c++17
-
 // <memory>
 
 // shared_ptr
@@ -15,17 +13,20 @@
 // template<class T, class A, class... Args>
 // shared_ptr<T> allocate_shared(const A& a, Args&&... args);
 
-// This test checks that allocator_traits::construct is used in allocate_shared
-// as requested in C++20 (via P0674R1).
-
-#include "test_macros.h"
+// This test checks that allocator_traits::construct and allocator_traits::destroy
+// are used in allocate_shared as requested for the resolution of LWG2070. Note
+// that LWG2070 was resolved by P0674R1 (which is a C++20 paper), but we implement
+// LWG issue resolutions as DRs per our policy.
 
 #include <cassert>
+#include <cstddef>
 #include <cstdint>
 #include <memory>
 #include <new>
 #include <utility>
 
+#include "test_macros.h"
+
 static bool construct_called = false;
 static bool destroy_called = false;
 static unsigned allocator_id = 0;
@@ -118,10 +119,6 @@ struct Foo {
   Foo(Foo a, Foo b) : val(a.val + b.val) {}
 };
 
-struct Bar {
-  std::max_align_t y;
-};
-
 void test_aligned(void* p, std::size_t align) {
   assert(reinterpret_cast<std::uintptr_t>(p) % align == 0);
 }
@@ -170,10 +167,16 @@ int main(int, char**) {
     assert(p->id == 42);
   }
 
+#if TEST_STD_VER >= 11
   {
+    struct Bar {
+      std::max_align_t y;
+    };
+
     std::shared_ptr<Bar> p;
     test_aligned(p.get(), alignof(Bar));
   }
+#endif
 
   return 0;
 }
diff --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
index ac7a9913b0e9182..341a442c90a1674 100644
--- a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp
@@ -90,22 +90,6 @@ struct Three
 
 int Three::count = 0;
 
-template<class T>
-struct AllocNoConstruct : std::allocator<T>
-{
-    AllocNoConstruct() = default;
-
-    template <class T1>
-    AllocNoConstruct(AllocNoConstruct<T1>) {}
-
-    template <class T1>
-    struct rebind {
-        typedef AllocNoConstruct<T1> other;
-    };
-
-    void construct(void*) { assert(false); }
-};
-
 template <class Alloc>
 void test()
 {
@@ -182,12 +166,5 @@ int main(int, char**)
         assert(p2 != nullptr);
     }
 
-    // Test that we don't call construct before C++20.
-#if TEST_STD_VER < 20
-    {
-    (void)std::allocate_shared<int>(AllocNoConstruct<int>());
-    }
-#endif // TEST_STD_VER < 20
-
   return 0;
 }



More information about the libcxx-commits mailing list