1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// REQUIRES: c++experimental
11// UNSUPPORTED: c++98, c++03
12
13// <experimental/memory_resource>
14
15// template <class T> class polymorphic_allocator
16
17// T* polymorphic_allocator<T>::allocate(size_t n)
18
19#include <experimental/memory_resource>
20#include <limits>
21#include <memory>
22#include <exception>
23#include <type_traits>
24#include <cassert>
25
26#include "test_macros.h"
27#include "test_memory_resource.hpp"
28
29namespace ex = std::experimental::pmr;
30
31template <size_t S, size_t Align>
32void testForSizeAndAlign() {
33    using T = typename std::aligned_storage<S, Align>::type;
34    TestResource R;
35    ex::polymorphic_allocator<T> a(&R);
36
37    for (int N = 1; N <= 5; ++N) {
38        auto ret = a.allocate(N);
39        assert(R.checkAlloc(ret, N * sizeof(T), alignof(T)));
40
41        a.deallocate(ret, N);
42        R.reset();
43    }
44}
45
46#ifndef TEST_HAS_NO_EXCEPTIONS
47template <size_t S>
48void testAllocForSizeThrows() {
49    using T = typename std::aligned_storage<S>::type;
50    using Alloc = ex::polymorphic_allocator<T>;
51    using Traits = std::allocator_traits<Alloc>;
52    NullResource R;
53    Alloc a(&R);
54
55    // Test that allocating exactly the max size does not throw.
56    size_t maxSize = Traits::max_size(a);
57    try {
58        a.allocate(maxSize);
59    } catch (...) {
60        assert(false);
61    }
62
63    size_t sizeTypeMax = std::numeric_limits<std::size_t>::max();
64    if (maxSize != sizeTypeMax)
65    {
66        // Test that allocating size_t(~0) throws bad alloc.
67        try {
68            a.allocate(sizeTypeMax);
69            assert(false);
70        } catch (std::exception const&) {
71        }
72
73        // Test that allocating even one more than the max size does throw.
74        size_t overSize = maxSize + 1;
75        try {
76            a.allocate(overSize);
77            assert(false);
78        } catch (std::exception const&) {
79        }
80    }
81}
82#endif // TEST_HAS_NO_EXCEPTIONS
83
84int main()
85{
86    {
87        ex::polymorphic_allocator<int> a;
88        static_assert(std::is_same<decltype(a.allocate(0)), int*>::value, "");
89        static_assert(!noexcept(a.allocate(0)), "");
90    }
91    {
92        constexpr std::size_t MA = alignof(std::max_align_t);
93        testForSizeAndAlign<1, 1>();
94        testForSizeAndAlign<1, 2>();
95        testForSizeAndAlign<1, MA>();
96        testForSizeAndAlign<2, 2>();
97        testForSizeAndAlign<73, alignof(void*)>();
98        testForSizeAndAlign<73, MA>();
99        testForSizeAndAlign<13, MA>();
100    }
101#ifndef TEST_HAS_NO_EXCEPTIONS
102    {
103        testAllocForSizeThrows<1>();
104        testAllocForSizeThrows<2>();
105        testAllocForSizeThrows<4>();
106        testAllocForSizeThrows<8>();
107        testAllocForSizeThrows<16>();
108        testAllocForSizeThrows<73>();
109        testAllocForSizeThrows<13>();
110    }
111#endif
112}
113