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 T, class... Args>
14 // shared_ptr<T> make_shared(Args&&... args); // T is not an array
15 
16 #include <memory>
17 #include <cassert>
18 
19 #include "count_new.h"
20 #include "operator_hijacker.h"
21 #include "test_macros.h"
22 
23 struct A
24 {
25     static int count;
26 
AA27     A(int i, char c) : int_(i), char_(c) {++count;}
AA28     A(const A& a)
29         : int_(a.int_), char_(a.char_)
30         {++count;}
~AA31     ~A() {--count;}
32 
get_intA33     int get_int() const {return int_;}
get_charA34     char get_char() const {return char_;}
35 
36     A* operator& () = delete;
37 
38 private:
39     int int_;
40     char char_;
41 };
42 
43 int A::count = 0;
44 
45 
46 struct Foo
47 {
48     Foo() = default;
49     virtual ~Foo() = default;
50 };
51 
52 #ifdef _LIBCPP_VERSION
53 struct Result {};
theFunction()54 static Result theFunction() { return Result(); }
55 static int resultDeletorCount;
resultDeletor(Result (* pf)())56 static void resultDeletor(Result (*pf)()) {
57   assert(pf == theFunction);
58   ++resultDeletorCount;
59 }
60 
test_pointer_to_function()61 void test_pointer_to_function() {
62     { // https://llvm.org/PR27566
63       std::shared_ptr<Result()> x(&theFunction, &resultDeletor);
64       std::shared_ptr<Result()> y(theFunction, resultDeletor);
65     }
66     assert(resultDeletorCount == 2);
67 }
68 #else // _LIBCPP_VERSION
test_pointer_to_function()69 void test_pointer_to_function() {}
70 #endif // _LIBCPP_VERSION
71 
72 template <typename T>
test(const T & t0)73 void test(const T &t0)
74 {
75     {
76       T t1 = t0;
77       std::shared_ptr<T> p0 = std::make_shared<T>(t0);
78       std::shared_ptr<T> p1 = std::make_shared<T>(t1);
79       assert(*p0 == t0);
80       assert(*p1 == t1);
81     }
82 
83     {
84       const T t1 = t0;
85       std::shared_ptr<const T> p0 = std::make_shared<const T>(t0);
86       std::shared_ptr<const T> p1 = std::make_shared<const T>(t1);
87       assert(*p0 == t0);
88       assert(*p1 == t1);
89     }
90 }
91 
main(int,char **)92 int main(int, char**)
93 {
94     int nc = globalMemCounter.outstanding_new;
95     {
96     int i = 67;
97     char c = 'e';
98     std::shared_ptr<A> p = std::make_shared<A>(i, c);
99     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
100     assert(A::count == 1);
101     assert(p->get_int() == 67);
102     assert(p->get_char() == 'e');
103     }
104 
105     { // https://llvm.org/PR24137
106     std::shared_ptr<Foo> p1       = std::make_shared<Foo>();
107     assert(p1.get());
108     std::shared_ptr<const Foo> p2 = std::make_shared<const Foo>();
109     assert(p2.get());
110     }
111 
112     test_pointer_to_function();
113 
114 #if TEST_STD_VER >= 11
115     nc = globalMemCounter.outstanding_new;
116     {
117     char c = 'e';
118     std::shared_ptr<A> p = std::make_shared<A>(67, c);
119     assert(globalMemCounter.checkOutstandingNewLessThanOrEqual(nc+1));
120     assert(A::count == 1);
121     assert(p->get_int() == 67);
122     assert(p->get_char() == 'e');
123     }
124 #endif
125     assert(A::count == 0);
126 
127     // Make sure std::make_shared handles badly-behaved types properly
128     {
129       std::shared_ptr<operator_hijacker> p1 = std::make_shared<operator_hijacker>();
130       std::shared_ptr<operator_hijacker> p2 = std::make_shared<operator_hijacker>(operator_hijacker());
131       assert(p1 != nullptr);
132       assert(p2 != nullptr);
133     }
134 
135     test<bool>(true);
136     test<int>(3);
137     test<double>(5.0);
138 
139   return 0;
140 }
141