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 // XFAIL: LIBCXX-AIX-FIXME
10 
11 // <string>
12 
13 // basic_string(const basic_string& str, const Allocator& alloc); // constexpr since C++20
14 
15 #include <string>
16 #include <cassert>
17 
18 #include "test_macros.h"
19 #include "test_allocator.h"
20 #include "min_allocator.h"
21 
22 #ifndef TEST_HAS_NO_EXCEPTIONS
23 struct alloc_imp {
24     bool active;
25 
26     TEST_CONSTEXPR alloc_imp() : active(true) {}
27 
28     template <class T>
29     T* allocate(std::size_t n)
30     {
31         if (active)
32             return static_cast<T*>(std::malloc(n * sizeof(T)));
33         else
34             throw std::bad_alloc();
35     }
36 
37     template <class T>
38     void deallocate(T* p, std::size_t) { std::free(p); }
39     void activate  ()                  { active = true; }
40     void deactivate()                  { active = false; }
41 };
42 
43 template <class T>
44 struct poca_alloc {
45     typedef T value_type;
46     typedef std::true_type propagate_on_container_copy_assignment;
47 
48     alloc_imp *imp;
49 
50     TEST_CONSTEXPR poca_alloc(alloc_imp *imp_) : imp (imp_) {}
51 
52     template <class U>
53     TEST_CONSTEXPR poca_alloc(const poca_alloc<U>& other) : imp(other.imp) {}
54 
55     T*   allocate  (std::size_t n)       { return imp->allocate<T>(n);}
56     void deallocate(T* p, std::size_t n) { imp->deallocate(p, n); }
57 };
58 
59 template <typename T, typename U>
60 bool operator==(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
61 {
62     return lhs.imp == rhs.imp;
63 }
64 
65 template <typename T, typename U>
66 bool operator!=(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
67 {
68     return lhs.imp != rhs.imp;
69 }
70 
71 template <class S>
72 TEST_CONSTEXPR_CXX20 void test_assign(S &s1, const S& s2)
73 {
74     try { s1 = s2; }
75     catch ( std::bad_alloc &) { return; }
76     assert(false);
77 }
78 #endif
79 
80 
81 
82 template <class S>
83 TEST_CONSTEXPR_CXX20 void
84 test(S s1, const typename S::allocator_type& a)
85 {
86     S s2(s1, a);
87     LIBCPP_ASSERT(s2.__invariants());
88     assert(s2 == s1);
89     assert(s2.capacity() >= s2.size());
90     assert(s2.get_allocator() == a);
91 }
92 
93 TEST_CONSTEXPR_CXX20 bool test() {
94   {
95     typedef test_allocator<char> A;
96     typedef std::basic_string<char, std::char_traits<char>, A> S;
97     test(S(), A(3));
98     test(S("1"), A(5));
99     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
100   }
101 #if TEST_STD_VER >= 11
102   {
103     typedef min_allocator<char> A;
104     typedef std::basic_string<char, std::char_traits<char>, A> S;
105     test(S(), A());
106     test(S("1"), A());
107     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
108   }
109 
110 #ifndef TEST_HAS_NO_EXCEPTIONS
111   if (!TEST_IS_CONSTANT_EVALUATED) {
112     typedef poca_alloc<char> A;
113     typedef std::basic_string<char, std::char_traits<char>, A> S;
114     const char * p1 = "This is my first string";
115     const char * p2 = "This is my second string";
116 
117     alloc_imp imp1;
118     alloc_imp imp2;
119     S s1(p1, A(&imp1));
120     S s2(p2, A(&imp2));
121 
122     assert(s1 == p1);
123     assert(s2 == p2);
124 
125     imp2.deactivate();
126     test_assign(s1, s2);
127     assert(s1 == p1);
128     assert(s2 == p2);
129   }
130 #endif
131 #endif
132 
133   return true;
134 }
135 
136 int main(int, char**)
137 {
138   test();
139 #if TEST_STD_VER > 17
140   static_assert(test());
141 #endif
142 
143   return 0;
144 }
145