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