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

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Sep 14 12:12:11 PDT 2023


Author: Louis Dionne
Date: 2023-09-14T15:12:06-04:00
New Revision: 85f27d126dbe696070a0c79c476070a67e40aa29

URL: https://github.com/llvm/llvm-project/commit/85f27d126dbe696070a0c79c476070a67e40aa29
DIFF: https://github.com/llvm/llvm-project/commit/85f27d126dbe696070a0c79c476070a67e40aa29.diff

LOG: [libc++] Make sure LWG2070 is implemented as a DR (#65998)

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.

Added: 
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.lwg2070.pass.cpp

Modified: 
    libcxx/include/__memory/shared_ptr.h
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.pass.cpp

Removed: 
    libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared_construct.pass.cpp


################################################################################
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