From: Eric Fiselier Date: Wed, 14 Dec 2016 21:29:29 +0000 (+0000) Subject: [libcxx] Fix PR24075, PR23841 - Add scoped_allocator_adaptor::construct(pair*, ...) overloads. Summary: For more information see: * https://llvm.org/bugs/show_bug.cgi?id=23841 * https://llvm.org/bugs/show_bug.cgi?id=24075 I hope you have as much fun reviewing as I did writing these insane tests! Reviewers: mclow.lists, AlisdairM, EricWF Subscribers: AlisdairM, Potatoswatter, cfe-commits Differential Revision: https://reviews.llvm.org/D27612 llvm-svn: 289710 --- diff --git a/libcxx/include/__functional_base b/libcxx/include/__functional_base index 82b4146..6e2cfef 100644 --- a/libcxx/include/__functional_base +++ b/libcxx/include/__functional_base @@ -637,7 +637,8 @@ constexpr size_t uses_allocator_v = uses_allocator<_Tp, _Alloc>::value; template struct __uses_alloc_ctor_imp { - static const bool __ua = uses_allocator<_Tp, _Alloc>::value; + typedef typename __uncvref<_Alloc>::type _RawAlloc; + static const bool __ua = uses_allocator<_Tp, _RawAlloc>::value; static const bool __ic = is_constructible<_Tp, allocator_arg_t, _Alloc, _Args...>::value; static const int value = __ua ? 2 - __ic : 0; @@ -655,6 +656,7 @@ void __user_alloc_construct_impl (integral_constant, _Tp *__storage, con new (__storage) _Tp (_VSTD::forward<_Args>(__args)...); } +// FIXME: This should have a version which takes a non-const alloc. template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) @@ -662,6 +664,7 @@ void __user_alloc_construct_impl (integral_constant, _Tp *__storage, con new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...); } +// FIXME: This should have a version which takes a non-const alloc. template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct_impl (integral_constant, _Tp *__storage, const _Allocator &__a, _Args &&... __args ) @@ -669,6 +672,7 @@ void __user_alloc_construct_impl (integral_constant, _Tp *__storage, con new (__storage) _Tp (_VSTD::forward<_Args>(__args)..., __a); } +// FIXME: Theis should have a version which takes a non-const alloc. template inline _LIBCPP_INLINE_VISIBILITY void __user_alloc_construct (_Tp *__storage, const _Allocator &__a, _Args &&... __args) diff --git a/libcxx/include/scoped_allocator b/libcxx/include/scoped_allocator index 04e7386..605f70b 100644 --- a/libcxx/include/scoped_allocator +++ b/libcxx/include/scoped_allocator @@ -498,8 +498,58 @@ public: template _LIBCPP_INLINE_VISIBILITY void construct(_Tp* __p, _Args&& ...__args) - {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(), + {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type&, _Args...>(), __p, _VSTD::forward<_Args>(__args)...);} + + template + void construct(pair<_T1, _T2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + typedef __outermost _OM; + allocator_traits::construct( + _OM()(outer_allocator()), __p, piecewise_construct + , __transform_tuple( + typename __uses_alloc_ctor< + _T1, inner_allocator_type&, _Args1... + >::type() + , _VSTD::move(__x) + , typename __make_tuple_indices::type{} + ) + , __transform_tuple( + typename __uses_alloc_ctor< + _T2, inner_allocator_type&, _Args2... + >::type() + , _VSTD::move(__y) + , typename __make_tuple_indices::type{} + ) + ); + } + + template + void construct(pair<_T1, _T2>* __p) + { construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); } + + template + void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x)), + _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__y))); + } + + template + void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(__x.first), + _VSTD::forward_as_tuple(__x.second)); + } + + template + void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x.first)), + _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__x.second))); + } + template _LIBCPP_INLINE_VISIBILITY void destroy(_Tp* __p) @@ -515,6 +565,7 @@ public: private: + template ::value @@ -545,9 +596,7 @@ private: allocator_traits::construct ( _OM()(outer_allocator()), - __p, - allocator_arg, - inner_allocator(), + __p, allocator_arg, inner_allocator(), _VSTD::forward<_Args>(__args)... ); } @@ -566,6 +615,36 @@ private: ); } + template + _LIBCPP_INLINE_VISIBILITY + tuple<_Args&&...> + __transform_tuple(integral_constant, tuple<_Args...>&& __t, + __tuple_indices<_Idx...>) + { + return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...); + } + + template + _LIBCPP_INLINE_VISIBILITY + tuple + __transform_tuple(integral_constant, tuple<_Args...> && __t, + __tuple_indices<_Idx...>) + { + using _Tup = tuple; + return _Tup(allocator_arg, inner_allocator(), + _VSTD::get<_Idx>(_VSTD::move(__t))...); + } + + template + _LIBCPP_INLINE_VISIBILITY + tuple<_Args&&..., inner_allocator_type&> + __transform_tuple(integral_constant, tuple<_Args...> && __t, + __tuple_indices<_Idx...>) + { + using _Tup = tuple<_Args&&..., inner_allocator_type&>; + return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., inner_allocator()); + } + template friend class __scoped_allocator_storage; }; diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp new file mode 100644 index 0000000..4e73d80 --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(pair*) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator; + AllocController P; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((P.checkConstruct&&, + std::tuple<>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((POuter.checkConstruct&&, + std::tuple<>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp new file mode 100644 index 0000000..9effb6e --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(pair*, pairconst&) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator; + AllocController P; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_None)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_None)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp new file mode 100644 index 0000000..4d371f2 --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp @@ -0,0 +1,156 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(pair*, +// piecewise_construct_t, tuple, tuple) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator; + AllocController P; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(y)); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_None)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_None)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp new file mode 100644 index 0000000..1d0fb51 --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(pair*, pair&&) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator; + AllocController P; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_None)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + using PairIn = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_None)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp new file mode 100644 index 0000000..840f4ec --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(pair*, Tp&&, Up&&) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator; + AllocController P; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + static_assert(std::uses_allocator >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::move(x), y); + assert(checkConstruct(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct(ptr->second, UA_None)); + assert((P.checkConstruct&&, + std::tuple&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using U = UsesAllocatorV2; + using Pair = std::pair; + int x = 42; + int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3; + using U = NotUsesAllocator; + using Pair = std::pair; + int x = 42; + const int y = 101; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::move(x), std::move(y)); + assert(checkConstruct(ptr->first, UA_AllocArg, I)); + assert(checkConstruct(ptr->second, UA_None)); + assert((POuter.checkConstruct&&, + std::tuple&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} diff --git a/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp new file mode 100644 index 0000000..867cc74 --- /dev/null +++ b/libcxx/test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_type.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// + +// template +// class scoped_allocator_adaptor + +// template +// void scoped_allocator_adaptor::construct(T*, Args&&...) + +#include +#include +#include +#include +#include +#include +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + +// — If uses_allocator_v is false and +// is_constructible_v is true, calls +// OUTERMOST_ALLOC_TRAITS(*this)::construct( +// OUTERMOST (*this), p, std::forward(args)...). +void test_bullet_one() { + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = NotUsesAllocator; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(!std::uses_allocator::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct(*ptr, UA_None))); + assert((POuter.checkConstruct(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + + +// Otherwise, if uses_allocator_v is true and +// is_constructible_v is +// true, calls OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, +// allocator_arg, inner_allocator(), std::forward(args)...). +void test_bullet_two() { + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct(*ptr, UA_AllocArg, I))); + assert((POuter.checkConstruct(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + +// Otherwise, if uses_allocator_v is true and +// is_constructible_v is true, calls +// OUTERMOST_ALLOC_TRAITS(*this)::construct(OUTERMOST (*this), p, +// std::forward(args)..., inner_allocator()). +void test_bullet_three() { + using VoidAlloc1 = CountingAllocator; + using VoidAlloc2 = CountingAllocator; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV2; + using Outer = CountingAllocator; + using Inner = CountingAllocator; + using SA = std::scoped_allocator_adaptor; + using SAInner = std::scoped_allocator_adaptor; + static_assert(!std::uses_allocator::value, ""); + static_assert(std::uses_allocator::value, ""); + T* ptr = (T*)::operator new(sizeof(T)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + int x = 42; + int const& cx = x; + A.construct(ptr, x, cx, std::move(x)); + assert((checkConstruct(*ptr, UA_AllocLast, I))); + assert((POuter.checkConstruct< + int&, int const&, int&&, + SA::inner_allocator_type&>(O, ptr))); + A.destroy(ptr); + ::operator delete((void*)ptr); + } + PInner.reset(); + POuter.reset(); +} + +int main() { + test_bullet_one(); + test_bullet_two(); + test_bullet_three(); +}