xref: /llvm-project/libcxx/test/std/utilities/memory/default.allocator/allocator.members/allocate.pass.cpp (revision fb855eb941b6d740cc6560297d0b4d3201dcaf9f)
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 // <memory>
10 
11 // allocator:
12 // constexpr T* allocate(size_t n);
13 
14 #include <memory>
15 #include <cassert>
16 #include <cstddef>       // for std::max_align_t
17 
18 #include "test_macros.h"
19 #include "count_new.h"
20 
21 
22 #ifdef TEST_HAS_NO_ALIGNED_ALLOCATION
23 static const bool UsingAlignedNew = false;
24 #else
25 static const bool UsingAlignedNew = true;
26 #endif
27 
28 #ifdef __STDCPP_DEFAULT_NEW_ALIGNMENT__
29 static const std::size_t MaxAligned = __STDCPP_DEFAULT_NEW_ALIGNMENT__;
30 #else
31 static const std::size_t MaxAligned = std::alignment_of<std::max_align_t>::value;
32 #endif
33 
34 static const std::size_t OverAligned = MaxAligned * 2;
35 
36 
37 template <std::size_t Align>
TEST_ALIGNAS(Align)38 struct TEST_ALIGNAS(Align) AlignedType {
39   char data;
40   static int constructed;
41   AlignedType() { ++constructed; }
42   AlignedType(AlignedType const&) { ++constructed; }
43   ~AlignedType() { --constructed; }
44 };
45 template <std::size_t Align>
46 int AlignedType<Align>::constructed = 0;
47 
48 
49 template <std::size_t Align>
test_aligned()50 void test_aligned() {
51   typedef AlignedType<Align> T;
52   T::constructed = 0;
53   globalMemCounter.reset();
54   std::allocator<T> a;
55   const bool IsOverAlignedType = Align > MaxAligned;
56   const bool ExpectAligned = IsOverAlignedType && UsingAlignedNew;
57   {
58     assert(globalMemCounter.checkOutstandingNewEq(0));
59     assert(T::constructed == 0);
60     globalMemCounter.last_new_size = 0;
61     globalMemCounter.last_new_align = 0;
62     T* ap = a.allocate(3);
63     DoNotOptimize(ap);
64     assert(globalMemCounter.checkOutstandingNewEq(1));
65     assert(globalMemCounter.checkNewCalledEq(1));
66     assert(globalMemCounter.checkAlignedNewCalledEq(ExpectAligned));
67     assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(T)));
68     assert(globalMemCounter.checkLastNewAlignEq(ExpectAligned ? Align : 0));
69     assert(T::constructed == 0);
70     globalMemCounter.last_delete_align = 0;
71     a.deallocate(ap, 3);
72     assert(globalMemCounter.checkOutstandingNewEq(0));
73     assert(globalMemCounter.checkDeleteCalledEq(1));
74     assert(globalMemCounter.checkAlignedDeleteCalledEq(ExpectAligned));
75     assert(globalMemCounter.checkLastDeleteAlignEq(ExpectAligned ? Align : 0));
76     assert(T::constructed == 0);
77   }
78 }
79 
80 #if TEST_STD_VER > 17
81 template <std::size_t Align>
test_aligned_constexpr()82 constexpr bool test_aligned_constexpr() {
83     typedef AlignedType<Align> T;
84     std::allocator<T> a;
85     T* ap = a.allocate(3);
86     a.deallocate(ap, 3);
87 
88     return true;
89 }
90 #endif
91 
main(int,char **)92 int main(int, char**) {
93     test_aligned<1>();
94     test_aligned<2>();
95     test_aligned<4>();
96     test_aligned<8>();
97     test_aligned<16>();
98     test_aligned<MaxAligned>();
99     test_aligned<OverAligned>();
100     test_aligned<OverAligned * 2>();
101 
102 #if TEST_STD_VER > 17
103     static_assert(test_aligned_constexpr<1>());
104     static_assert(test_aligned_constexpr<2>());
105     static_assert(test_aligned_constexpr<4>());
106     static_assert(test_aligned_constexpr<8>());
107     static_assert(test_aligned_constexpr<16>());
108     static_assert(test_aligned_constexpr<MaxAligned>());
109     static_assert(test_aligned_constexpr<OverAligned>());
110     static_assert(test_aligned_constexpr<OverAligned * 2>());
111 #endif
112 
113   return 0;
114 }
115