1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 // UNSUPPORTED: c++03, c++11, c++14
10 // TODO: Change to XFAIL once https://github.com/llvm/llvm-project/issues/40340 is fixed
11 // UNSUPPORTED: availability-pmr-missing
12
13 // test_memory_resource requires RTTI for dynamic_cast
14 // UNSUPPORTED: no-rtti
15
16 // <memory_resource>
17
18 // template <class T> class polymorphic_allocator
19
20 // template <class U1, class U2, class ...Args1, class ...Args2>
21 // void polymorphic_allocator<T>::construct(pair<U1, U2>*, piecewise_construct_t
22 // tuple<Args1...>, tuple<Args2...>)
23
24 #include <memory_resource>
25 #include <type_traits>
26 #include <utility>
27 #include <tuple>
28 #include <cassert>
29 #include <cstdlib>
30
31 #include "test_macros.h"
32 #include "test_std_memory_resource.h"
33 #include "uses_alloc_types.h"
34 #include "controlled_allocators.h"
35 #include "test_allocator.h"
36
37 template <class T, class U, class... TTuple, class... UTuple>
doTest(UsesAllocatorType TExpect,UsesAllocatorType UExpect,std::tuple<TTuple...> ttuple,std::tuple<UTuple...> utuple)38 bool doTest(
39 UsesAllocatorType TExpect, UsesAllocatorType UExpect, std::tuple<TTuple...> ttuple, std::tuple<UTuple...> utuple) {
40 using P = std::pair<T, U>;
41 TestResource R;
42 std::pmr::memory_resource* M = &R;
43 std::pmr::polymorphic_allocator<P> A(M);
44 P* ptr = A.allocate(1);
45
46 // UNDER TEST //
47 A.construct(ptr, std::piecewise_construct, std::move(ttuple), std::move(utuple));
48 // ------- //
49 bool tres = checkConstruct<TTuple&&...>(ptr->first, TExpect, M);
50 bool ures = checkConstruct<UTuple&&...>(ptr->second, UExpect, M);
51
52 A.destroy(ptr);
53 A.deallocate(ptr, 1);
54 return tres && ures;
55 }
56
57 template <class Alloc, class... TTypes, class... UTypes>
test_pmr_uses_allocator(std::tuple<TTypes...> ttuple,std::tuple<UTypes...> utuple)58 void test_pmr_uses_allocator(std::tuple<TTypes...> ttuple, std::tuple<UTypes...> utuple) {
59 {
60 using T = NotUsesAllocator<Alloc, sizeof...(TTypes)>;
61 using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
62 assert((doTest<T, U>(UA_None, UA_None, std::move(ttuple), std::move(utuple))));
63 }
64 {
65 using T = UsesAllocatorV1<Alloc, sizeof...(TTypes)>;
66 using U = UsesAllocatorV2<Alloc, sizeof...(UTypes)>;
67 assert((doTest<T, U>(UA_AllocArg, UA_AllocLast, std::move(ttuple), std::move(utuple))));
68 }
69 {
70 using T = UsesAllocatorV2<Alloc, sizeof...(TTypes)>;
71 using U = UsesAllocatorV3<Alloc, sizeof...(UTypes)>;
72 assert((doTest<T, U>(UA_AllocLast, UA_AllocArg, std::move(ttuple), std::move(utuple))));
73 }
74 {
75 using T = UsesAllocatorV3<Alloc, sizeof...(TTypes)>;
76 using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
77 assert((doTest<T, U>(UA_AllocArg, UA_None, std::move(ttuple), std::move(utuple))));
78 }
79 }
80
81 template <class Alloc, class... TTypes, class... UTypes>
test_pmr_not_uses_allocator(std::tuple<TTypes...> ttuple,std::tuple<UTypes...> utuple)82 void test_pmr_not_uses_allocator(std::tuple<TTypes...> ttuple, std::tuple<UTypes...> utuple) {
83 {
84 using T = NotUsesAllocator<Alloc, sizeof...(TTypes)>;
85 using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
86 assert((doTest<T, U>(UA_None, UA_None, std::move(ttuple), std::move(utuple))));
87 }
88 {
89 using T = UsesAllocatorV1<Alloc, sizeof...(TTypes)>;
90 using U = UsesAllocatorV2<Alloc, sizeof...(UTypes)>;
91 assert((doTest<T, U>(UA_None, UA_None, std::move(ttuple), std::move(utuple))));
92 }
93 {
94 using T = UsesAllocatorV2<Alloc, sizeof...(TTypes)>;
95 using U = UsesAllocatorV3<Alloc, sizeof...(UTypes)>;
96 assert((doTest<T, U>(UA_None, UA_None, std::move(ttuple), std::move(utuple))));
97 }
98 {
99 using T = UsesAllocatorV3<Alloc, sizeof...(TTypes)>;
100 using U = NotUsesAllocator<Alloc, sizeof...(UTypes)>;
101 assert((doTest<T, U>(UA_None, UA_None, std::move(ttuple), std::move(utuple))));
102 }
103 }
104
main(int,char **)105 int main(int, char**) {
106 using PMR = std::pmr::memory_resource*;
107 using PMA = std::pmr::polymorphic_allocator<char>;
108 {
109 std::tuple<> t1;
110 test_pmr_not_uses_allocator<PMR>(t1, t1);
111 test_pmr_uses_allocator<PMA>(t1, t1);
112 }
113 {
114 std::tuple<int> t1(42);
115 std::tuple<> t2;
116 test_pmr_not_uses_allocator<PMR>(t1, t2);
117 test_pmr_not_uses_allocator<PMR>(t2, t1);
118 test_pmr_uses_allocator<PMA>(t1, t2);
119 test_pmr_uses_allocator<PMA>(t2, t1);
120 }
121 {
122 std::tuple<int> t1(42);
123 int x = 55;
124 double dx = 42.42;
125 std::tuple<int&, double&&> t2(x, std::move(dx));
126 test_pmr_not_uses_allocator<PMR>(t1, std::move(t2));
127 test_pmr_not_uses_allocator<PMR>(std::move(t2), t1);
128 test_pmr_uses_allocator<PMA>(t1, std::move(t2));
129 test_pmr_uses_allocator<PMA>(std::move(t2), t1);
130 }
131 {
132 void* xptr = nullptr;
133 long y = 4242;
134 std::tuple<int, long const&, void*&> t1(42, y, xptr);
135 int x = 55;
136 double dx = 42.42;
137 const char* s = "hello World";
138 std::tuple<int&, double&&, const char*> t2(x, std::move(dx), s);
139 test_pmr_not_uses_allocator<PMR>(t1, std::move(t2));
140 test_pmr_not_uses_allocator<PMR>(std::move(t2), t1);
141 test_pmr_uses_allocator<PMA>(t1, std::move(t2));
142 test_pmr_uses_allocator<PMA>(std::move(t2), t1);
143 }
144
145 return 0;
146 }
147