1 // RUN: %check_clang_tidy %s modernize-make-shared %t -- -- -std=c++11 \
2 // RUN:   -I%S/Inputs/modernize-smart-ptr
3 
4 #include "shared_ptr.h"
5 // CHECK-FIXES: #include <memory>
6 
7 struct Base {
8   Base();
9   Base(int, int);
10 };
11 
12 struct Derived : public Base {
13   Derived();
14   Derived(int, int);
15 };
16 
17 struct APair {
18   int a, b;
19 };
20 
21 struct DPair {
DPairDPair22   DPair() : a(0), b(0) {}
DPairDPair23   DPair(int x, int y) : a(y), b(x) {}
24   int a, b;
25 };
26 
27 struct Empty {};
28 
29 template <class T>
30 using shared_ptr_ = std::shared_ptr<T>;
31 
32 void *operator new(__SIZE_TYPE__ Count, void *Ptr);
33 
34 int g(std::shared_ptr<int> P);
35 
getPointer()36 std::shared_ptr<Base> getPointer() {
37   return std::shared_ptr<Base>(new Base);
38   // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: use std::make_shared instead
39   // CHECK-FIXES: return std::make_shared<Base>();
40 }
41 
basic()42 void basic() {
43   std::shared_ptr<int> P1 = std::shared_ptr<int>(new int());
44   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
45   // CHECK-FIXES: std::shared_ptr<int> P1 = std::make_shared<int>();
46 
47   P1.reset(new int());
48   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
49   // CHECK-FIXES: P1 = std::make_shared<int>();
50 
51   P1 = std::shared_ptr<int>(new int());
52   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
53   // CHECK-FIXES: P1 = std::make_shared<int>();
54 
55   // Without parenthesis.
56   std::shared_ptr<int> P2 = std::shared_ptr<int>(new int);
57   // CHECK-MESSAGES: :[[@LINE-1]]:29: warning: use std::make_shared instead [modernize-make-shared]
58   // CHECK-FIXES: std::shared_ptr<int> P2 = std::make_shared<int>();
59 
60   P2.reset(new int);
61   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead [modernize-make-shared]
62   // CHECK-FIXES: P2 = std::make_shared<int>();
63 
64   P2 = std::shared_ptr<int>(new int);
65   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead [modernize-make-shared]
66   // CHECK-FIXES: P2 = std::make_shared<int>();
67 
68   // With auto.
69   auto P3 = std::shared_ptr<int>(new int());
70   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
71   // CHECK-FIXES: auto P3 = std::make_shared<int>();
72 
73   {
74     // No std.
75     using namespace std;
76     shared_ptr<int> Q = shared_ptr<int>(new int());
77     // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: use std::make_shared instead
78     // CHECK-FIXES: shared_ptr<int> Q = std::make_shared<int>();
79 
80     Q = shared_ptr<int>(new int());
81     // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
82     // CHECK-FIXES: Q = std::make_shared<int>();
83   }
84 
85   std::shared_ptr<int> R(new int());
86 
87   // Create the shared_ptr as a parameter to a function.
88   int T = g(std::shared_ptr<int>(new int()));
89   // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: use std::make_shared instead
90   // CHECK-FIXES: int T = g(std::make_shared<int>());
91 
92   // Only replace if the type in the template is the same as the type returned
93   // by the new operator.
94   auto Pderived = std::shared_ptr<Base>(new Derived());
95 
96   // OK to replace for reset and assign
97   Pderived.reset(new Derived());
98   // CHECK-MESSAGES: :[[@LINE-1]]:12: warning: use std::make_shared instead
99   // CHECK-FIXES: Pderived = std::make_shared<Derived>();
100 
101   Pderived = std::shared_ptr<Derived>(new Derived());
102   // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: use std::make_shared instead
103   // CHECK-FIXES: Pderived = std::make_shared<Derived>();
104 
105   // FIXME: OK to replace if assigned to shared_ptr<Base>
106   Pderived = std::shared_ptr<Base>(new Derived());
107 
108   // FIXME: OK to replace when auto is not used
109   std::shared_ptr<Base> PBase = std::shared_ptr<Base>(new Derived());
110 
111   // The pointer is returned by the function, nothing to do.
112   std::shared_ptr<Base> RetPtr = getPointer();
113 
114   // This emulates std::move.
115   std::shared_ptr<int> Move = static_cast<std::shared_ptr<int> &&>(P1);
116 
117   // Placement arguments should not be removed.
118   int *PInt = new int;
119   std::shared_ptr<int> Placement = std::shared_ptr<int>(new (PInt) int{3});
120   Placement.reset(new (PInt) int{3});
121   Placement = std::shared_ptr<int>(new (PInt) int{3});
122 }
123 
124 // Calling make_smart_ptr from within a member function of a type with a
125 // private or protected constructor would be ill-formed.
126 class Private {
127 private:
Private(int z)128   Private(int z) {}
129 
130 public:
Private()131   Private() {}
create()132   void create() {
133     auto callsPublic = std::shared_ptr<Private>(new Private);
134     // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
135     // CHECK-FIXES: auto callsPublic = std::make_shared<Private>();
136     auto ptr = std::shared_ptr<Private>(new Private(42));
137     ptr.reset(new Private(42));
138     ptr = std::shared_ptr<Private>(new Private(42));
139   }
140 
141   virtual ~Private();
142 };
143 
144 class Protected {
145 protected:
Protected()146   Protected() {}
147 
148 public:
Protected(int,int)149   Protected(int, int) {}
create()150   void create() {
151     auto callsPublic = std::shared_ptr<Protected>(new Protected(1, 2));
152     // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
153     // CHECK-FIXES: auto callsPublic = std::make_shared<Protected>(1, 2);
154     auto ptr = std::shared_ptr<Protected>(new Protected);
155     ptr.reset(new Protected);
156     ptr = std::shared_ptr<Protected>(new Protected);
157   }
158 };
159 
initialization(int T,Base b)160 void initialization(int T, Base b) {
161   // Test different kinds of initialization of the pointee.
162 
163   // Direct initialization with parenthesis.
164   std::shared_ptr<DPair> PDir1 = std::shared_ptr<DPair>(new DPair(1, T));
165   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
166   // CHECK-FIXES: std::shared_ptr<DPair> PDir1 = std::make_shared<DPair>(1, T);
167   PDir1.reset(new DPair(1, T));
168   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
169   // CHECK-FIXES: PDir1 = std::make_shared<DPair>(1, T);
170 
171   // Direct initialization with braces.
172   std::shared_ptr<DPair> PDir2 = std::shared_ptr<DPair>(new DPair{2, T});
173   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
174   // CHECK-FIXES: std::shared_ptr<DPair> PDir2 = std::make_shared<DPair>(2, T);
175   PDir2.reset(new DPair{2, T});
176   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
177   // CHECK-FIXES: PDir2 = std::make_shared<DPair>(2, T);
178 
179   // Aggregate initialization.
180   std::shared_ptr<APair> PAggr = std::shared_ptr<APair>(new APair{T, 1});
181   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
182   // CHECK-FIXES: std::shared_ptr<APair> PAggr = std::make_shared<APair>(APair{T, 1});
183   PAggr.reset(new APair{T, 1});
184   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
185   // CHECK-FIXES: std::make_shared<APair>(APair{T, 1});
186 
187   // Test different kinds of initialization of the pointee, when the shared_ptr
188   // is initialized with braces.
189 
190   // Direct initialization with parenthesis.
191   std::shared_ptr<DPair> PDir3 = std::shared_ptr<DPair>{new DPair(3, T)};
192   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
193   // CHECK-FIXES: std::shared_ptr<DPair> PDir3 = std::make_shared<DPair>(3, T);
194 
195   // Direct initialization with braces.
196   std::shared_ptr<DPair> PDir4 = std::shared_ptr<DPair>{new DPair{4, T}};
197   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
198   // CHECK-FIXES: std::shared_ptr<DPair> PDir4 = std::make_shared<DPair>(4, T);
199 
200   // Aggregate initialization.
201   std::shared_ptr<APair> PAggr2 = std::shared_ptr<APair>{new APair{T, 2}};
202   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
203   // CHECK-FIXES: std::shared_ptr<APair> PAggr2 = std::make_shared<APair>(APair{T, 2});
204 
205   // Direct initialization with parenthesis, without arguments.
206   std::shared_ptr<DPair> PDir5 = std::shared_ptr<DPair>(new DPair());
207   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
208   // CHECK-FIXES: std::shared_ptr<DPair> PDir5 = std::make_shared<DPair>();
209 
210   // Direct initialization with braces, without arguments.
211   std::shared_ptr<DPair> PDir6 = std::shared_ptr<DPair>(new DPair{});
212   // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: use std::make_shared instead
213   // CHECK-FIXES: std::shared_ptr<DPair> PDir6 = std::make_shared<DPair>();
214 
215   // Aggregate initialization without arguments.
216   std::shared_ptr<Empty> PEmpty = std::shared_ptr<Empty>(new Empty{});
217   // CHECK-MESSAGES: :[[@LINE-1]]:35: warning: use std::make_shared instead
218   // CHECK-FIXES: std::shared_ptr<Empty> PEmpty = std::make_shared<Empty>(Empty{});
219 }
220 
aliases()221 void aliases() {
222   typedef std::shared_ptr<int> IntPtr;
223   IntPtr Typedef = IntPtr(new int);
224   // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: use std::make_shared instead
225   // CHECK-FIXES: IntPtr Typedef = std::make_shared<int>();
226 
227   // We use 'bool' instead of '_Bool'.
228   typedef std::shared_ptr<bool> BoolPtr;
229   BoolPtr BoolType = BoolPtr(new bool);
230   // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: use std::make_shared instead
231   // CHECK-FIXES: BoolPtr BoolType = std::make_shared<bool>();
232 
233   // We use 'Base' instead of 'struct Base'.
234   typedef std::shared_ptr<Base> BasePtr;
235   BasePtr StructType = BasePtr(new Base);
236 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: use std::make_shared instead
237 // CHECK-FIXES: BasePtr StructType = std::make_shared<Base>();
238 
239 #define PTR shared_ptr<int>
240   std::shared_ptr<int> Macro = std::PTR(new int);
241 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
242 // CHECK-FIXES: std::shared_ptr<int> Macro = std::make_shared<int>();
243 #undef PTR
244 
245   std::shared_ptr<int> Using = shared_ptr_<int>(new int);
246   // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: use std::make_shared instead
247   // CHECK-FIXES: std::shared_ptr<int> Using = std::make_shared<int>();
248 }
249 
whitespaces()250 void whitespaces() {
251   // clang-format off
252   auto Space = std::shared_ptr <int>(new int());
253   // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: use std::make_shared instead
254   // CHECK-FIXES: auto Space = std::make_shared<int>();
255 
256   auto Spaces = std  ::    shared_ptr  <int>(new int());
257   // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: use std::make_shared instead
258   // CHECK-FIXES: auto Spaces = std::make_shared<int>();
259   // clang-format on
260 }
261 
nesting()262 void nesting() {
263   auto Nest = std::shared_ptr<std::shared_ptr<int>>(new std::shared_ptr<int>(new int));
264   // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: use std::make_shared instead
265   // CHECK-FIXES: auto Nest = std::make_shared<std::shared_ptr<int>>(new int);
266   Nest.reset(new std::shared_ptr<int>(new int));
267   // CHECK-MESSAGES: :[[@LINE-1]]:8: warning: use std::make_shared instead
268   // CHECK-FIXES: Nest = std::make_shared<std::shared_ptr<int>>(new int);
269   Nest->reset(new int);
270   // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use std::make_shared instead
271   // CHECK-FIXES: *Nest = std::make_shared<int>();
272 }
273 
reset()274 void reset() {
275   std::shared_ptr<int> P;
276   P.reset();
277   P.reset(nullptr);
278   P.reset(new int());
279   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use std::make_shared instead
280   // CHECK-FIXES: P = std::make_shared<int>();
281 
282   auto Q = &P;
283   Q->reset(new int());
284   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use std::make_shared instead
285   // CHECK-FIXES: *Q = std::make_shared<int>();
286 }
287