1ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//===----------------------------------------------------------------------===//
2ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//
3ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//                     The LLVM Compiler Infrastructure
4ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//
5ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open
6ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// Source Licenses. See LICENSE.TXT for details.
7ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//
8ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//===----------------------------------------------------------------------===//
9ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
10ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// UNSUPPORTED: c++98, c++03
11ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
12ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// <scoped_allocator>
13ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
14ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// template <class OtherAlloc, class ...InnerAlloc>
15ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//   class scoped_allocator_adaptor
16ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
17ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// template <class U1, class U2, class ...Args1, class ...Args2>
18ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier// void scoped_allocator_adaptor::construct(pair<U1, U2>*,
19ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier//     piecewise_construct_t, tuple<Args1...>, tuple<Args2...>)
20ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
21ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <scoped_allocator>
22ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <type_traits>
23ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <utility>
24ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <tuple>
25ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <cassert>
26ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include <cstdlib>
27ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include "uses_alloc_types.hpp"
28ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier#include "controlled_allocators.hpp"
29ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
30ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
31ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiseliervoid test_no_inner_alloc()
32ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier{
33ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    using VoidAlloc = CountingAllocator<void>;
34ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    AllocController P;
35ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    {
36ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using T = UsesAllocatorV1<VoidAlloc, 1>;
37ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using U = UsesAllocatorV2<VoidAlloc, 1>;
38ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Pair = std::pair<T, U>;
39ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        int x = 42;
40ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        const int y = 101;
41ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Alloc = CountingAllocator<Pair>;
42ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SA = std::scoped_allocator_adaptor<Alloc>;
43ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
44ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
453169d4a451aef7929cc5bc399d1a089e127868a4Stephan T. Lavavej        assert(ptr != nullptr);
46ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Alloc CA(P);
47ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        SA A(CA);
48ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.construct(ptr, std::piecewise_construct,
49ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(x),
50ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(std::move(y)));
51ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA));
52ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA));
53ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert((P.checkConstruct<std::piecewise_construct_t const&,
54ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<std::allocator_arg_t, SA&, int&>&&,
55ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<int const&&, SA&>&&
56ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier              >(CA, ptr)));
57ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.destroy(ptr);
58ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        std::free(ptr);
59ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
60ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    }
61ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    P.reset();
62ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    {
63ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using T = UsesAllocatorV3<VoidAlloc, 1>;
64ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using U = NotUsesAllocator<VoidAlloc, 1>;
65ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Pair = std::pair<T, U>;
66ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        int x = 42;
67ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        const int y = 101;
68ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Alloc = CountingAllocator<Pair>;
69ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SA = std::scoped_allocator_adaptor<Alloc>;
70ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, "");
71ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
723169d4a451aef7929cc5bc399d1a089e127868a4Stephan T. Lavavej        assert(ptr != nullptr);
73ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Alloc CA(P);
74ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        SA A(CA);
75ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.construct(ptr, std::piecewise_construct,
76ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(std::move(x)),
77ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(y));
78ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA));
79ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int const&>(ptr->second, UA_None));
80ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert((P.checkConstruct<std::piecewise_construct_t const&,
81ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<std::allocator_arg_t, SA&, int&&>&&,
82ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<int const&>&&
83ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                   >(CA, ptr)));
84ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.destroy(ptr);
85ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        std::free(ptr);
86ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    }
87ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier}
88ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
89ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiseliervoid test_with_inner_alloc()
90ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier{
91ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    using VoidAlloc2 = CountingAllocator<void, 2>;
92ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier
93ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    AllocController POuter;
94ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    AllocController PInner;
95ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    {
96ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using T = UsesAllocatorV1<VoidAlloc2, 1>;
97ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using U = UsesAllocatorV2<VoidAlloc2, 1>;
98ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Pair = std::pair<T, U>;
99ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        int x = 42;
100ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        int y = 101;
101ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Outer = CountingAllocator<Pair, 1>;
102ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Inner = CountingAllocator<Pair, 2>;
103ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SA = std::scoped_allocator_adaptor<Outer, Inner>;
104ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SAInner = std::scoped_allocator_adaptor<Inner>;
105ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(!std::uses_allocator<T, Outer>::value, "");
106ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(std::uses_allocator<T, Inner>::value, "");
107ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
1083169d4a451aef7929cc5bc399d1a089e127868a4Stephan T. Lavavej        assert(ptr != nullptr);
109ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Outer O(POuter);
110ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Inner I(PInner);
111ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        SA A(O, I);
112ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.construct(ptr, std::piecewise_construct,
113ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(x),
114ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(std::move(y)));
115ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I));
116ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int &&>(ptr->second, UA_AllocLast));
117ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert((POuter.checkConstruct<std::piecewise_construct_t const&,
118ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<std::allocator_arg_t, SAInner&, int&>&&,
119ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<int &&, SAInner&>&&
120ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier              >(O, ptr)));
121ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.destroy(ptr);
122ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        std::free(ptr);
123ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    }
124ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    PInner.reset();
125ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    POuter.reset();
126ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    {
127ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using T = UsesAllocatorV3<VoidAlloc2, 1>;
128ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using U = NotUsesAllocator<VoidAlloc2, 1>;
129ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Pair = std::pair<T, U>;
130ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        int x = 42;
131ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        const int y = 101;
132ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Outer = CountingAllocator<Pair, 1>;
133ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using Inner = CountingAllocator<Pair, 2>;
134ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SA = std::scoped_allocator_adaptor<Outer, Inner>;
135ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        using SAInner = std::scoped_allocator_adaptor<Inner>;
136ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(!std::uses_allocator<T, Outer>::value, "");
137ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        static_assert(std::uses_allocator<T, Inner>::value, "");
138ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Pair * ptr = (Pair*)std::malloc(sizeof(Pair));
1393169d4a451aef7929cc5bc399d1a089e127868a4Stephan T. Lavavej        assert(ptr != nullptr);
140ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Outer O(POuter);
141ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        Inner I(PInner);
142ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        SA A(O, I);
143ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.construct(ptr, std::piecewise_construct,
144ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(std::move(x)),
145ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                    std::forward_as_tuple(std::move(y)));
146ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I));
147ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert(checkConstruct<int const&&>(ptr->second, UA_None));
148ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        assert((POuter.checkConstruct<std::piecewise_construct_t const&,
149ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<std::allocator_arg_t, SAInner&, int&&>&&,
150ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier                                 std::tuple<int const&&>&&
151ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier              >(O, ptr)));
152ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        A.destroy(ptr);
153ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier        std::free(ptr);
154ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    }
155ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier}
156ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselierint main() {
157ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    test_no_inner_alloc();
158ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier    test_with_inner_alloc();
159ff62475dcdf8fd5bebdce7fa61c81038db4f2fa7Eric Fiselier}
160