1 // RUN: %check_clang_tidy %s modernize-use-emplace %t -- \
2 // RUN:   -config="{CheckOptions: \
3 // RUN:             [{key: modernize-use-emplace.ContainersWithPushBack, \
4 // RUN:               value: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector'}, \
5 // RUN:              {key: modernize-use-emplace.TupleTypes, \
6 // RUN:               value: '::std::pair; std::tuple; ::test::Single'}, \
7 // RUN:              {key: modernize-use-emplace.TupleMakeFunctions, \
8 // RUN:               value: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}] \
9 // RUN:             }"
10 
11 namespace std {
12 template <typename>
13 class initializer_list
14 {
15 public:
initializer_list()16   initializer_list() noexcept {}
17 };
18 
19 template <typename T>
20 class vector {
21 public:
22   vector() = default;
vector(initializer_list<T>)23   vector(initializer_list<T>) {}
24 
push_back(const T &)25   void push_back(const T &) {}
push_back(T &&)26   void push_back(T &&) {}
27 
28   template <typename... Args>
emplace_back(Args &&...args)29   void emplace_back(Args &&... args){};
30   ~vector();
31 };
32 template <typename T>
33 class list {
34 public:
push_back(const T &)35   void push_back(const T &) {}
push_back(T &&)36   void push_back(T &&) {}
37 
38   template <typename... Args>
emplace_back(Args &&...args)39   void emplace_back(Args &&... args){};
40   ~list();
41 };
42 
43 template <typename T>
44 class deque {
45 public:
push_back(const T &)46   void push_back(const T &) {}
push_back(T &&)47   void push_back(T &&) {}
48 
49   template <typename... Args>
emplace_back(Args &&...args)50   void emplace_back(Args &&... args){};
51   ~deque();
52 };
53 
54 template <typename T> struct remove_reference { using type = T; };
55 template <typename T> struct remove_reference<T &> { using type = T; };
56 template <typename T> struct remove_reference<T &&> { using type = T; };
57 
58 template <typename T1, typename T2> class pair {
59 public:
60   pair() = default;
61   pair(const pair &) = default;
62   pair(pair &&) = default;
63 
pair(const T1 &,const T2 &)64   pair(const T1 &, const T2 &) {}
pair(T1 &&,T2 &&)65   pair(T1 &&, T2 &&) {}
66 
pair(const pair<U1,U2> &)67   template <typename U1, typename U2> pair(const pair<U1, U2> &){};
pair(pair<U1,U2> &&)68   template <typename U1, typename U2> pair(pair<U1, U2> &&){};
69 };
70 
71 template <typename T1, typename T2>
72 pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type>
make_pair(T1 &&,T2 &&)73 make_pair(T1 &&, T2 &&) {
74   return {};
75 };
76 
77 template <typename... Ts> class tuple {
78 public:
79   tuple() = default;
80   tuple(const tuple &) = default;
81   tuple(tuple &&) = default;
82 
tuple(const Ts &...)83   tuple(const Ts &...) {}
tuple(Ts &&...)84   tuple(Ts &&...) {}
85 
tuple(const tuple<Us...> &)86   template <typename... Us> tuple(const tuple<Us...> &){};
tuple(tuple<Us...> &&)87   template <typename... Us> tuple(tuple<Us...> &&) {}
88 
tuple(const pair<U1,U2> &)89   template <typename U1, typename U2> tuple(const pair<U1, U2> &) {
90     static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
91   };
tuple(pair<U1,U2> &&)92   template <typename U1, typename U2> tuple(pair<U1, U2> &&) {
93     static_assert(sizeof...(Ts) == 2, "Wrong tuple size");
94   };
95 };
96 
97 template <typename... Ts>
make_tuple(Ts &&...)98 tuple<typename remove_reference<Ts>::type...> make_tuple(Ts &&...) {
99   return {};
100 }
101 
102 template <typename T>
103 class unique_ptr {
104 public:
unique_ptr(T *)105   explicit unique_ptr(T *) {}
106   ~unique_ptr();
107 };
108 } // namespace std
109 
110 namespace llvm {
111 template <typename T>
112 class LikeASmallVector {
113 public:
push_back(const T &)114   void push_back(const T &) {}
push_back(T &&)115   void push_back(T &&) {}
116 
117   template <typename... Args>
emplace_back(Args &&...args)118   void emplace_back(Args &&... args){};
119 };
120 
121 } // llvm
122 
testInts()123 void testInts() {
124   std::vector<int> v;
125   v.push_back(42);
126   v.push_back(int(42));
127   v.push_back(int{42});
128   v.push_back(42.0);
129   int z;
130   v.push_back(z);
131 }
132 
133 struct Something {
SomethingSomething134   Something(int a, int b = 41) {}
SomethingSomething135   Something() {}
136   void push_back(Something);
getIntSomething137   int getInt() { return 42; }
138 };
139 
140 struct Convertable {
operator SomethingConvertable141   operator Something() { return Something{}; }
142 };
143 
144 struct Zoz {
ZozZoz145   Zoz(Something, int = 42) {}
146 };
147 
getZoz(Something s)148 Zoz getZoz(Something s) { return Zoz(s); }
149 
test_Something()150 void test_Something() {
151   std::vector<Something> v;
152 
153   v.push_back(Something(1, 2));
154   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace]
155   // CHECK-FIXES: v.emplace_back(1, 2);
156 
157   v.push_back(Something{1, 2});
158   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
159   // CHECK-FIXES: v.emplace_back(1, 2);
160 
161   v.push_back(Something());
162   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
163   // CHECK-FIXES: v.emplace_back();
164 
165   v.push_back(Something{});
166   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
167   // CHECK-FIXES: v.emplace_back();
168 
169   Something Different;
170   v.push_back(Something(Different.getInt(), 42));
171   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
172   // CHECK-FIXES: v.emplace_back(Different.getInt(), 42);
173 
174   v.push_back(Different.getInt());
175   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
176   // CHECK-FIXES: v.emplace_back(Different.getInt());
177 
178   v.push_back(42);
179   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
180   // CHECK-FIXES: v.emplace_back(42);
181 
182   Something temporary(42, 42);
183   temporary.push_back(temporary);
184   v.push_back(temporary);
185 
186   v.push_back(Convertable());
187   v.push_back(Convertable{});
188   Convertable s;
189   v.push_back(s);
190 }
191 
192 template <typename ElemType>
dependOnElem()193 void dependOnElem() {
194   std::vector<ElemType> v;
195   v.push_back(ElemType(42));
196 }
197 
198 template <typename ContainerType>
dependOnContainer()199 void dependOnContainer() {
200   ContainerType v;
201   v.push_back(Something(42));
202 }
203 
callDependent()204 void callDependent() {
205   dependOnElem<Something>();
206   dependOnContainer<std::vector<Something>>();
207 }
208 
test2()209 void test2() {
210   std::vector<Zoz> v;
211   v.push_back(Zoz(Something(21, 37)));
212   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
213   // CHECK-FIXES: v.emplace_back(Something(21, 37));
214 
215   v.push_back(Zoz(Something(21, 37), 42));
216   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
217   // CHECK-FIXES: v.emplace_back(Something(21, 37), 42);
218 
219   v.push_back(getZoz(Something(1, 2)));
220 }
221 
222 struct GetPair {
223   std::pair<int, long> getPair();
224 };
testPair()225 void testPair() {
226   std::vector<std::pair<int, int>> v;
227   v.push_back(std::pair<int, int>(1, 2));
228   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
229   // CHECK-FIXES: v.emplace_back(1, 2);
230 
231   GetPair g;
232   v.push_back(g.getPair());
233   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
234   // CHECK-FIXES: v.emplace_back(g.getPair());
235 
236   std::vector<std::pair<Something, Zoz>> v2;
237   v2.push_back(std::pair<Something, Zoz>(Something(42, 42), Zoz(Something(21, 37))));
238   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
239   // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37)));
240 }
241 
testTuple()242 void testTuple() {
243   std::vector<std::tuple<bool, char, int>> v;
244   v.push_back(std::tuple<bool, char, int>(false, 'x', 1));
245   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
246   // CHECK-FIXES: v.emplace_back(false, 'x', 1);
247 
248   v.push_back(std::tuple<bool, char, int>{false, 'y', 2});
249   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
250   // CHECK-FIXES: v.emplace_back(false, 'y', 2);
251 
252   v.push_back({true, 'z', 3});
253   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
254   // CHECK-FIXES: v.emplace_back(true, 'z', 3);
255 
256   std::vector<std::tuple<int, bool>> x;
257   x.push_back(std::make_pair(1, false));
258   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
259   // CHECK-FIXES: x.emplace_back(1, false);
260 
261   x.push_back(std::make_pair(2LL, 1));
262   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
263   // CHECK-FIXES: x.emplace_back(2LL, 1);
264 }
265 
266 struct Base {
267   Base(int, int *, int = 42);
268 };
269 
270 struct Derived : Base {
DerivedDerived271   Derived(int *, Something) : Base(42, nullptr) {}
272 };
273 
testDerived()274 void testDerived() {
275   std::vector<Base> v;
276   v.push_back(Derived(nullptr, Something{}));
277 }
278 
testNewExpr()279 void testNewExpr() {
280   std::vector<Derived> v;
281   v.push_back(Derived(new int, Something{}));
282 }
283 
testSpaces()284 void testSpaces() {
285   std::vector<Something> v;
286 
287   // clang-format off
288 
289   v.push_back(Something(1, //arg1
290                 2 // arg2
291                ) // Something
292               );
293   // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back
294   // CHECK-FIXES: v.emplace_back(1, //arg1
295   // CHECK-FIXES:                2 // arg2
296   // CHECK-FIXES:                  // Something
297   // CHECK-FIXES:                );
298 
299   v.push_back(    Something   (1, 2)    );
300   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
301   // CHECK-FIXES: v.emplace_back(1, 2   );
302 
303   v.push_back(    Something   {1, 2}    );
304   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
305   // CHECK-FIXES: v.emplace_back(1, 2   );
306 
307   v.push_back(  Something {}    );
308   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
309   // CHECK-FIXES: v.emplace_back(   );
310 
311   v.push_back(
312              Something(1, 2)    );
313   // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back
314   // CHECK-FIXES: v.emplace_back(1, 2   );
315 
316   std::vector<Base> v2;
317   v2.push_back(
318     Base(42, nullptr));
319   // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back
320   // CHECK-FIXES: v2.emplace_back(42, nullptr);
321 
322   // clang-format on
323 }
324 
testPointers()325 void testPointers() {
326   std::vector<int *> v;
327   v.push_back(new int(5));
328 
329   std::vector<std::unique_ptr<int>> v2;
330   v2.push_back(std::unique_ptr<int>(new int(42)));
331   // This call can't be replaced with emplace_back.
332   // If emplacement will fail (not enough memory to add to vector)
333   // we will have leak of int because unique_ptr won't be constructed
334   // (and destructed) as in push_back case.
335 
336   auto *ptr = new int;
337   v2.push_back(std::unique_ptr<int>(ptr));
338   // Same here
339 }
340 
testMakePair()341 void testMakePair() {
342   std::vector<std::pair<int, int>> v;
343   v.push_back(std::make_pair(1, 2));
344   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
345   // CHECK-FIXES: v.emplace_back(1, 2);
346 
347   v.push_back(std::make_pair(42LL, 13));
348   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
349   // CHECK-FIXES: v.emplace_back(42LL, 13);
350 
351   v.push_back(std::make_pair<char, char>(0, 3));
352   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
353   // CHECK-FIXES: v.emplace_back(std::make_pair<char, char>(0, 3));
354   //
355   // Even though the call above could be turned into v.emplace_back(0, 3),
356   // we don't eliminate the make_pair call here, because of the explicit
357   // template parameters provided. make_pair's arguments can be convertible
358   // to its explicitly provided template parameter, but not to the pair's
359   // element type. The examples below illustrate the problem.
360   struct D {
361     D(...) {}
362     operator char() const { return 0; }
363   };
364   v.push_back(std::make_pair<D, int>(Something(), 2));
365   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
366   // CHECK-FIXES: v.emplace_back(std::make_pair<D, int>(Something(), 2));
367 
368   struct X {
369     X(std::pair<int, int>) {}
370   };
371   std::vector<X> x;
372   x.push_back(std::make_pair(1, 2));
373   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
374   // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2));
375   // make_pair cannot be removed here, as X is not constructible with two ints.
376 
377   struct Y {
378     Y(std::pair<int, int>&&) {}
379   };
380   std::vector<Y> y;
381   y.push_back(std::make_pair(2, 3));
382   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
383   // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3));
384   // make_pair cannot be removed here, as Y is not constructible with two ints.
385 }
386 
testMakeTuple()387 void testMakeTuple() {
388   std::vector<std::tuple<int, bool, char>> v;
389   v.push_back(std::make_tuple(1, true, 'v'));
390   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
391   // CHECK-FIXES: v.emplace_back(1, true, 'v');
392 
393   v.push_back(std::make_tuple(2ULL, 1, 0));
394   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
395   // CHECK-FIXES: v.emplace_back(2ULL, 1, 0);
396 
397   v.push_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
398   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
399   // CHECK-FIXES: v.emplace_back(std::make_tuple<long long, int, int>(3LL, 1, 0));
400   // make_tuple is not removed when there are explicit template
401   // arguments provided.
402 }
403 
404 namespace test {
405 template <typename T> struct Single {
406   Single() = default;
407   Single(const Single &) = default;
408   Single(Single &&) = default;
409 
Singletest::Single410   Single(const T &) {}
Singletest::Single411   Single(T &&) {}
412 
Singletest::Single413   template <typename U> Single(const Single<U> &) {}
Singletest::Single414   template <typename U> Single(Single<U> &&) {}
415 
Singletest::Single416   template <typename U> Single(const std::tuple<U> &) {}
Singletest::Single417   template <typename U> Single(std::tuple<U> &&) {}
418 };
419 
420 template <typename T>
MakeSingle(T &&)421 Single<typename std::remove_reference<T>::type> MakeSingle(T &&) {
422   return {};
423 }
424 } // namespace test
425 
testOtherTuples()426 void testOtherTuples() {
427   std::vector<test::Single<int>> v;
428   v.push_back(test::Single<int>(1));
429   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
430   // CHECK-FIXES: v.emplace_back(1);
431 
432   v.push_back({2});
433   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
434   // CHECK-FIXES: v.emplace_back(2);
435 
436   v.push_back(test::MakeSingle(3));
437   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
438   // CHECK-FIXES: v.emplace_back(3);
439 
440   v.push_back(test::MakeSingle<long long>(4));
441   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
442   // CHECK-FIXES: v.emplace_back(test::MakeSingle<long long>(4));
443   // We don't remove make functions with explicit template parameters.
444 
445   v.push_back(test::MakeSingle(5LL));
446   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
447   // CHECK-FIXES: v.emplace_back(5LL);
448 
449   v.push_back(std::make_tuple(6));
450   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
451   // CHECK-FIXES: v.emplace_back(6);
452 
453   v.push_back(std::make_tuple(7LL));
454   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
455   // CHECK-FIXES: v.emplace_back(7LL);
456 }
457 
testOtherContainers()458 void testOtherContainers() {
459   std::list<Something> l;
460   l.push_back(Something(42, 41));
461   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
462   // CHECK-FIXES: l.emplace_back(42, 41);
463 
464   std::deque<Something> d;
465   d.push_back(Something(42));
466   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
467   // CHECK-FIXES: d.emplace_back(42);
468 
469   llvm::LikeASmallVector<Something> ls;
470   ls.push_back(Something(42));
471   // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back
472   // CHECK-FIXES: ls.emplace_back(42);
473 }
474 
475 class IntWrapper {
476 public:
IntWrapper(int x)477   IntWrapper(int x) : value(x) {}
operator +(const IntWrapper other) const478   IntWrapper operator+(const IntWrapper other) const {
479     return IntWrapper(value + other.value);
480   }
481 
482 private:
483   int value;
484 };
485 
testMultipleOpsInPushBack()486 void testMultipleOpsInPushBack() {
487   std::vector<IntWrapper> v;
488   v.push_back(IntWrapper(42) + IntWrapper(27));
489 }
490 
491 // Macro tests.
492 #define PUSH_BACK_WHOLE(c, x) c.push_back(x)
493 #define PUSH_BACK_NAME push_back
494 #define PUSH_BACK_ARG(x) (x)
495 #define SOME_OBJ Something(10)
496 #define MILLION 3
497 #define SOME_WEIRD_PUSH(v) v.push_back(Something(
498 #define OPEN (
499 #define CLOSE )
macroTest()500 void macroTest() {
501   std::vector<Something> v;
502   Something s;
503 
504   PUSH_BACK_WHOLE(v, Something(5, 6));
505   // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back
506 
507   v.PUSH_BACK_NAME(Something(5));
508   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
509 
510   v.push_back PUSH_BACK_ARG(Something(5, 6));
511   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
512 
513   v.push_back(SOME_OBJ);
514   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
515 
516   v.push_back(Something(MILLION));
517   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
518   // CHECK-FIXES: v.emplace_back(MILLION);
519 
520   // clang-format off
521   v.push_back(  Something OPEN 3 CLOSE  );
522   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
523   // clang-format on
524   PUSH_BACK_WHOLE(s, Something(1));
525 }
526 
527 struct A {
528   int value1, value2;
529 };
530 
531 struct B {
BB532   B(A) {}
533 };
534 
535 struct C {
536   int value1, value2, value3;
537 };
538 
testAggregation()539 void testAggregation() {
540   // This should not be noticed or fixed; after the correction, the code won't
541   // compile.
542 
543   std::vector<A> v;
544   v.push_back(A({1, 2}));
545 
546   std::vector<B> vb;
547   vb.push_back(B({10, 42}));
548 }
549 
550 struct Bitfield {
551   unsigned bitfield : 1;
552   unsigned notBitfield;
553 };
554 
testBitfields()555 void testBitfields() {
556   std::vector<Something> v;
557   Bitfield b;
558   v.push_back(Something(42, b.bitfield));
559   v.push_back(Something(b.bitfield));
560 
561   v.push_back(Something(42, b.notBitfield));
562   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
563   // CHECK-FIXES: v.emplace_back(42, b.notBitfield);
564   int var;
565   v.push_back(Something(42, var));
566   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
567   // CHECK-FIXES: v.emplace_back(42, var);
568 }
569 
570 class PrivateCtor {
571   PrivateCtor(int z);
572 
573 public:
doStuff()574   void doStuff() {
575     std::vector<PrivateCtor> v;
576     // This should not change it because emplace back doesn't have permission.
577     // Check currently doesn't support friend declarations because pretty much
578     // nobody would want to be friend with std::vector :(.
579     v.push_back(PrivateCtor(42));
580   }
581 };
582 
583 struct WithDtor {
WithDtorWithDtor584   WithDtor(int) {}
585   ~WithDtor();
586 };
587 
testWithDtor()588 void testWithDtor() {
589   std::vector<WithDtor> v;
590 
591   v.push_back(WithDtor(42));
592   // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back
593   // CHECK-FIXES: v.emplace_back(42);
594 }
595 
testInitializerList()596 void testInitializerList() {
597   std::vector<std::vector<int>> v;
598   v.push_back(std::vector<int>({1}));
599   // Test against the bug reported in PR32896.
600 
601   v.push_back({{2}});
602 
603   using PairIntVector = std::pair<int, std::vector<int>>;
604   std::vector<PairIntVector> x;
605   x.push_back(PairIntVector(3, {4}));
606   x.push_back({5, {6}});
607 }
608