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; +} _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits