[VPlan] Perform DT expensive input DT verification earlier (NFC).
[llvm-project.git] / libcxx / test / std / utilities / memory / util.smartptr / util.smartptr.shared / util.smartptr.shared.create / allocate_shared.lwg2070.pass.cpp
blob222a552e58378aa8971cd8bc9e8025e348c500c4
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 //===----------------------------------------------------------------------===//
9 // <memory>
11 // shared_ptr
13 // template<class T, class A, class... Args>
14 // shared_ptr<T> allocate_shared(const A& a, Args&&... args);
16 // This test checks that allocator_traits::construct and allocator_traits::destroy
17 // are used in allocate_shared as requested for the resolution of LWG2070. Note
18 // that LWG2070 was resolved by P0674R1 (which is a C++20 paper), but we implement
19 // LWG issue resolutions as DRs per our policy.
21 #include <cassert>
22 #include <cstddef>
23 #include <cstdint>
24 #include <memory>
25 #include <new>
26 #include <utility>
28 #include "test_macros.h"
30 static bool construct_called = false;
31 static bool destroy_called = false;
32 static unsigned allocator_id = 0;
34 template <class T>
35 struct MyAllocator {
36 public:
37 typedef T value_type;
38 typedef T* pointer;
40 unsigned id = 0;
42 MyAllocator() = default;
43 MyAllocator(int i) : id(i) {}
45 template <class U>
46 MyAllocator(MyAllocator<U> const& other) : id(other.id) {}
48 pointer allocate(std::ptrdiff_t n) {
49 return pointer(static_cast<T*>(::operator new(n * sizeof(T))));
52 void deallocate(pointer p, std::ptrdiff_t) { return ::operator delete(p); }
54 template <typename ...Args>
55 void construct(T* p, Args&& ...args) {
56 construct_called = true;
57 destroy_called = false;
58 allocator_id = id;
59 ::new (p) T(std::forward<Args>(args)...);
62 void destroy(T* p) {
63 construct_called = false;
64 destroy_called = true;
65 allocator_id = id;
66 p->~T();
70 struct Private;
72 class Factory {
73 public:
74 static std::shared_ptr<Private> allocate();
77 template <class T>
78 struct FactoryAllocator;
80 struct Private {
81 int id;
83 private:
84 friend FactoryAllocator<Private>;
85 Private(int i) : id(i) {}
86 ~Private() {}
89 template <class T>
90 struct FactoryAllocator : std::allocator<T> {
91 FactoryAllocator() = default;
93 template <class T1>
94 FactoryAllocator(FactoryAllocator<T1>) {}
96 template <class T1>
97 struct rebind {
98 typedef FactoryAllocator<T1> other;
101 void construct(void* p, int id) { ::new (p) Private(id); }
102 void destroy(Private* p) { p->~Private(); }
105 std::shared_ptr<Private> Factory::allocate() {
106 FactoryAllocator<Private> factory_alloc;
107 return std::allocate_shared<Private>(factory_alloc, 42);
110 struct mchar {
111 char c;
114 struct Foo {
115 int val;
117 Foo(int v) : val(v) {}
119 Foo(Foo a, Foo b) : val(a.val + b.val) {}
122 void test_aligned(void* p, std::size_t align) {
123 assert(reinterpret_cast<std::uintptr_t>(p) % align == 0);
126 int main(int, char**) {
128 std::shared_ptr<int> p = std::allocate_shared<int>(MyAllocator<int>());
129 assert(construct_called);
131 assert(destroy_called);
133 std::shared_ptr<Foo> p =
134 std::allocate_shared<Foo>(MyAllocator<Foo>(), Foo(42), Foo(100));
135 assert(construct_called);
136 assert(p->val == 142);
138 assert(destroy_called);
139 { // Make sure allocator is copied.
140 std::shared_ptr<int> p = std::allocate_shared<int>(MyAllocator<int>(3));
141 assert(allocator_id == 3);
143 allocator_id = 0;
145 assert(allocator_id == 3);
148 std::shared_ptr<int> p = std::allocate_shared<int>(MyAllocator<int>(), 42);
149 assert(construct_called);
150 assert(*p == 42);
152 assert(destroy_called);
154 { // Make sure allocator is properly re-bound.
155 std::shared_ptr<int> p =
156 std::allocate_shared<int>(MyAllocator<mchar>(), 42);
157 assert(construct_called);
158 assert(*p == 42);
160 assert(destroy_called);
163 // Make sure that we call the correct allocator::construct. Private has a private constructor
164 // so the construct method must be called on its friend Factory's allocator
165 // (Factory::Allocator).
166 std::shared_ptr<Private> p = Factory().allocate();
167 assert(p->id == 42);
170 #if TEST_STD_VER >= 11
172 struct Bar {
173 std::max_align_t y;
176 std::shared_ptr<Bar> p;
177 test_aligned(p.get(), alignof(Bar));
179 #endif
181 return 0;