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 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // template<class T>
12 //   constexpr unique_ptr<T> make_unique_for_overwrite(); // T is not array
13 //
14 // template<class T>
15 //   constexpr unique_ptr<T> make_unique_for_overwrite(size_t n); // T is U[]
16 //
17 // template<class T, class... Args>
18 //   unspecified make_unique_for_overwrite(Args&&...) = delete; // T is U[N]
19 
20 #include <cassert>
21 #include <concepts>
22 #include <cstring>
23 #include <memory>
24 #include <utility>
25 
26 #include "test_macros.h"
27 
28 template <class T, class... Args>
29 concept HasMakeUniqueForOverwrite =
30     requires(Args&&... args) { std::make_unique_for_overwrite<T>(std::forward<Args>(args)...); };
31 
32 struct Foo {
33   int i;
34 };
35 
36 // template<class T>
37 //   constexpr unique_ptr<T> make_unique_for_overwrite();
38 static_assert(HasMakeUniqueForOverwrite<int>);
39 static_assert(HasMakeUniqueForOverwrite<Foo>);
40 static_assert(!HasMakeUniqueForOverwrite<int, int>);
41 static_assert(!HasMakeUniqueForOverwrite<Foo, Foo>);
42 
43 // template<class T>
44 //   constexpr unique_ptr<T> make_unique_for_overwrite(size_t n);
45 static_assert(HasMakeUniqueForOverwrite<int[], std::size_t>);
46 static_assert(HasMakeUniqueForOverwrite<Foo[], std::size_t>);
47 static_assert(!HasMakeUniqueForOverwrite<int[]>);
48 static_assert(!HasMakeUniqueForOverwrite<Foo[]>);
49 static_assert(!HasMakeUniqueForOverwrite<int[], std::size_t, int>);
50 static_assert(!HasMakeUniqueForOverwrite<Foo[], std::size_t, int>);
51 
52 // template<class T, class... Args>
53 //   unspecified make_unique_for_overwrite(Args&&...) = delete;
54 static_assert(!HasMakeUniqueForOverwrite<int[2]>);
55 static_assert(!HasMakeUniqueForOverwrite<int[2], std::size_t>);
56 static_assert(!HasMakeUniqueForOverwrite<int[2], int>);
57 static_assert(!HasMakeUniqueForOverwrite<int[2], int, int>);
58 static_assert(!HasMakeUniqueForOverwrite<Foo[2]>);
59 static_assert(!HasMakeUniqueForOverwrite<Foo[2], std::size_t>);
60 static_assert(!HasMakeUniqueForOverwrite<Foo[2], int>);
61 static_assert(!HasMakeUniqueForOverwrite<Foo[2], int, int>);
62 
63 struct WithDefaultConstructor {
64   int i;
WithDefaultConstructorWithDefaultConstructor65   constexpr WithDefaultConstructor() : i(5) {}
66 };
67 
test()68 TEST_CONSTEXPR_CXX23 bool test() {
69   // single int
70   {
71     std::same_as<std::unique_ptr<int>> decltype(auto) ptr = std::make_unique_for_overwrite<int>();
72     // memory is available for write, otherwise constexpr test would fail
73     *ptr = 5;
74   }
75 
76   // unbounded array int[]
77   {
78     std::same_as<std::unique_ptr<int[]>> decltype(auto) ptrs = std::make_unique_for_overwrite<int[]>(3);
79 
80     // memory is available for write, otherwise constexpr test would fail
81     ptrs[0] = 3;
82     ptrs[1] = 4;
83     ptrs[2] = 5;
84   }
85 
86   // single with default constructor
87   {
88     std::same_as<std::unique_ptr<WithDefaultConstructor>> decltype(auto) ptr =
89         std::make_unique_for_overwrite<WithDefaultConstructor>();
90     assert(ptr->i == 5);
91   }
92 
93   // unbounded array with default constructor
94   {
95     std::same_as<std::unique_ptr<WithDefaultConstructor[]>> decltype(auto) ptrs =
96         std::make_unique_for_overwrite<WithDefaultConstructor[]>(3);
97     assert(ptrs[0].i == 5);
98     assert(ptrs[1].i == 5);
99     assert(ptrs[2].i == 5);
100   }
101 
102   return true;
103 }
104 
105 // The standard specifically says to use `new (p) T`, which means that we should pick up any
106 // custom in-class operator new if there is one.
107 struct WithCustomNew {
108   inline static bool customNewCalled    = false;
109   inline static bool customNewArrCalled = false;
110 
operator newWithCustomNew111   static void* operator new(std::size_t n) {
112     customNewCalled = true;
113     return ::operator new(n);
114     ;
115   }
116 
operator new[]WithCustomNew117   static void* operator new[](std::size_t n) {
118     customNewArrCalled = true;
119     return ::operator new[](n);
120   }
121 };
122 
testCustomNew()123 void testCustomNew() {
124   // single with custom operator new
125   {
126     [[maybe_unused]] std::same_as<std::unique_ptr<WithCustomNew>> decltype(auto) ptr =
127         std::make_unique_for_overwrite<WithCustomNew>();
128 
129     assert(WithCustomNew::customNewCalled);
130   }
131 
132   // unbounded array with custom operator new
133   {
134     [[maybe_unused]] std::same_as<std::unique_ptr<WithCustomNew[]>> decltype(auto) ptr =
135         std::make_unique_for_overwrite<WithCustomNew[]>(3);
136 
137     assert(WithCustomNew::customNewArrCalled);
138   }
139 }
140 
main(int,char **)141 int main(int, char**) {
142   test();
143   testCustomNew();
144 #if TEST_STD_VER >= 23
145   static_assert(test());
146 #endif
147 
148   return 0;
149 }
150