1 | // RUN: %check_clang_tidy %s modernize-use-emplace %t -- \ |
2 | // RUN: -config="{CheckOptions: \ |
3 | // RUN: {modernize-use-emplace.ContainersWithPushBack: \ |
4 | // RUN: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector', \ |
5 | // RUN: modernize-use-emplace.TupleTypes: \ |
6 | // RUN: '::std::pair; std::tuple; ::test::Single', \ |
7 | // RUN: modernize-use-emplace.TupleMakeFunctions: \ |
8 | // RUN: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}}" |
9 | |
10 | namespace std { |
11 | template <typename> |
12 | class initializer_list { |
13 | public: |
14 | initializer_list() noexcept {} |
15 | }; |
16 | |
17 | template <typename T1, typename T2> |
18 | class pair { |
19 | public: |
20 | pair() = default; |
21 | pair(const pair &) = default; |
22 | pair(pair &&) = default; |
23 | |
24 | pair(const T1 &, const T2 &) {} |
25 | pair(T1 &&, T2 &&) {} |
26 | |
27 | template <typename U1, typename U2> |
28 | pair(const pair<U1, U2> &){}; |
29 | template <typename U1, typename U2> |
30 | pair(pair<U1, U2> &&){}; |
31 | }; |
32 | |
33 | template <typename T> |
34 | class vector { |
35 | public: |
36 | using value_type = T; |
37 | |
38 | class iterator {}; |
39 | class const_iterator {}; |
40 | const_iterator begin() { return const_iterator{}; } |
41 | |
42 | vector() = default; |
43 | vector(initializer_list<T>) {} |
44 | |
45 | void push_back(const T &) {} |
46 | void push_back(T &&) {} |
47 | |
48 | template <typename... Args> |
49 | void emplace_back(Args &&... args){}; |
50 | template <typename... Args> |
51 | iterator emplace(const_iterator pos, Args &&...args){}; |
52 | ~vector(); |
53 | }; |
54 | |
55 | template <typename T> |
56 | class list { |
57 | public: |
58 | using value_type = T; |
59 | |
60 | class iterator {}; |
61 | class const_iterator {}; |
62 | const_iterator begin() { return const_iterator{}; } |
63 | |
64 | void push_front(const T &) {} |
65 | void push_front(T &&) {} |
66 | |
67 | void push_back(const T &) {} |
68 | void push_back(T &&) {} |
69 | |
70 | template <typename... Args> |
71 | iterator emplace(const_iterator pos, Args &&...args){}; |
72 | template <typename... Args> |
73 | void emplace_back(Args &&... args){}; |
74 | template <typename... Args> |
75 | void emplace_front(Args &&...args){}; |
76 | ~list(); |
77 | }; |
78 | |
79 | template <typename T> |
80 | class deque { |
81 | public: |
82 | using value_type = T; |
83 | |
84 | class iterator {}; |
85 | class const_iterator {}; |
86 | const_iterator begin() { return const_iterator{}; } |
87 | |
88 | void push_back(const T &) {} |
89 | void push_back(T &&) {} |
90 | |
91 | void push_front(const T &) {} |
92 | void push_front(T &&) {} |
93 | |
94 | template <typename... Args> |
95 | iterator emplace(const_iterator pos, Args &&...args){}; |
96 | template <typename... Args> |
97 | void emplace_back(Args &&... args){}; |
98 | template <typename... Args> |
99 | void emplace_front(Args &&...args){}; |
100 | ~deque(); |
101 | }; |
102 | |
103 | template <typename T> |
104 | class forward_list { |
105 | public: |
106 | using value_type = T; |
107 | |
108 | class iterator {}; |
109 | class const_iterator {}; |
110 | const_iterator begin() { return const_iterator{}; } |
111 | |
112 | void push_front(const T &) {} |
113 | void push_front(T &&) {} |
114 | |
115 | template <typename... Args> |
116 | void emplace_front(Args &&...args){}; |
117 | template <typename... Args> |
118 | iterator emplace_after(const_iterator pos, Args &&...args){}; |
119 | }; |
120 | |
121 | template <typename T> |
122 | class set { |
123 | public: |
124 | using value_type = T; |
125 | |
126 | class iterator {}; |
127 | class const_iterator {}; |
128 | const_iterator begin() { return const_iterator{}; } |
129 | |
130 | template <typename... Args> |
131 | void emplace(Args &&...args){}; |
132 | template <typename... Args> |
133 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
134 | }; |
135 | |
136 | template <typename Key, typename T> |
137 | class map { |
138 | public: |
139 | using value_type = std::pair<Key, T>; |
140 | |
141 | class iterator {}; |
142 | class const_iterator {}; |
143 | const_iterator begin() { return const_iterator{}; } |
144 | |
145 | template <typename... Args> |
146 | void emplace(Args &&...args){}; |
147 | template <typename... Args> |
148 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
149 | }; |
150 | |
151 | template <typename T> |
152 | class multiset { |
153 | public: |
154 | using value_type = T; |
155 | |
156 | class iterator {}; |
157 | class const_iterator {}; |
158 | const_iterator begin() { return const_iterator{}; } |
159 | |
160 | template <typename... Args> |
161 | void emplace(Args &&...args){}; |
162 | template <typename... Args> |
163 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
164 | }; |
165 | |
166 | template <typename Key, typename T> |
167 | class multimap { |
168 | public: |
169 | using value_type = std::pair<Key, T>; |
170 | |
171 | class iterator {}; |
172 | class const_iterator {}; |
173 | const_iterator begin() { return const_iterator{}; } |
174 | |
175 | template <typename... Args> |
176 | void emplace(Args &&...args){}; |
177 | template <typename... Args> |
178 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
179 | }; |
180 | |
181 | template <typename T> |
182 | class unordered_set { |
183 | public: |
184 | using value_type = T; |
185 | |
186 | class iterator {}; |
187 | class const_iterator {}; |
188 | const_iterator begin() { return const_iterator{}; } |
189 | |
190 | template <typename... Args> |
191 | void emplace(Args &&...args){}; |
192 | template <typename... Args> |
193 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
194 | }; |
195 | |
196 | template <typename Key, typename T> |
197 | class unordered_map { |
198 | public: |
199 | using value_type = std::pair<Key, T>; |
200 | |
201 | class iterator {}; |
202 | class const_iterator {}; |
203 | const_iterator begin() { return const_iterator{}; } |
204 | |
205 | template <typename... Args> |
206 | void emplace(Args &&...args){}; |
207 | template <typename... Args> |
208 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
209 | }; |
210 | |
211 | template <typename T> |
212 | class unordered_multiset { |
213 | public: |
214 | using value_type = T; |
215 | |
216 | class iterator {}; |
217 | class const_iterator {}; |
218 | const_iterator begin() { return const_iterator{}; } |
219 | |
220 | template <typename... Args> |
221 | void emplace(Args &&...args){}; |
222 | template <typename... Args> |
223 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
224 | }; |
225 | |
226 | template <typename Key, typename T> |
227 | class unordered_multimap { |
228 | public: |
229 | using value_type = std::pair<Key, T>; |
230 | |
231 | class iterator {}; |
232 | class const_iterator {}; |
233 | const_iterator begin() { return const_iterator{}; } |
234 | |
235 | template <typename... Args> |
236 | void emplace(Args &&...args){}; |
237 | template <typename... Args> |
238 | iterator emplace_hint(const_iterator pos, Args &&...args){}; |
239 | }; |
240 | |
241 | template <typename T> |
242 | class stack { |
243 | public: |
244 | using value_type = T; |
245 | |
246 | void push(const T &) {} |
247 | void push(T &&) {} |
248 | |
249 | template <typename... Args> |
250 | void emplace(Args &&...args){}; |
251 | }; |
252 | |
253 | template <typename T> |
254 | class queue { |
255 | public: |
256 | using value_type = T; |
257 | |
258 | void push(const T &) {} |
259 | void push(T &&) {} |
260 | |
261 | template <typename... Args> |
262 | void emplace(Args &&...args){}; |
263 | }; |
264 | |
265 | template <typename T> |
266 | class priority_queue { |
267 | public: |
268 | using value_type = T; |
269 | |
270 | void push(const T &) {} |
271 | void push(T &&) {} |
272 | |
273 | template <typename... Args> |
274 | void emplace(Args &&...args){}; |
275 | }; |
276 | |
277 | template <typename T> |
278 | struct remove_reference { using type = T; }; |
279 | template <typename T> |
280 | struct remove_reference<T &> { using type = T; }; |
281 | template <typename T> |
282 | struct remove_reference<T &&> { using type = T; }; |
283 | |
284 | template <typename T1, typename T2> |
285 | pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type> |
286 | make_pair(T1 &&, T2 &&) { |
287 | return {}; |
288 | }; |
289 | |
290 | template <typename... Ts> |
291 | class tuple { |
292 | public: |
293 | tuple() = default; |
294 | tuple(const tuple &) = default; |
295 | tuple(tuple &&) = default; |
296 | |
297 | tuple(const Ts &...) {} |
298 | tuple(Ts &&...) {} |
299 | |
300 | template <typename... Us> |
301 | tuple(const tuple<Us...> &){}; |
302 | template <typename... Us> |
303 | tuple(tuple<Us...> &&) {} |
304 | |
305 | template <typename U1, typename U2> |
306 | tuple(const pair<U1, U2> &) { |
307 | static_assert(sizeof...(Ts) == 2, "Wrong tuple size" ); |
308 | }; |
309 | template <typename U1, typename U2> |
310 | tuple(pair<U1, U2> &&) { |
311 | static_assert(sizeof...(Ts) == 2, "Wrong tuple size" ); |
312 | }; |
313 | }; |
314 | |
315 | template <typename... Ts> |
316 | tuple<typename remove_reference<Ts>::type...> make_tuple(Ts &&...) { |
317 | return {}; |
318 | } |
319 | |
320 | template <typename T> |
321 | class unique_ptr { |
322 | public: |
323 | explicit unique_ptr(T *) {} |
324 | ~unique_ptr(); |
325 | }; |
326 | } // namespace std |
327 | |
328 | namespace llvm { |
329 | template <typename T> |
330 | class LikeASmallVector { |
331 | public: |
332 | void push_back(const T &) {} |
333 | void push_back(T &&) {} |
334 | |
335 | template <typename... Args> |
336 | void emplace_back(Args &&... args){}; |
337 | }; |
338 | |
339 | } // namespace llvm |
340 | |
341 | void testInts() { |
342 | std::vector<int> v; |
343 | v.push_back(42); |
344 | v.push_back(int(42)); |
345 | v.push_back(int{42}); |
346 | v.push_back(42.0); |
347 | int z; |
348 | v.push_back(z); |
349 | } |
350 | |
351 | struct Something { |
352 | Something(int a, int b = 41) {} |
353 | Something() {} |
354 | void push_back(Something); |
355 | int getInt() { return 42; } |
356 | }; |
357 | |
358 | struct Convertable { |
359 | operator Something() { return Something{}; } |
360 | }; |
361 | |
362 | struct Zoz { |
363 | Zoz(Something, int = 42) {} |
364 | }; |
365 | |
366 | Zoz getZoz(Something s) { return Zoz(s); } |
367 | |
368 | void test_Something() { |
369 | std::vector<Something> v; |
370 | |
371 | v.push_back(Something(1, 2)); |
372 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace] |
373 | // CHECK-FIXES: v.emplace_back(1, 2); |
374 | |
375 | v.push_back(Something{1, 2}); |
376 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
377 | // CHECK-FIXES: v.emplace_back(1, 2); |
378 | |
379 | v.push_back(Something()); |
380 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
381 | // CHECK-FIXES: v.emplace_back(); |
382 | |
383 | v.push_back(Something{}); |
384 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
385 | // CHECK-FIXES: v.emplace_back(); |
386 | |
387 | Something Different; |
388 | v.push_back(Something(Different.getInt(), 42)); |
389 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
390 | // CHECK-FIXES: v.emplace_back(Different.getInt(), 42); |
391 | |
392 | v.push_back(Different.getInt()); |
393 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
394 | // CHECK-FIXES: v.emplace_back(Different.getInt()); |
395 | |
396 | v.push_back(42); |
397 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
398 | // CHECK-FIXES: v.emplace_back(42); |
399 | |
400 | Something temporary(42, 42); |
401 | temporary.push_back(temporary); |
402 | v.push_back(temporary); |
403 | |
404 | v.push_back(Convertable()); |
405 | v.push_back(Convertable{}); |
406 | Convertable s; |
407 | v.push_back(s); |
408 | } |
409 | |
410 | template <typename ElemType> |
411 | void dependOnElem() { |
412 | std::vector<ElemType> v; |
413 | v.push_back(ElemType(42)); |
414 | } |
415 | |
416 | template <typename ContainerType> |
417 | void dependOnContainer() { |
418 | ContainerType v; |
419 | v.push_back(Something(42)); |
420 | } |
421 | |
422 | void callDependent() { |
423 | dependOnElem<Something>(); |
424 | dependOnContainer<std::vector<Something>>(); |
425 | } |
426 | |
427 | void test2() { |
428 | std::vector<Zoz> v; |
429 | v.push_back(Zoz(Something(21, 37))); |
430 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
431 | // CHECK-FIXES: v.emplace_back(Something(21, 37)); |
432 | |
433 | v.push_back(Zoz(Something(21, 37), 42)); |
434 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
435 | // CHECK-FIXES: v.emplace_back(Something(21, 37), 42); |
436 | |
437 | v.push_back(getZoz(s: Something(1, 2))); |
438 | } |
439 | |
440 | struct GetPair { |
441 | std::pair<int, long> getPair(); |
442 | }; |
443 | void testPair() { |
444 | std::vector<std::pair<int, int>> v; |
445 | v.push_back(std::pair<int, int>(1, 2)); |
446 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
447 | // CHECK-FIXES: v.emplace_back(1, 2); |
448 | |
449 | GetPair g; |
450 | v.push_back(g.getPair()); |
451 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
452 | // CHECK-FIXES: v.emplace_back(g.getPair()); |
453 | |
454 | std::vector<std::pair<Something, Zoz>> v2; |
455 | v2.push_back(std::pair<Something, Zoz>(Something(42, 42), Zoz(Something(21, 37)))); |
456 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
457 | // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37))); |
458 | } |
459 | |
460 | void testTuple() { |
461 | std::vector<std::tuple<bool, char, int>> v; |
462 | v.push_back(std::tuple<bool, char, int>(false, 'x', 1)); |
463 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
464 | // CHECK-FIXES: v.emplace_back(false, 'x', 1); |
465 | |
466 | v.push_back(std::tuple<bool, char, int>{false, 'y', 2}); |
467 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
468 | // CHECK-FIXES: v.emplace_back(false, 'y', 2); |
469 | |
470 | v.push_back({true, 'z', 3}); |
471 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
472 | // CHECK-FIXES: v.emplace_back(true, 'z', 3); |
473 | |
474 | std::vector<std::tuple<int, bool>> x; |
475 | x.push_back(std::make_pair(1, false)); |
476 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
477 | // CHECK-FIXES: x.emplace_back(1, false); |
478 | |
479 | x.push_back(std::make_pair(2LL, 1)); |
480 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
481 | // CHECK-FIXES: x.emplace_back(2LL, 1); |
482 | } |
483 | |
484 | struct Base { |
485 | Base(int, int *, int = 42); |
486 | }; |
487 | |
488 | struct Derived : Base { |
489 | Derived(int *, Something) : Base(42, nullptr) {} |
490 | }; |
491 | |
492 | void testDerived() { |
493 | std::vector<Base> v; |
494 | v.push_back(Derived(nullptr, Something{})); |
495 | } |
496 | |
497 | void testNewExpr() { |
498 | std::vector<Derived> v; |
499 | v.push_back(Derived(new int, Something{})); |
500 | } |
501 | |
502 | void testSpaces() { |
503 | std::vector<Something> v; |
504 | |
505 | // clang-format off |
506 | |
507 | v.push_back(Something(1, //arg1 |
508 | 2 // arg2 |
509 | ) // Something |
510 | ); |
511 | // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back |
512 | // CHECK-FIXES: v.emplace_back(1, //arg1 |
513 | // CHECK-FIXES: 2 // arg2 |
514 | // CHECK-FIXES: // Something |
515 | // CHECK-FIXES: ); |
516 | |
517 | v.push_back( Something (1, 2) ); |
518 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
519 | // CHECK-FIXES: v.emplace_back(1, 2 ); |
520 | |
521 | v.push_back( Something {1, 2} ); |
522 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
523 | // CHECK-FIXES: v.emplace_back(1, 2 ); |
524 | |
525 | v.push_back( Something {} ); |
526 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
527 | // CHECK-FIXES: v.emplace_back( ); |
528 | |
529 | v.push_back( |
530 | Something(1, 2) ); |
531 | // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back |
532 | // CHECK-FIXES: v.emplace_back(1, 2 ); |
533 | |
534 | std::vector<Base> v2; |
535 | v2.push_back( |
536 | Base(42, nullptr)); |
537 | // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back |
538 | // CHECK-FIXES: v2.emplace_back(42, nullptr); |
539 | |
540 | // clang-format on |
541 | } |
542 | |
543 | void testPointers() { |
544 | std::vector<int *> v; |
545 | v.push_back(new int(5)); |
546 | |
547 | std::vector<std::unique_ptr<int>> v2; |
548 | v2.push_back(std::unique_ptr<int>(new int(42))); |
549 | // This call can't be replaced with emplace_back. |
550 | // If emplacement will fail (not enough memory to add to vector) |
551 | // we will have leak of int because unique_ptr won't be constructed |
552 | // (and destructed) as in push_back case. |
553 | |
554 | auto *ptr = new int; |
555 | v2.push_back(std::unique_ptr<int>(ptr)); |
556 | // Same here |
557 | } |
558 | |
559 | void testMakePair() { |
560 | std::vector<std::pair<int, int>> v; |
561 | v.push_back(std::make_pair(1, 2)); |
562 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
563 | // CHECK-FIXES: v.emplace_back(1, 2); |
564 | |
565 | v.push_back(std::make_pair(42LL, 13)); |
566 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
567 | // CHECK-FIXES: v.emplace_back(42LL, 13); |
568 | |
569 | v.push_back(std::make_pair<char, char>(0, 3)); |
570 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
571 | // CHECK-FIXES: v.emplace_back(std::make_pair<char, char>(0, 3)); |
572 | // |
573 | // Even though the call above could be turned into v.emplace_back(0, 3), |
574 | // we don't eliminate the make_pair call here, because of the explicit |
575 | // template parameters provided. make_pair's arguments can be convertible |
576 | // to its explicitly provided template parameter, but not to the pair's |
577 | // element type. The examples below illustrate the problem. |
578 | struct D { |
579 | D(...) {} |
580 | operator char() const { return 0; } |
581 | }; |
582 | v.push_back(std::make_pair<D, int>(Something(), 2)); |
583 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
584 | // CHECK-FIXES: v.emplace_back(std::make_pair<D, int>(Something(), 2)); |
585 | |
586 | struct X { |
587 | X(std::pair<int, int>) {} |
588 | }; |
589 | std::vector<X> x; |
590 | x.push_back(std::make_pair(1, 2)); |
591 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
592 | // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2)); |
593 | // make_pair cannot be removed here, as X is not constructible with two ints. |
594 | |
595 | struct Y { |
596 | Y(std::pair<int, int> &&) {} |
597 | }; |
598 | std::vector<Y> y; |
599 | y.push_back(std::make_pair(2, 3)); |
600 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
601 | // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3)); |
602 | // make_pair cannot be removed here, as Y is not constructible with two ints. |
603 | } |
604 | |
605 | void testMakeTuple() { |
606 | std::vector<std::tuple<int, bool, char>> v; |
607 | v.push_back(std::make_tuple(1, true, 'v')); |
608 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
609 | // CHECK-FIXES: v.emplace_back(1, true, 'v'); |
610 | |
611 | v.push_back(std::make_tuple(2ULL, 1, 0)); |
612 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
613 | // CHECK-FIXES: v.emplace_back(2ULL, 1, 0); |
614 | |
615 | v.push_back(std::make_tuple<long long, int, int>(3LL, 1, 0)); |
616 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
617 | // CHECK-FIXES: v.emplace_back(std::make_tuple<long long, int, int>(3LL, 1, 0)); |
618 | // make_tuple is not removed when there are explicit template |
619 | // arguments provided. |
620 | } |
621 | |
622 | namespace test { |
623 | template <typename T> |
624 | struct Single { |
625 | Single() = default; |
626 | Single(const Single &) = default; |
627 | Single(Single &&) = default; |
628 | |
629 | Single(const T &) {} |
630 | Single(T &&) {} |
631 | |
632 | template <typename U> |
633 | Single(const Single<U> &) {} |
634 | template <typename U> |
635 | Single(Single<U> &&) {} |
636 | |
637 | template <typename U> |
638 | Single(const std::tuple<U> &) {} |
639 | template <typename U> |
640 | Single(std::tuple<U> &&) {} |
641 | }; |
642 | |
643 | template <typename T> |
644 | Single<typename std::remove_reference<T>::type> MakeSingle(T &&) { |
645 | return {}; |
646 | } |
647 | } // namespace test |
648 | |
649 | void testOtherTuples() { |
650 | std::vector<test::Single<int>> v; |
651 | v.push_back(test::Single<int>(1)); |
652 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
653 | // CHECK-FIXES: v.emplace_back(1); |
654 | |
655 | v.push_back({2}); |
656 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
657 | // CHECK-FIXES: v.emplace_back(2); |
658 | |
659 | v.push_back(test::MakeSingle(3)); |
660 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
661 | // CHECK-FIXES: v.emplace_back(3); |
662 | |
663 | v.push_back(test::MakeSingle<long long>(4)); |
664 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
665 | // CHECK-FIXES: v.emplace_back(test::MakeSingle<long long>(4)); |
666 | // We don't remove make functions with explicit template parameters. |
667 | |
668 | v.push_back(test::MakeSingle(5LL)); |
669 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
670 | // CHECK-FIXES: v.emplace_back(5LL); |
671 | |
672 | v.push_back(std::make_tuple(6)); |
673 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
674 | // CHECK-FIXES: v.emplace_back(6); |
675 | |
676 | v.push_back(std::make_tuple(7LL)); |
677 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
678 | // CHECK-FIXES: v.emplace_back(7LL); |
679 | } |
680 | |
681 | void testOtherContainers() { |
682 | std::list<Something> l; |
683 | l.push_back(Something(42, 41)); |
684 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
685 | // CHECK-FIXES: l.emplace_back(42, 41); |
686 | |
687 | l.push_front(Something(42, 41)); |
688 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_front |
689 | // CHECK-FIXES: l.emplace_front(42, 41); |
690 | |
691 | std::deque<Something> d; |
692 | d.push_back(Something(42)); |
693 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
694 | // CHECK-FIXES: d.emplace_back(42); |
695 | |
696 | d.push_front(Something(42)); |
697 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_front |
698 | // CHECK-FIXES: d.emplace_front(42); |
699 | |
700 | llvm::LikeASmallVector<Something> ls; |
701 | ls.push_back(Something(42)); |
702 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
703 | // CHECK-FIXES: ls.emplace_back(42); |
704 | |
705 | std::stack<Something> s; |
706 | s.push(Something(42, 41)); |
707 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace |
708 | // CHECK-FIXES: s.emplace(42, 41); |
709 | |
710 | std::queue<Something> q; |
711 | q.push(Something(42, 41)); |
712 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace |
713 | // CHECK-FIXES: q.emplace(42, 41); |
714 | |
715 | std::priority_queue<Something> pq; |
716 | pq.push(Something(42, 41)); |
717 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace |
718 | // CHECK-FIXES: pq.emplace(42, 41); |
719 | |
720 | std::forward_list<Something> fl; |
721 | fl.push_front(Something(42, 41)); |
722 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_front |
723 | // CHECK-FIXES: fl.emplace_front(42, 41); |
724 | } |
725 | |
726 | class IntWrapper { |
727 | public: |
728 | IntWrapper(int x) : value(x) {} |
729 | IntWrapper operator+(const IntWrapper other) const { |
730 | return IntWrapper(value + other.value); |
731 | } |
732 | |
733 | private: |
734 | int value; |
735 | }; |
736 | |
737 | void testMultipleOpsInPushBack() { |
738 | std::vector<IntWrapper> v; |
739 | v.push_back(IntWrapper(42) + IntWrapper(27)); |
740 | } |
741 | |
742 | // Macro tests. |
743 | #define PUSH_BACK_WHOLE(c, x) c.push_back(x) |
744 | #define PUSH_BACK_NAME push_back |
745 | #define PUSH_BACK_ARG(x) (x) |
746 | #define SOME_OBJ Something(10) |
747 | #define MILLION 3 |
748 | #define SOME_WEIRD_PUSH(v) v.push_back(Something( |
749 | #define OPEN ( |
750 | #define CLOSE ) |
751 | void macroTest() { |
752 | std::vector<Something> v; |
753 | Something s; |
754 | |
755 | PUSH_BACK_WHOLE(v, Something(5, 6)); |
756 | // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back |
757 | |
758 | v.PUSH_BACK_NAME(Something(5)); |
759 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
760 | |
761 | v.push_back PUSH_BACK_ARG(Something(5, 6)); |
762 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
763 | |
764 | v.push_back(SOME_OBJ); |
765 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
766 | |
767 | v.push_back(Something(MILLION)); |
768 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
769 | // CHECK-FIXES: v.emplace_back(MILLION); |
770 | |
771 | // clang-format off |
772 | v.push_back( Something OPEN 3 CLOSE ); |
773 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
774 | // clang-format on |
775 | PUSH_BACK_WHOLE(s, Something(1)); |
776 | } |
777 | |
778 | struct A { |
779 | int value1, value2; |
780 | }; |
781 | |
782 | struct B { |
783 | B(A) {} |
784 | }; |
785 | |
786 | struct C { |
787 | int value1, value2, value3; |
788 | }; |
789 | |
790 | void testAggregation() { |
791 | // This should not be noticed or fixed; after the correction, the code won't |
792 | // compile. |
793 | |
794 | std::vector<A> v; |
795 | v.push_back(A({.value1: 1, .value2: 2})); |
796 | |
797 | std::vector<B> vb; |
798 | vb.push_back(B({.value1: 10, .value2: 42})); |
799 | } |
800 | |
801 | struct Bitfield { |
802 | unsigned bitfield : 1; |
803 | unsigned notBitfield; |
804 | }; |
805 | |
806 | void testBitfields() { |
807 | std::vector<Something> v; |
808 | Bitfield b; |
809 | v.push_back(Something(42, b.bitfield)); |
810 | v.push_back(Something(b.bitfield)); |
811 | |
812 | v.push_back(Something(42, b.notBitfield)); |
813 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
814 | // CHECK-FIXES: v.emplace_back(42, b.notBitfield); |
815 | int var; |
816 | v.push_back(Something(42, var)); |
817 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
818 | // CHECK-FIXES: v.emplace_back(42, var); |
819 | } |
820 | |
821 | class PrivateCtor { |
822 | PrivateCtor(int z); |
823 | |
824 | public: |
825 | void doStuff() { |
826 | std::vector<PrivateCtor> v; |
827 | // This should not change it because emplace back doesn't have permission. |
828 | // Check currently doesn't support friend declarations because pretty much |
829 | // nobody would want to be friend with std::vector :(. |
830 | v.push_back(PrivateCtor(42)); |
831 | } |
832 | }; |
833 | |
834 | struct WithDtor { |
835 | WithDtor(int) {} |
836 | ~WithDtor(); |
837 | }; |
838 | |
839 | void testWithDtor() { |
840 | std::vector<WithDtor> v; |
841 | |
842 | v.push_back(WithDtor(42)); |
843 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back |
844 | // CHECK-FIXES: v.emplace_back(42); |
845 | } |
846 | |
847 | void testInitializerList() { |
848 | std::vector<std::vector<int>> v; |
849 | v.push_back(std::vector<int>({1})); |
850 | // Test against the bug reported in PR32896. |
851 | |
852 | v.push_back({{2}}); |
853 | |
854 | using PairIntVector = std::pair<int, std::vector<int>>; |
855 | std::vector<PairIntVector> x; |
856 | x.push_back(PairIntVector(3, {4})); |
857 | x.push_back({5, {6}}); |
858 | } |
859 | |
860 | class Foo { |
861 | public: |
862 | Foo(){}; |
863 | Foo(int){}; |
864 | Foo(int, int){}; |
865 | Foo(std::pair<int, int>){}; |
866 | |
867 | protected: |
868 | Foo(char *) : Foo(){}; |
869 | }; |
870 | |
871 | void testSomeEmplaceCases() { |
872 | std::vector<std::pair<char *, char *>> v1; |
873 | std::vector<Foo> v2; |
874 | std::unordered_map<int, char *> m1; |
875 | |
876 | v1.emplace_back(args: std::make_pair("foo" , "bar" )); |
877 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
878 | // CHECK-FIXES: v1.emplace_back("foo", "bar"); |
879 | |
880 | char *foo = "bar" ; |
881 | v1.emplace_back(args: std::make_pair(foo, "bar" )); |
882 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
883 | // CHECK-FIXES: v1.emplace_back(foo, "bar"); |
884 | |
885 | v1.emplace(pos: v1.begin(), args: std::make_pair("foo" , "bar" )); |
886 | // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace |
887 | // CHECK-FIXES: v1.emplace(v1.begin(), "foo", "bar"); |
888 | |
889 | v2.emplace_back(args: Foo()); |
890 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
891 | // CHECK-FIXES: v2.emplace_back(); |
892 | |
893 | v2.emplace_back(args: Foo(13)); |
894 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
895 | // CHECK-FIXES: v2.emplace_back(13); |
896 | |
897 | v2.emplace_back(args: Foo{13}); |
898 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
899 | // CHECK-FIXES: v2.emplace_back(13); |
900 | |
901 | int a = 31; |
902 | v2.emplace_back(args: Foo(13, a)); |
903 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
904 | // CHECK-FIXES: v2.emplace_back(13, a); |
905 | |
906 | v2.emplace_back(args: std::make_pair(3, 3)); |
907 | |
908 | m1.emplace(args: std::make_pair(13, "foo" )); |
909 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace |
910 | // CHECK-FIXES: m1.emplace(13, "foo"); |
911 | |
912 | std::vector<std::pair<int, int>> v3; |
913 | v3.emplace_back(args: std::pair<int, int>(13, 71)); |
914 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
915 | v3.emplace_back(args: std::make_pair(13, 71)); |
916 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
917 | |
918 | std::vector<std::tuple<int, int, int>> v4; |
919 | v4.emplace_back(args: std::tuple<int, int, int>(13, 31, 71)); |
920 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
921 | v4.emplace_back(args: std::make_tuple(13, 31, 71)); |
922 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
923 | |
924 | std::vector<test::Single<int>> v5; |
925 | v5.emplace_back(args: test::Single<int>(13)); |
926 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
927 | v5.emplace_back(args: test::MakeSingle(13)); |
928 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
929 | } |
930 | |
931 | void testAllSTLEmplacyFunctions() { |
932 | std::vector<Foo> vector; |
933 | std::deque<Foo> deque; |
934 | std::forward_list<Foo> forward_list; |
935 | std::list<Foo> list; |
936 | std::set<Foo> set; |
937 | std::map<int, Foo> map; |
938 | std::multiset<Foo> multiset; |
939 | std::multimap<int, Foo> multimap; |
940 | std::unordered_set<Foo> unordered_set; |
941 | std::unordered_map<int, Foo> unordered_map; |
942 | std::unordered_multiset<Foo> unordered_multiset; |
943 | std::unordered_multimap<int, Foo> unordered_multimap; |
944 | std::stack<Foo> stack; |
945 | std::queue<Foo> queue; |
946 | std::priority_queue<Foo> priority_queue; |
947 | |
948 | vector.emplace_back(args: Foo(13)); |
949 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_back |
950 | // CHECK-FIXES: vector.emplace_back(13); |
951 | |
952 | vector.emplace(pos: vector.begin(), args: Foo(13)); |
953 | // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: unnecessary temporary object created while calling emplace |
954 | // CHECK-FIXES: vector.emplace(vector.begin(), 13); |
955 | |
956 | deque.emplace(pos: deque.begin(), args: Foo(13)); |
957 | // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: unnecessary temporary object created while calling emplace |
958 | // CHECK-FIXES: deque.emplace(deque.begin(), 13); |
959 | |
960 | deque.emplace_front(args: Foo(13)); |
961 | // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_front |
962 | // CHECK-FIXES: deque.emplace_front(13); |
963 | |
964 | deque.emplace_back(args: Foo(13)); |
965 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_back |
966 | // CHECK-FIXES: deque.emplace_back(13); |
967 | |
968 | forward_list.emplace_after(pos: forward_list.begin(), args: Foo(13)); |
969 | // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: unnecessary temporary object created while calling emplace_after |
970 | // CHECK-FIXES: forward_list.emplace_after(forward_list.begin(), 13); |
971 | |
972 | forward_list.emplace_front(args: Foo(13)); |
973 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace_front |
974 | // CHECK-FIXES: forward_list.emplace_front(13); |
975 | |
976 | list.emplace(pos: list.begin(), args: Foo(13)); |
977 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace |
978 | // CHECK-FIXES: list.emplace(list.begin(), 13); |
979 | |
980 | list.emplace_back(args: Foo(13)); |
981 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_back |
982 | // CHECK-FIXES: list.emplace_back(13); |
983 | |
984 | list.emplace_front(args: Foo(13)); |
985 | // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_front |
986 | // CHECK-FIXES: list.emplace_front(13); |
987 | |
988 | set.emplace(args: Foo(13)); |
989 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
990 | // CHECK-FIXES: set.emplace(13); |
991 | |
992 | set.emplace_hint(pos: set.begin(), args: Foo(13)); |
993 | // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint |
994 | // CHECK-FIXES: set.emplace_hint(set.begin(), 13); |
995 | |
996 | map.emplace(args: std::make_pair(13, Foo(13))); |
997 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
998 | // CHECK-FIXES: map.emplace(13, Foo(13)); |
999 | |
1000 | map.emplace_hint(pos: map.begin(), args: std::make_pair(13, Foo(13))); |
1001 | // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint |
1002 | // CHECK-FIXES: map.emplace_hint(map.begin(), 13, Foo(13)); |
1003 | |
1004 | multiset.emplace(args: Foo(13)); |
1005 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace |
1006 | // CHECK-FIXES: multiset.emplace(13); |
1007 | |
1008 | multiset.emplace_hint(pos: multiset.begin(), args: Foo(13)); |
1009 | // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint |
1010 | // CHECK-FIXES: multiset.emplace_hint(multiset.begin(), 13); |
1011 | |
1012 | multimap.emplace(args: std::make_pair(13, Foo(13))); |
1013 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace |
1014 | // CHECK-FIXES: multimap.emplace(13, Foo(13)); |
1015 | |
1016 | multimap.emplace_hint(pos: multimap.begin(), args: std::make_pair(13, Foo(13))); |
1017 | // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint |
1018 | // CHECK-FIXES: multimap.emplace_hint(multimap.begin(), 13, Foo(13)); |
1019 | |
1020 | unordered_set.emplace(args: Foo(13)); |
1021 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace |
1022 | // CHECK-FIXES: unordered_set.emplace(13); |
1023 | |
1024 | unordered_set.emplace_hint(pos: unordered_set.begin(), args: Foo(13)); |
1025 | // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint |
1026 | // CHECK-FIXES: unordered_set.emplace_hint(unordered_set.begin(), 13); |
1027 | |
1028 | unordered_map.emplace(args: std::make_pair(13, Foo(13))); |
1029 | // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace |
1030 | // CHECK-FIXES: unordered_map.emplace(13, Foo(13)); |
1031 | |
1032 | unordered_map.emplace_hint(pos: unordered_map.begin(), args: std::make_pair(13, Foo(13))); |
1033 | // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint |
1034 | // CHECK-FIXES: unordered_map.emplace_hint(unordered_map.begin(), 13, Foo(13)); |
1035 | |
1036 | unordered_multiset.emplace(args: Foo(13)); |
1037 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace |
1038 | // CHECK-FIXES: unordered_multiset.emplace(13); |
1039 | unordered_multiset.emplace_hint(pos: unordered_multiset.begin(), args: Foo(13)); |
1040 | // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint |
1041 | // CHECK-FIXES: unordered_multiset.emplace_hint(unordered_multiset.begin(), 13); |
1042 | |
1043 | unordered_multimap.emplace(args: std::make_pair(13, Foo(13))); |
1044 | // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace |
1045 | // CHECK-FIXES: unordered_multimap.emplace(13, Foo(13)); |
1046 | unordered_multimap.emplace_hint(pos: unordered_multimap.begin(), args: std::make_pair(13, Foo(13))); |
1047 | // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint |
1048 | // CHECK-FIXES: unordered_multimap.emplace_hint(unordered_multimap.begin(), 13, Foo(13)); |
1049 | |
1050 | stack.emplace(args: Foo(13)); |
1051 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace |
1052 | // CHECK-FIXES: stack.emplace(13); |
1053 | |
1054 | queue.emplace(args: Foo(13)); |
1055 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace |
1056 | // CHECK-FIXES: queue.emplace(13); |
1057 | |
1058 | priority_queue.emplace(args: Foo(13)); |
1059 | // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace |
1060 | // CHECK-FIXES: priority_queue.emplace(13); |
1061 | } |
1062 | |
1063 | void test_AliasEmplacyFunctions() { |
1064 | typedef std::list<Foo> L; |
1065 | using DQ = std::deque<Foo>; |
1066 | L l; |
1067 | l.emplace_back(args: Foo(3)); |
1068 | // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unnecessary temporary object created while calling emplace_back |
1069 | // CHECK-FIXES: l.emplace_back(3); |
1070 | |
1071 | DQ dq; |
1072 | dq.emplace_back(args: Foo(3)); |
1073 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1074 | // CHECK-FIXES: dq.emplace_back(3); |
1075 | |
1076 | typedef std::stack<Foo> STACK; |
1077 | using PQ = std::priority_queue<Foo>; |
1078 | STACK stack; |
1079 | stack.emplace(args: Foo(3)); |
1080 | // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace |
1081 | // CHECK-FIXES: stack.emplace(3); |
1082 | |
1083 | PQ pq; |
1084 | pq.emplace(args: Foo(3)); |
1085 | // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace |
1086 | // CHECK-FIXES: pq.emplace(3); |
1087 | |
1088 | typedef std::forward_list<Foo> FL; |
1089 | using DQ2 = std::deque<Foo>; |
1090 | FL fl; |
1091 | fl.emplace_front(args: Foo(3)); |
1092 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_front |
1093 | // CHECK-FIXES: fl.emplace_front(3); |
1094 | |
1095 | DQ2 dq2; |
1096 | dq2.emplace_front(args: Foo(3)); |
1097 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front |
1098 | // CHECK-FIXES: dq2.emplace_front(3); |
1099 | } |
1100 | |
1101 | void test_Alias() { |
1102 | typedef std::list<Foo> L; |
1103 | using DQ = std::deque<Foo>; |
1104 | L l; |
1105 | l.push_back(Foo(3)); |
1106 | // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1107 | // CHECK-FIXES: l.emplace_back(3); |
1108 | |
1109 | DQ dq; |
1110 | dq.push_back(Foo(3)); |
1111 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1112 | // CHECK-FIXES: dq.emplace_back(3); |
1113 | |
1114 | typedef std::stack<Foo> STACK; |
1115 | using PQ = std::priority_queue<Foo>; |
1116 | STACK stack; |
1117 | stack.push(Foo(3)); |
1118 | // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use emplace instead of push [modernize-use-emplace] |
1119 | // CHECK-FIXES: stack.emplace(3); |
1120 | |
1121 | PQ pq; |
1122 | pq.push(Foo(3)); |
1123 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace instead of push [modernize-use-emplace] |
1124 | // CHECK-FIXES: pq.emplace(3); |
1125 | |
1126 | typedef std::forward_list<Foo> FL; |
1127 | using DQ2 = std::deque<Foo>; |
1128 | FL fl; |
1129 | fl.push_front(Foo(3)); |
1130 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1131 | // CHECK-FIXES: fl.emplace_front(3); |
1132 | |
1133 | DQ2 dq2; |
1134 | dq2.push_front(Foo(3)); |
1135 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1136 | // CHECK-FIXES: dq2.emplace_front(3); |
1137 | } |
1138 | |
1139 | struct Bar { |
1140 | public: |
1141 | Bar(){}; |
1142 | void testWithPrivateAndProtectedCtor() { |
1143 | std::vector<Bar> vec; |
1144 | |
1145 | vec.emplace_back(args: Bar(13)); |
1146 | vec.emplace_back(args: Bar(13, 13)); |
1147 | } |
1148 | |
1149 | protected: |
1150 | Bar(int){}; |
1151 | |
1152 | private: |
1153 | Bar(int, int){}; |
1154 | }; |
1155 | |
1156 | void testPossibleFalsePositives() { |
1157 | struct Y { |
1158 | Y(std::pair<int, int> &&) {} |
1159 | }; |
1160 | std::vector<Y> y; |
1161 | y.emplace_back(args: std::make_pair(2, 3)); |
1162 | |
1163 | std::vector<std::pair<int, int>> v; |
1164 | v.emplace_back(args: std::make_pair<char, char>(0, 3)); |
1165 | |
1166 | struct D { |
1167 | D(...) {} |
1168 | operator char() const { return 0; } |
1169 | }; |
1170 | v.emplace_back(args: std::make_pair<D, int>(Something(), 2)); |
1171 | } |
1172 | |
1173 | struct InnerType { |
1174 | InnerType(); |
1175 | InnerType(char const*); |
1176 | }; |
1177 | |
1178 | struct NonTrivialNoCtor { |
1179 | InnerType it; |
1180 | }; |
1181 | |
1182 | struct NonTrivialWithVector { |
1183 | std::vector<int> it; |
1184 | }; |
1185 | |
1186 | struct NonTrivialWithIntAndVector { |
1187 | int x; |
1188 | std::vector<int> it; |
1189 | }; |
1190 | |
1191 | struct NonTrivialWithCtor { |
1192 | NonTrivialWithCtor(); |
1193 | NonTrivialWithCtor(std::vector<int> const&); |
1194 | }; |
1195 | |
1196 | void testBracedInitTemporaries() { |
1197 | std::vector<NonTrivialNoCtor> v1; |
1198 | |
1199 | v1.push_back(NonTrivialNoCtor()); |
1200 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1201 | // CHECK-FIXES: v1.emplace_back(); |
1202 | v1.push_back(NonTrivialNoCtor{}); |
1203 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1204 | // CHECK-FIXES: v1.emplace_back(); |
1205 | v1.push_back({}); |
1206 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1207 | // CHECK-FIXES: v1.emplace_back(); |
1208 | v1.push_back(NonTrivialNoCtor{.it: InnerType{}}); |
1209 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1210 | // CHECK-FIXES: v1.emplace_back(); |
1211 | v1.push_back({.it: InnerType{}}); |
1212 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1213 | // CHECK-FIXES: v1.emplace_back(); |
1214 | v1.push_back(NonTrivialNoCtor{.it: InnerType()}); |
1215 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1216 | // CHECK-FIXES: v1.emplace_back(); |
1217 | v1.push_back({.it: InnerType()}); |
1218 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1219 | // CHECK-FIXES: v1.emplace_back(); |
1220 | v1.push_back({.it: {}}); |
1221 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1222 | // CHECK-FIXES: v1.emplace_back(); |
1223 | |
1224 | v1.emplace_back(args: NonTrivialNoCtor()); |
1225 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1226 | // CHECK-FIXES: v1.emplace_back(); |
1227 | v1.emplace_back(args: NonTrivialNoCtor{}); |
1228 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1229 | // CHECK-FIXES: v1.emplace_back(); |
1230 | v1.emplace_back(args: NonTrivialNoCtor{.it: InnerType{}}); |
1231 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1232 | // CHECK-FIXES: v1.emplace_back(); |
1233 | v1.emplace_back(args: NonTrivialNoCtor{.it: {}}); |
1234 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1235 | // CHECK-FIXES: v1.emplace_back(); |
1236 | |
1237 | // These should not be noticed or fixed; after the correction, the code won't |
1238 | // compile. |
1239 | v1.push_back(NonTrivialNoCtor{.it: "" }); |
1240 | v1.push_back({.it: "" }); |
1241 | v1.push_back(NonTrivialNoCtor{.it: InnerType{"" }}); |
1242 | v1.push_back({.it: InnerType{"" }}); |
1243 | v1.emplace_back(args: NonTrivialNoCtor{.it: "" }); |
1244 | |
1245 | std::vector<NonTrivialWithVector> v2; |
1246 | |
1247 | v2.push_back(NonTrivialWithVector()); |
1248 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1249 | // CHECK-FIXES: v2.emplace_back(); |
1250 | v2.push_back(NonTrivialWithVector{}); |
1251 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1252 | // CHECK-FIXES: v2.emplace_back(); |
1253 | v2.push_back({}); |
1254 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1255 | // CHECK-FIXES: v2.emplace_back(); |
1256 | v2.push_back(NonTrivialWithVector{.it: std::vector<int>{}}); |
1257 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1258 | // CHECK-FIXES: v2.emplace_back(); |
1259 | v2.push_back({.it: std::vector<int>{}}); |
1260 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1261 | // CHECK-FIXES: v2.emplace_back(); |
1262 | v2.push_back(NonTrivialWithVector{.it: std::vector<int>()}); |
1263 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1264 | // CHECK-FIXES: v2.emplace_back(); |
1265 | v2.push_back({.it: std::vector<int>()}); |
1266 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1267 | // CHECK-FIXES: v2.emplace_back(); |
1268 | v2.push_back({.it: {}}); |
1269 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1270 | // CHECK-FIXES: v2.emplace_back(); |
1271 | |
1272 | v2.emplace_back(args: NonTrivialWithVector()); |
1273 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1274 | // CHECK-FIXES: v2.emplace_back(); |
1275 | v2.emplace_back(args: NonTrivialWithVector{}); |
1276 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1277 | // CHECK-FIXES: v2.emplace_back(); |
1278 | v2.emplace_back(args: NonTrivialWithVector{.it: std::vector<int>{}}); |
1279 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1280 | // CHECK-FIXES: v2.emplace_back(); |
1281 | v2.emplace_back(args: NonTrivialWithVector{.it: {}}); |
1282 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1283 | // CHECK-FIXES: v2.emplace_back(); |
1284 | |
1285 | |
1286 | // These should not be noticed or fixed; after the correction, the code won't |
1287 | // compile. |
1288 | v2.push_back(NonTrivialWithVector{.it: {0}}); |
1289 | v2.push_back({.it: {0}}); |
1290 | v2.push_back(NonTrivialWithVector{.it: std::vector<int>{0}}); |
1291 | v2.push_back({.it: std::vector<int>{0}}); |
1292 | v2.emplace_back(args: NonTrivialWithVector{.it: std::vector<int>{0}}); |
1293 | |
1294 | std::vector<NonTrivialWithCtor> v3; |
1295 | |
1296 | v3.push_back(NonTrivialWithCtor()); |
1297 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1298 | // CHECK-FIXES: v3.emplace_back(); |
1299 | v3.push_back(NonTrivialWithCtor{}); |
1300 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1301 | // CHECK-FIXES: v3.emplace_back(); |
1302 | v3.push_back({}); |
1303 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1304 | // CHECK-FIXES: v3.emplace_back(); |
1305 | v3.push_back(NonTrivialWithCtor{std::vector<int>()}); |
1306 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1307 | // CHECK-FIXES: v3.emplace_back(std::vector<int>()); |
1308 | v3.push_back(NonTrivialWithCtor{std::vector<int>{0}}); |
1309 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1310 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{0}); |
1311 | v3.push_back(NonTrivialWithCtor{std::vector<int>{}}); |
1312 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1313 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{}); |
1314 | v3.push_back({std::vector<int>{0}}); |
1315 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1316 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{0}); |
1317 | v3.push_back({std::vector<int>{}}); |
1318 | // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back |
1319 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{}); |
1320 | |
1321 | v3.emplace_back(args: NonTrivialWithCtor()); |
1322 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1323 | // CHECK-FIXES: v3.emplace_back(); |
1324 | v3.emplace_back(args: NonTrivialWithCtor{}); |
1325 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1326 | // CHECK-FIXES: v3.emplace_back(); |
1327 | v3.emplace_back(args: NonTrivialWithCtor{std::vector<int>{}}); |
1328 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1329 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{}); |
1330 | v3.emplace_back(args: NonTrivialWithCtor{std::vector<int>{0}}); |
1331 | // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back |
1332 | // CHECK-FIXES: v3.emplace_back(std::vector<int>{0}); |
1333 | |
1334 | // These should not be noticed or fixed; after the correction, the code won't |
1335 | // compile. |
1336 | v3.push_back(NonTrivialWithCtor{{0}}); |
1337 | v3.push_back(NonTrivialWithCtor{{}}); |
1338 | v3.push_back({{0}}); |
1339 | v3.push_back({{}}); |
1340 | |
1341 | std::vector<NonTrivialWithIntAndVector> v4; |
1342 | |
1343 | // These should not be noticed or fixed; after the correction, the code won't |
1344 | // compile. |
1345 | v4.push_back(NonTrivialWithIntAndVector{.x: 1, .it: {}}); |
1346 | v4.push_back(NonTrivialWithIntAndVector{}); |
1347 | v4.push_back({}); |
1348 | } |
1349 | |
1350 | void testWithPointerTypes() { |
1351 | std::list<Something> l; |
1352 | std::list<Something>* lp = &l; |
1353 | std::stack<Something> s; |
1354 | std::stack<Something>* sp; |
1355 | |
1356 | lp->push_back(Something(1, 2)); |
1357 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1358 | // CHECK-FIXES: lp->emplace_back(1, 2); |
1359 | lp->push_front(Something(1, 2)); |
1360 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1361 | // CHECK-FIXES: lp->emplace_front(1, 2); |
1362 | sp->push(Something(1, 2)); |
1363 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] |
1364 | // CHECK-FIXES: sp->emplace(1, 2); |
1365 | |
1366 | lp->push_back(Something{1, 2}); |
1367 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1368 | // CHECK-FIXES: lp->emplace_back(1, 2); |
1369 | lp->push_front(Something{1, 2}); |
1370 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1371 | // CHECK-FIXES: lp->emplace_front(1, 2); |
1372 | sp->push(Something{1, 2}); |
1373 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] |
1374 | // CHECK-FIXES: sp->emplace(1, 2); |
1375 | |
1376 | lp->push_back(Something()); |
1377 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1378 | // CHECK-FIXES: lp->emplace_back(); |
1379 | lp->push_front(Something()); |
1380 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1381 | // CHECK-FIXES: lp->emplace_front(); |
1382 | sp->push(Something()); |
1383 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] |
1384 | // CHECK-FIXES: sp->emplace(); |
1385 | |
1386 | lp->push_back(Something{}); |
1387 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] |
1388 | // CHECK-FIXES: lp->emplace_back(); |
1389 | lp->push_front(Something{}); |
1390 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] |
1391 | // CHECK-FIXES: lp->emplace_front(); |
1392 | sp->push(Something{}); |
1393 | // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] |
1394 | // CHECK-FIXES: sp->emplace(); |
1395 | |
1396 | lp->emplace_back(args: Something(1, 2)); |
1397 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back |
1398 | // CHECK-FIXES: lp->emplace_back(1, 2); |
1399 | lp->emplace_front(args: Something(1, 2)); |
1400 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front |
1401 | // CHECK-FIXES: lp->emplace_front(1, 2); |
1402 | sp->emplace(args: Something(1, 2)); |
1403 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
1404 | // CHECK-FIXES: sp->emplace(1, 2); |
1405 | |
1406 | lp->emplace_back(args: Something{1, 2}); |
1407 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back |
1408 | // CHECK-FIXES: lp->emplace_back(1, 2); |
1409 | lp->emplace_front(args: Something{1, 2}); |
1410 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front |
1411 | // CHECK-FIXES: lp->emplace_front(1, 2); |
1412 | sp->emplace(args: Something{1, 2}); |
1413 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
1414 | // CHECK-FIXES: sp->emplace(1, 2); |
1415 | |
1416 | lp->emplace_back(args: Something()); |
1417 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back |
1418 | // CHECK-FIXES: lp->emplace_back(); |
1419 | lp->emplace_front(args: Something()); |
1420 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front |
1421 | // CHECK-FIXES: lp->emplace_front(); |
1422 | sp->emplace(args: Something()); |
1423 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
1424 | // CHECK-FIXES: sp->emplace(); |
1425 | |
1426 | lp->emplace_back(args: Something{}); |
1427 | // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back |
1428 | // CHECK-FIXES: lp->emplace_back(); |
1429 | lp->emplace_front(args: Something{}); |
1430 | // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front |
1431 | // CHECK-FIXES: lp->emplace_front(); |
1432 | sp->emplace(args: Something{}); |
1433 | // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace |
1434 | // CHECK-FIXES: sp->emplace(); |
1435 | } |
1436 | |