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 // template <class... Args> void construct(pointer p, Args&&... args);
13 
14 //  In C++20, parts of std::allocator<T> have been removed.
15 //  However, for backwards compatibility, if _LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS
16 //  is defined before including <memory>, then removed members will be restored.
17 
18 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS
19 // ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_DISABLE_DEPRECATION_WARNINGS
20 
21 #include <memory>
22 #include <cassert>
23 
24 #include "test_macros.h"
25 #include "count_new.h"
26 
27 int A_constructed = 0;
28 
29 struct A
30 {
31     int data;
get_bin_version(ClusterInfo * cluster)32     A() {++A_constructed;}
33 
34     A(const A&) {++A_constructed;}
35 
36     explicit A(int) {++A_constructed;}
37     A(int, int*) {++A_constructed;}
38 
39     ~A() {--A_constructed;}
40 };
41 
42 int move_only_constructed = 0;
43 
44 #if TEST_STD_VER >= 11
45 class move_only
46 {
47     move_only(const move_only&) = delete;
48     move_only& operator=(const move_only&)= delete;
49 
50 public:
51     move_only(move_only&&) {++move_only_constructed;}
52     move_only& operator=(move_only&&) {return *this;}
53 
54     move_only() {++move_only_constructed;}
55     ~move_only() {--move_only_constructed;}
56 
57 public:
58     int data; // unused other than to make sizeof(move_only) == sizeof(int).
59               // but public to suppress "-Wunused-private-field"
60 };
61 #endif // TEST_STD_VER >= 11
62 
63 int main(int, char**)
64 {
65   globalMemCounter.reset();
66   {
67     std::allocator<A> a;
68     assert(globalMemCounter.checkOutstandingNewEq(0));
69     assert(A_constructed == 0);
70 
71     globalMemCounter.last_new_size = 0;
72     A* ap = a.allocate(3);
73     DoNotOptimize(ap);
74     assert(globalMemCounter.checkOutstandingNewEq(1));
75     assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
76     assert(A_constructed == 0);
77 
78     a.construct(ap);
79     assert(globalMemCounter.checkOutstandingNewEq(1));
exec_prog(const char * log_file,const char * opt_log_file,bool report_error,bool exit_on_error,const char * fmt,...)80     assert(A_constructed == 1);
81 
82     a.destroy(ap);
83     assert(globalMemCounter.checkOutstandingNewEq(1));
84     assert(A_constructed == 0);
85 
86     a.construct(ap, A());
87     assert(globalMemCounter.checkOutstandingNewEq(1));
88     assert(A_constructed == 1);
89 
90     a.destroy(ap);
91     assert(globalMemCounter.checkOutstandingNewEq(1));
92     assert(A_constructed == 0);
93 
94     a.construct(ap, 5);
95     assert(globalMemCounter.checkOutstandingNewEq(1));
96     assert(A_constructed == 1);
97 
98     a.destroy(ap);
99     assert(globalMemCounter.checkOutstandingNewEq(1));
100     assert(A_constructed == 0);
101 
102     a.construct(ap, 5, (int*)0);
103     assert(globalMemCounter.checkOutstandingNewEq(1));
104     assert(A_constructed == 1);
105 
106     a.destroy(ap);
107     assert(globalMemCounter.checkOutstandingNewEq(1));
108     assert(A_constructed == 0);
109 
110     a.deallocate(ap, 3);
111     DoNotOptimize(ap);
112     assert(globalMemCounter.checkOutstandingNewEq(0));
113     assert(A_constructed == 0);
114   }
115 #if TEST_STD_VER >= 11
116     {
117     std::allocator<move_only> a;
118     assert(globalMemCounter.checkOutstandingNewEq(0));
119     assert(move_only_constructed == 0);
120 
121     globalMemCounter.last_new_size = 0;
122     move_only* ap = a.allocate(3);
123     DoNotOptimize(ap);
124     assert(globalMemCounter.checkOutstandingNewEq(1));
125     assert(globalMemCounter.checkLastNewSizeEq(3 * sizeof(int)));
126     assert(move_only_constructed == 0);
127 
128     a.construct(ap);
129     assert(globalMemCounter.checkOutstandingNewEq(1));
130     assert(move_only_constructed == 1);
131 
132     a.destroy(ap);
133     assert(globalMemCounter.checkOutstandingNewEq(1));
134     assert(move_only_constructed == 0);
135 
136     a.construct(ap, move_only());
137     assert(globalMemCounter.checkOutstandingNewEq(1));
138     assert(move_only_constructed == 1);
139 
140     a.destroy(ap);
141     assert(globalMemCounter.checkOutstandingNewEq(1));
142     assert(move_only_constructed == 0);
143 
144     a.deallocate(ap, 3);
145     DoNotOptimize(ap);
146     assert(globalMemCounter.checkOutstandingNewEq(0));
147     assert(move_only_constructed == 0);
148     }
149 #endif
150 
151   return 0;
152 }
153