[libcxx-commits] [libcxx] a00290e - [libc++] Fix allocate_shared when used with an explicitly convertible allocator

Louis Dionne via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 15 08:50:16 PST 2020


Author: Louis Dionne
Date: 2020-12-15T11:50:06-05:00
New Revision: a00290ed10a6b4e9f6e9be44ceec367562f270c6

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

LOG: [libc++] Fix allocate_shared when used with an explicitly convertible allocator

When the allocator is only explicitly convertible from other specializations
of itself, the new version of std::allocate_shared would not work because
it would try to do an implicit conversion. This patch fixes the problem
and adds a test so that we don't fall into the same trap in the future.

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

Modified: 
    libcxx/include/__memory/utilities.h

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__memory/utilities.h b/libcxx/include/__memory/utilities.h
index ccbfbe78966c..aac3d11cab57 100644
--- a/libcxx/include/__memory/utilities.h
+++ b/libcxx/include/__memory/utilities.h
@@ -48,8 +48,9 @@ struct __allocation_guard {
     using _Pointer = typename allocator_traits<_Alloc>::pointer;
     using _Size = typename allocator_traits<_Alloc>::size_type;
 
+    template<class _AllocT> // we perform the allocator conversion inside the constructor
     _LIBCPP_HIDE_FROM_ABI
-    explicit __allocation_guard(_Alloc __alloc, _Size __n)
+    explicit __allocation_guard(_AllocT __alloc, _Size __n)
         : __alloc_(_VSTD::move(__alloc))
         , __n_(__n)
         , __ptr_(allocator_traits<_Alloc>::allocate(__alloc_, __n_)) // initialization order is important

diff  --git a/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.explicit_conversion.pass.cpp b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.explicit_conversion.pass.cpp
new file mode 100644
index 000000000000..446daa1ec9f2
--- /dev/null
+++ b/libcxx/test/std/utilities/memory/util.smartptr/util.smartptr.shared/util.smartptr.shared.create/allocate_shared.explicit_conversion.pass.cpp
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// Make sure that std::allocate_shared works with an allocator type that is
+// only explicitly convertible from another specialization of itself.
+
+#include <cassert>
+#include <cstddef>
+#include <memory>
+
+template <class T>
+struct ExplicitAllocator {
+    ExplicitAllocator() = default;
+    template <class U>
+    explicit ExplicitAllocator(ExplicitAllocator<U>) { }
+
+    using value_type = T;
+    T* allocate(std::size_t n) { return std::allocator<T>().allocate(n); }
+    void deallocate(T* ptr, std::size_t n) { return std::allocator<T>().deallocate(ptr, n); }
+};
+
+int main(int, char**) {
+    std::shared_ptr<int> ptr = std::allocate_shared<int>(ExplicitAllocator<int>(), 0);
+    (void)ptr;
+
+    return 0;
+}


        


More information about the libcxx-commits mailing list