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