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 // shared_ptr
12 
13 // template<class Y> shared_ptr(const shared_ptr<Y>& r);
14 
15 #include <memory>
16 #include <type_traits>
17 #include <cassert>
18 
19 #include "test_macros.h"
20 
21 struct B
22 {
23     static int count;
24 
BB25     B() {++count;}
BB26     B(const B&) {++count;}
~BB27     virtual ~B() {--count;}
28 };
29 
30 int B::count = 0;
31 
32 struct A
33     : public B
34 {
35     static int count;
36 
AA37     A() {++count;}
AA38     A(const A& other) : B(other) {++count;}
~AA39     ~A() {--count;}
40 };
41 
42 int A::count = 0;
43 
44 struct C
45 {
46     static int count;
47 
CC48     C() {++count;}
CC49     C(const C&) {++count;}
~CC50     virtual ~C() {--count;}
51 };
52 
53 int C::count = 0;
54 
55 class private_delete_op
56 {
operator delete(void * p)57     static void operator delete (void *p) {
58         return delete static_cast<char*>(p);
59     }
60 public:
operator delete[](void * p)61     static void operator delete[] (void *p) {
62         return delete[] static_cast<char*>(p);
63     }
64 };
65 
66 class private_delete_arr_op
67 {
operator delete[](void * p)68     static void operator delete[] (void *p) {
69         return delete[] static_cast<char*>(p);
70     }
71 public:
operator delete(void * p)72     static void operator delete (void *p) {
73         return delete static_cast<char*>(p);
74     }
75 };
76 
77 // https://llvm.org/PR60258
78 // Invalid constructor SFINAE for std::shared_ptr's array ctors
79 static_assert(!std::is_constructible<std::shared_ptr<int>,     const std::shared_ptr<long>&>::value, "");
80 static_assert( std::is_constructible<std::shared_ptr<B>,       const std::shared_ptr<A>&>::value, "");
81 static_assert( std::is_constructible<std::shared_ptr<const A>, const std::shared_ptr<A>&>::value, "");
82 static_assert(!std::is_constructible<std::shared_ptr<A>,       const std::shared_ptr<const A>&>::value, "");
83 
84 #if TEST_STD_VER >= 17
85 static_assert(!std::is_constructible<std::shared_ptr<int>,     const std::shared_ptr<int[]>&>::value, "");
86 static_assert(!std::is_constructible<std::shared_ptr<int>,     const std::shared_ptr<int[5]>&>::value, "");
87 static_assert(!std::is_constructible<std::shared_ptr<int[]>,   const std::shared_ptr<int>&>::value, "");
88 static_assert( std::is_constructible<std::shared_ptr<int[]>,   const std::shared_ptr<int[5]>&>::value, "");
89 static_assert(!std::is_constructible<std::shared_ptr<int[5]>,  const std::shared_ptr<int>&>::value, "");
90 static_assert(!std::is_constructible<std::shared_ptr<int[5]>,  const std::shared_ptr<int[]>&>::value, "");
91 static_assert(!std::is_constructible<std::shared_ptr<int[7]>,  const std::shared_ptr<int[5]>&>::value, "");
92 #endif
93 
main(int,char **)94 int main(int, char**)
95 {
96     static_assert(( std::is_convertible<std::shared_ptr<A>, std::shared_ptr<B> >::value), "");
97     static_assert((!std::is_convertible<std::shared_ptr<B>, std::shared_ptr<A> >::value), "");
98     static_assert((!std::is_convertible<std::shared_ptr<A>, std::shared_ptr<C> >::value), "");
99     {
100         const std::shared_ptr<A> pA(new A);
101         assert(pA.use_count() == 1);
102         assert(B::count == 1);
103         assert(A::count == 1);
104         {
105             std::shared_ptr<B> pB(pA);
106             assert(B::count == 1);
107             assert(A::count == 1);
108             assert(pB.use_count() == 2);
109             assert(pA.use_count() == 2);
110             assert(pA.get() == pB.get());
111         }
112         assert(pA.use_count() == 1);
113         assert(B::count == 1);
114         assert(A::count == 1);
115     }
116     assert(B::count == 0);
117     assert(A::count == 0);
118     {
119         std::shared_ptr<A> pA;
120         assert(pA.use_count() == 0);
121         assert(B::count == 0);
122         assert(A::count == 0);
123         {
124             std::shared_ptr<B> pB(pA);
125             assert(B::count == 0);
126             assert(A::count == 0);
127             assert(pB.use_count() == 0);
128             assert(pA.use_count() == 0);
129             assert(pA.get() == pB.get());
130         }
131         assert(pA.use_count() == 0);
132         assert(B::count == 0);
133         assert(A::count == 0);
134     }
135     assert(B::count == 0);
136     assert(A::count == 0);
137 
138     // This should work in C++03 but we get errors when trying to do SFINAE with the delete operator.
139     // GCC also complains about this.
140 #if TEST_STD_VER >= 11 && !defined(TEST_COMPILER_GCC)
141     {
142         // LWG2874: Make sure that when T (for std::shared_ptr<T>) is an array type,
143         //          this constructor only participates in overload resolution when
144         //          `delete[] p` is well formed. And when T is not an array type,
145         //          this constructor only participates in overload resolution when
146         //          `delete p` is well formed.
147         static_assert(!std::is_constructible<std::shared_ptr<private_delete_op>,
148                                                              private_delete_op*>::value, "");
149         static_assert(!std::is_constructible<std::shared_ptr<private_delete_arr_op[4]>,
150                                                              private_delete_arr_op*>::value, "");
151     }
152 #endif
153 
154 #if TEST_STD_VER > 14
155     {
156         std::shared_ptr<A[]> p1(new A[8]);
157         assert(p1.use_count() == 1);
158         assert(A::count == 8);
159         {
160             std::shared_ptr<const A[]> p2(p1);
161             assert(A::count == 8);
162             assert(p2.use_count() == 2);
163             assert(p1.use_count() == 2);
164             assert(p1.get() == p2.get());
165         }
166         assert(p1.use_count() == 1);
167         assert(A::count == 8);
168     }
169     assert(A::count == 0);
170 #endif
171 
172     {
173         std::shared_ptr<A const> pA(new A);
174         std::shared_ptr<B const> pB(pA);
175         assert(pB.get() == pA.get());
176     }
177 
178     return 0;
179 }
180