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 public: 15 initializer_list() noexcept {} 16 }; 17 18 template <typename T1, typename T2> 19 class pair { 20 public: 21 pair() = default; 22 pair(const pair &) = default; 23 pair(pair &&) = default; 24 25 pair(const T1 &, const T2 &) {} 26 pair(T1 &&, T2 &&) {} 27 28 template <typename U1, typename U2> 29 pair(const pair<U1, U2> &){}; 30 template <typename U1, typename U2> 31 pair(pair<U1, U2> &&){}; 32 }; 33 34 template <typename T> 35 class vector { 36 public: 37 using value_type = T; 38 39 class iterator {}; 40 class const_iterator {}; 41 const_iterator begin() { return const_iterator{}; } 42 43 vector() = default; 44 vector(initializer_list<T>) {} 45 46 void push_back(const T &) {} 47 void push_back(T &&) {} 48 49 template <typename... Args> 50 void emplace_back(Args &&... args){}; 51 template <typename... Args> 52 iterator emplace(const_iterator pos, Args &&...args){}; 53 ~vector(); 54 }; 55 56 template <typename T> 57 class list { 58 public: 59 using value_type = T; 60 61 class iterator {}; 62 class const_iterator {}; 63 const_iterator begin() { return const_iterator{}; } 64 65 void push_back(const T &) {} 66 void push_back(T &&) {} 67 68 template <typename... Args> 69 iterator emplace(const_iterator pos, Args &&...args){}; 70 template <typename... Args> 71 void emplace_back(Args &&... args){}; 72 template <typename... Args> 73 void emplace_front(Args &&...args){}; 74 ~list(); 75 }; 76 77 template <typename T> 78 class deque { 79 public: 80 using value_type = T; 81 82 class iterator {}; 83 class const_iterator {}; 84 const_iterator begin() { return const_iterator{}; } 85 86 void push_back(const T &) {} 87 void push_back(T &&) {} 88 89 template <typename... Args> 90 iterator emplace(const_iterator pos, Args &&...args){}; 91 template <typename... Args> 92 void emplace_back(Args &&... args){}; 93 template <typename... Args> 94 void emplace_front(Args &&...args){}; 95 ~deque(); 96 }; 97 98 template <typename T> 99 class forward_list { 100 public: 101 using value_type = T; 102 103 class iterator {}; 104 class const_iterator {}; 105 const_iterator begin() { return const_iterator{}; } 106 107 template <typename... Args> 108 void emplace_front(Args &&...args){}; 109 template <typename... Args> 110 iterator emplace_after(const_iterator pos, Args &&...args){}; 111 }; 112 113 template <typename T> 114 class set { 115 public: 116 using value_type = T; 117 118 class iterator {}; 119 class const_iterator {}; 120 const_iterator begin() { return const_iterator{}; } 121 122 template <typename... Args> 123 void emplace(Args &&...args){}; 124 template <typename... Args> 125 iterator emplace_hint(const_iterator pos, Args &&...args){}; 126 }; 127 128 template <typename Key, typename T> 129 class map { 130 public: 131 using value_type = std::pair<Key, T>; 132 133 class iterator {}; 134 class const_iterator {}; 135 const_iterator begin() { return const_iterator{}; } 136 137 template <typename... Args> 138 void emplace(Args &&...args){}; 139 template <typename... Args> 140 iterator emplace_hint(const_iterator pos, Args &&...args){}; 141 }; 142 143 template <typename T> 144 class multiset { 145 public: 146 using value_type = T; 147 148 class iterator {}; 149 class const_iterator {}; 150 const_iterator begin() { return const_iterator{}; } 151 152 template <typename... Args> 153 void emplace(Args &&...args){}; 154 template <typename... Args> 155 iterator emplace_hint(const_iterator pos, Args &&...args){}; 156 }; 157 158 template <typename Key, typename T> 159 class multimap { 160 public: 161 using value_type = std::pair<Key, T>; 162 163 class iterator {}; 164 class const_iterator {}; 165 const_iterator begin() { return const_iterator{}; } 166 167 template <typename... Args> 168 void emplace(Args &&...args){}; 169 template <typename... Args> 170 iterator emplace_hint(const_iterator pos, Args &&...args){}; 171 }; 172 173 template <typename T> 174 class unordered_set { 175 public: 176 using value_type = T; 177 178 class iterator {}; 179 class const_iterator {}; 180 const_iterator begin() { return const_iterator{}; } 181 182 template <typename... Args> 183 void emplace(Args &&...args){}; 184 template <typename... Args> 185 iterator emplace_hint(const_iterator pos, Args &&...args){}; 186 }; 187 188 template <typename Key, typename T> 189 class unordered_map { 190 public: 191 using value_type = std::pair<Key, T>; 192 193 class iterator {}; 194 class const_iterator {}; 195 const_iterator begin() { return const_iterator{}; } 196 197 template <typename... Args> 198 void emplace(Args &&...args){}; 199 template <typename... Args> 200 iterator emplace_hint(const_iterator pos, Args &&...args){}; 201 }; 202 203 template <typename T> 204 class unordered_multiset { 205 public: 206 using value_type = T; 207 208 class iterator {}; 209 class const_iterator {}; 210 const_iterator begin() { return const_iterator{}; } 211 212 template <typename... Args> 213 void emplace(Args &&...args){}; 214 template <typename... Args> 215 iterator emplace_hint(const_iterator pos, Args &&...args){}; 216 }; 217 218 template <typename Key, typename T> 219 class unordered_multimap { 220 public: 221 using value_type = std::pair<Key, T>; 222 223 class iterator {}; 224 class const_iterator {}; 225 const_iterator begin() { return const_iterator{}; } 226 227 template <typename... Args> 228 void emplace(Args &&...args){}; 229 template <typename... Args> 230 iterator emplace_hint(const_iterator pos, Args &&...args){}; 231 }; 232 233 template <typename T> 234 class stack { 235 public: 236 using value_type = T; 237 238 template <typename... Args> 239 void emplace(Args &&...args){}; 240 }; 241 242 template <typename T> 243 class queue { 244 public: 245 using value_type = T; 246 247 template <typename... Args> 248 void emplace(Args &&...args){}; 249 }; 250 251 template <typename T> 252 class priority_queue { 253 public: 254 using value_type = T; 255 256 template <typename... Args> 257 void emplace(Args &&...args){}; 258 }; 259 260 template <typename T> 261 struct remove_reference { using type = T; }; 262 template <typename T> 263 struct remove_reference<T &> { using type = T; }; 264 template <typename T> 265 struct remove_reference<T &&> { using type = T; }; 266 267 template <typename T1, typename T2> 268 pair<typename remove_reference<T1>::type, typename remove_reference<T2>::type> 269 make_pair(T1 &&, T2 &&) { 270 return {}; 271 }; 272 273 template <typename... Ts> 274 class tuple { 275 public: 276 tuple() = default; 277 tuple(const tuple &) = default; 278 tuple(tuple &&) = default; 279 280 tuple(const Ts &...) {} 281 tuple(Ts &&...) {} 282 283 template <typename... Us> 284 tuple(const tuple<Us...> &){}; 285 template <typename... Us> 286 tuple(tuple<Us...> &&) {} 287 288 template <typename U1, typename U2> 289 tuple(const pair<U1, U2> &) { 290 static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); 291 }; 292 template <typename U1, typename U2> 293 tuple(pair<U1, U2> &&) { 294 static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); 295 }; 296 }; 297 298 template <typename... Ts> 299 tuple<typename remove_reference<Ts>::type...> make_tuple(Ts &&...) { 300 return {}; 301 } 302 303 template <typename T> 304 class unique_ptr { 305 public: 306 explicit unique_ptr(T *) {} 307 ~unique_ptr(); 308 }; 309 } // namespace std 310 311 namespace llvm { 312 template <typename T> 313 class LikeASmallVector { 314 public: 315 void push_back(const T &) {} 316 void push_back(T &&) {} 317 318 template <typename... Args> 319 void emplace_back(Args &&... args){}; 320 }; 321 322 } // namespace llvm 323 324 void testInts() { 325 std::vector<int> v; 326 v.push_back(42); 327 v.push_back(int(42)); 328 v.push_back(int{42}); 329 v.push_back(42.0); 330 int z; 331 v.push_back(z); 332 } 333 334 struct Something { 335 Something(int a, int b = 41) {} 336 Something() {} 337 void push_back(Something); 338 int getInt() { return 42; } 339 }; 340 341 struct Convertable { 342 operator Something() { return Something{}; } 343 }; 344 345 struct Zoz { 346 Zoz(Something, int = 42) {} 347 }; 348 349 Zoz getZoz(Something s) { return Zoz(s); } 350 351 void test_Something() { 352 std::vector<Something> v; 353 354 v.push_back(Something(1, 2)); 355 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace] 356 // CHECK-FIXES: v.emplace_back(1, 2); 357 358 v.push_back(Something{1, 2}); 359 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 360 // CHECK-FIXES: v.emplace_back(1, 2); 361 362 v.push_back(Something()); 363 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 364 // CHECK-FIXES: v.emplace_back(); 365 366 v.push_back(Something{}); 367 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 368 // CHECK-FIXES: v.emplace_back(); 369 370 Something Different; 371 v.push_back(Something(Different.getInt(), 42)); 372 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 373 // CHECK-FIXES: v.emplace_back(Different.getInt(), 42); 374 375 v.push_back(Different.getInt()); 376 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 377 // CHECK-FIXES: v.emplace_back(Different.getInt()); 378 379 v.push_back(42); 380 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 381 // CHECK-FIXES: v.emplace_back(42); 382 383 Something temporary(42, 42); 384 temporary.push_back(temporary); 385 v.push_back(temporary); 386 387 v.push_back(Convertable()); 388 v.push_back(Convertable{}); 389 Convertable s; 390 v.push_back(s); 391 } 392 393 template <typename ElemType> 394 void dependOnElem() { 395 std::vector<ElemType> v; 396 v.push_back(ElemType(42)); 397 } 398 399 template <typename ContainerType> 400 void dependOnContainer() { 401 ContainerType v; 402 v.push_back(Something(42)); 403 } 404 405 void callDependent() { 406 dependOnElem<Something>(); 407 dependOnContainer<std::vector<Something>>(); 408 } 409 410 void test2() { 411 std::vector<Zoz> v; 412 v.push_back(Zoz(Something(21, 37))); 413 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 414 // CHECK-FIXES: v.emplace_back(Something(21, 37)); 415 416 v.push_back(Zoz(Something(21, 37), 42)); 417 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 418 // CHECK-FIXES: v.emplace_back(Something(21, 37), 42); 419 420 v.push_back(getZoz(Something(1, 2))); 421 } 422 423 struct GetPair { 424 std::pair<int, long> getPair(); 425 }; 426 void testPair() { 427 std::vector<std::pair<int, int>> v; 428 v.push_back(std::pair<int, int>(1, 2)); 429 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 430 // CHECK-FIXES: v.emplace_back(1, 2); 431 432 GetPair g; 433 v.push_back(g.getPair()); 434 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 435 // CHECK-FIXES: v.emplace_back(g.getPair()); 436 437 std::vector<std::pair<Something, Zoz>> v2; 438 v2.push_back(std::pair<Something, Zoz>(Something(42, 42), Zoz(Something(21, 37)))); 439 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back 440 // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37))); 441 } 442 443 void testTuple() { 444 std::vector<std::tuple<bool, char, int>> v; 445 v.push_back(std::tuple<bool, char, int>(false, 'x', 1)); 446 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 447 // CHECK-FIXES: v.emplace_back(false, 'x', 1); 448 449 v.push_back(std::tuple<bool, char, int>{false, 'y', 2}); 450 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 451 // CHECK-FIXES: v.emplace_back(false, 'y', 2); 452 453 v.push_back({true, 'z', 3}); 454 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 455 // CHECK-FIXES: v.emplace_back(true, 'z', 3); 456 457 std::vector<std::tuple<int, bool>> x; 458 x.push_back(std::make_pair(1, false)); 459 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 460 // CHECK-FIXES: x.emplace_back(1, false); 461 462 x.push_back(std::make_pair(2LL, 1)); 463 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 464 // CHECK-FIXES: x.emplace_back(2LL, 1); 465 } 466 467 struct Base { 468 Base(int, int *, int = 42); 469 }; 470 471 struct Derived : Base { 472 Derived(int *, Something) : Base(42, nullptr) {} 473 }; 474 475 void testDerived() { 476 std::vector<Base> v; 477 v.push_back(Derived(nullptr, Something{})); 478 } 479 480 void testNewExpr() { 481 std::vector<Derived> v; 482 v.push_back(Derived(new int, Something{})); 483 } 484 485 void testSpaces() { 486 std::vector<Something> v; 487 488 // clang-format off 489 490 v.push_back(Something(1, //arg1 491 2 // arg2 492 ) // Something 493 ); 494 // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back 495 // CHECK-FIXES: v.emplace_back(1, //arg1 496 // CHECK-FIXES: 2 // arg2 497 // CHECK-FIXES: // Something 498 // CHECK-FIXES: ); 499 500 v.push_back( Something (1, 2) ); 501 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 502 // CHECK-FIXES: v.emplace_back(1, 2 ); 503 504 v.push_back( Something {1, 2} ); 505 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 506 // CHECK-FIXES: v.emplace_back(1, 2 ); 507 508 v.push_back( Something {} ); 509 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 510 // CHECK-FIXES: v.emplace_back( ); 511 512 v.push_back( 513 Something(1, 2) ); 514 // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back 515 // CHECK-FIXES: v.emplace_back(1, 2 ); 516 517 std::vector<Base> v2; 518 v2.push_back( 519 Base(42, nullptr)); 520 // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back 521 // CHECK-FIXES: v2.emplace_back(42, nullptr); 522 523 // clang-format on 524 } 525 526 void testPointers() { 527 std::vector<int *> v; 528 v.push_back(new int(5)); 529 530 std::vector<std::unique_ptr<int>> v2; 531 v2.push_back(std::unique_ptr<int>(new int(42))); 532 // This call can't be replaced with emplace_back. 533 // If emplacement will fail (not enough memory to add to vector) 534 // we will have leak of int because unique_ptr won't be constructed 535 // (and destructed) as in push_back case. 536 537 auto *ptr = new int; 538 v2.push_back(std::unique_ptr<int>(ptr)); 539 // Same here 540 } 541 542 void testMakePair() { 543 std::vector<std::pair<int, int>> v; 544 v.push_back(std::make_pair(1, 2)); 545 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 546 // CHECK-FIXES: v.emplace_back(1, 2); 547 548 v.push_back(std::make_pair(42LL, 13)); 549 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 550 // CHECK-FIXES: v.emplace_back(42LL, 13); 551 552 v.push_back(std::make_pair<char, char>(0, 3)); 553 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 554 // CHECK-FIXES: v.emplace_back(std::make_pair<char, char>(0, 3)); 555 // 556 // Even though the call above could be turned into v.emplace_back(0, 3), 557 // we don't eliminate the make_pair call here, because of the explicit 558 // template parameters provided. make_pair's arguments can be convertible 559 // to its explicitly provided template parameter, but not to the pair's 560 // element type. The examples below illustrate the problem. 561 struct D { 562 D(...) {} 563 operator char() const { return 0; } 564 }; 565 v.push_back(std::make_pair<D, int>(Something(), 2)); 566 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 567 // CHECK-FIXES: v.emplace_back(std::make_pair<D, int>(Something(), 2)); 568 569 struct X { 570 X(std::pair<int, int>) {} 571 }; 572 std::vector<X> x; 573 x.push_back(std::make_pair(1, 2)); 574 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 575 // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2)); 576 // make_pair cannot be removed here, as X is not constructible with two ints. 577 578 struct Y { 579 Y(std::pair<int, int> &&) {} 580 }; 581 std::vector<Y> y; 582 y.push_back(std::make_pair(2, 3)); 583 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 584 // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3)); 585 // make_pair cannot be removed here, as Y is not constructible with two ints. 586 } 587 588 void testMakeTuple() { 589 std::vector<std::tuple<int, bool, char>> v; 590 v.push_back(std::make_tuple(1, true, 'v')); 591 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 592 // CHECK-FIXES: v.emplace_back(1, true, 'v'); 593 594 v.push_back(std::make_tuple(2ULL, 1, 0)); 595 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 596 // CHECK-FIXES: v.emplace_back(2ULL, 1, 0); 597 598 v.push_back(std::make_tuple<long long, int, int>(3LL, 1, 0)); 599 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 600 // CHECK-FIXES: v.emplace_back(std::make_tuple<long long, int, int>(3LL, 1, 0)); 601 // make_tuple is not removed when there are explicit template 602 // arguments provided. 603 } 604 605 namespace test { 606 template <typename T> 607 struct Single { 608 Single() = default; 609 Single(const Single &) = default; 610 Single(Single &&) = default; 611 612 Single(const T &) {} 613 Single(T &&) {} 614 615 template <typename U> 616 Single(const Single<U> &) {} 617 template <typename U> 618 Single(Single<U> &&) {} 619 620 template <typename U> 621 Single(const std::tuple<U> &) {} 622 template <typename U> 623 Single(std::tuple<U> &&) {} 624 }; 625 626 template <typename T> 627 Single<typename std::remove_reference<T>::type> MakeSingle(T &&) { 628 return {}; 629 } 630 } // namespace test 631 632 void testOtherTuples() { 633 std::vector<test::Single<int>> v; 634 v.push_back(test::Single<int>(1)); 635 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 636 // CHECK-FIXES: v.emplace_back(1); 637 638 v.push_back({2}); 639 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 640 // CHECK-FIXES: v.emplace_back(2); 641 642 v.push_back(test::MakeSingle(3)); 643 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 644 // CHECK-FIXES: v.emplace_back(3); 645 646 v.push_back(test::MakeSingle<long long>(4)); 647 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 648 // CHECK-FIXES: v.emplace_back(test::MakeSingle<long long>(4)); 649 // We don't remove make functions with explicit template parameters. 650 651 v.push_back(test::MakeSingle(5LL)); 652 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 653 // CHECK-FIXES: v.emplace_back(5LL); 654 655 v.push_back(std::make_tuple(6)); 656 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 657 // CHECK-FIXES: v.emplace_back(6); 658 659 v.push_back(std::make_tuple(7LL)); 660 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 661 // CHECK-FIXES: v.emplace_back(7LL); 662 } 663 664 void testOtherContainers() { 665 std::list<Something> l; 666 l.push_back(Something(42, 41)); 667 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 668 // CHECK-FIXES: l.emplace_back(42, 41); 669 670 std::deque<Something> d; 671 d.push_back(Something(42)); 672 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 673 // CHECK-FIXES: d.emplace_back(42); 674 675 llvm::LikeASmallVector<Something> ls; 676 ls.push_back(Something(42)); 677 // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back 678 // CHECK-FIXES: ls.emplace_back(42); 679 } 680 681 class IntWrapper { 682 public: 683 IntWrapper(int x) : value(x) {} 684 IntWrapper operator+(const IntWrapper other) const { 685 return IntWrapper(value + other.value); 686 } 687 688 private: 689 int value; 690 }; 691 692 void testMultipleOpsInPushBack() { 693 std::vector<IntWrapper> v; 694 v.push_back(IntWrapper(42) + IntWrapper(27)); 695 } 696 697 // Macro tests. 698 #define PUSH_BACK_WHOLE(c, x) c.push_back(x) 699 #define PUSH_BACK_NAME push_back 700 #define PUSH_BACK_ARG(x) (x) 701 #define SOME_OBJ Something(10) 702 #define MILLION 3 703 #define SOME_WEIRD_PUSH(v) v.push_back(Something( 704 #define OPEN ( 705 #define CLOSE ) 706 void macroTest() { 707 std::vector<Something> v; 708 Something s; 709 710 PUSH_BACK_WHOLE(v, Something(5, 6)); 711 // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back 712 713 v.PUSH_BACK_NAME(Something(5)); 714 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 715 716 v.push_back PUSH_BACK_ARG(Something(5, 6)); 717 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 718 719 v.push_back(SOME_OBJ); 720 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 721 722 v.push_back(Something(MILLION)); 723 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 724 // CHECK-FIXES: v.emplace_back(MILLION); 725 726 // clang-format off 727 v.push_back( Something OPEN 3 CLOSE ); 728 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 729 // clang-format on 730 PUSH_BACK_WHOLE(s, Something(1)); 731 } 732 733 struct A { 734 int value1, value2; 735 }; 736 737 struct B { 738 B(A) {} 739 }; 740 741 struct C { 742 int value1, value2, value3; 743 }; 744 745 void testAggregation() { 746 // This should not be noticed or fixed; after the correction, the code won't 747 // compile. 748 749 std::vector<A> v; 750 v.push_back(A({1, 2})); 751 752 std::vector<B> vb; 753 vb.push_back(B({10, 42})); 754 } 755 756 struct Bitfield { 757 unsigned bitfield : 1; 758 unsigned notBitfield; 759 }; 760 761 void testBitfields() { 762 std::vector<Something> v; 763 Bitfield b; 764 v.push_back(Something(42, b.bitfield)); 765 v.push_back(Something(b.bitfield)); 766 767 v.push_back(Something(42, b.notBitfield)); 768 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 769 // CHECK-FIXES: v.emplace_back(42, b.notBitfield); 770 int var; 771 v.push_back(Something(42, var)); 772 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 773 // CHECK-FIXES: v.emplace_back(42, var); 774 } 775 776 class PrivateCtor { 777 PrivateCtor(int z); 778 779 public: 780 void doStuff() { 781 std::vector<PrivateCtor> v; 782 // This should not change it because emplace back doesn't have permission. 783 // Check currently doesn't support friend declarations because pretty much 784 // nobody would want to be friend with std::vector :(. 785 v.push_back(PrivateCtor(42)); 786 } 787 }; 788 789 struct WithDtor { 790 WithDtor(int) {} 791 ~WithDtor(); 792 }; 793 794 void testWithDtor() { 795 std::vector<WithDtor> v; 796 797 v.push_back(WithDtor(42)); 798 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back 799 // CHECK-FIXES: v.emplace_back(42); 800 } 801 802 void testInitializerList() { 803 std::vector<std::vector<int>> v; 804 v.push_back(std::vector<int>({1})); 805 // Test against the bug reported in PR32896. 806 807 v.push_back({{2}}); 808 809 using PairIntVector = std::pair<int, std::vector<int>>; 810 std::vector<PairIntVector> x; 811 x.push_back(PairIntVector(3, {4})); 812 x.push_back({5, {6}}); 813 } 814 815 class Foo { 816 public: 817 Foo(){}; 818 Foo(int){}; 819 Foo(int, int){}; 820 Foo(std::pair<int, int>){}; 821 822 protected: 823 Foo(char *) : Foo(){}; 824 }; 825 826 void testSomeEmplaceCases() { 827 std::vector<std::pair<char *, char *>> v1; 828 std::vector<Foo> v2; 829 std::unordered_map<int, char *> m1; 830 831 v1.emplace_back(std::make_pair("foo", "bar")); 832 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 833 // CHECK-FIXES: v1.emplace_back("foo", "bar"); 834 835 char *foo = "bar"; 836 v1.emplace_back(std::make_pair(foo, "bar")); 837 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 838 // CHECK-FIXES: v1.emplace_back(foo, "bar"); 839 840 v1.emplace(v1.begin(), std::make_pair("foo", "bar")); 841 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace 842 // CHECK-FIXES: v1.emplace(v1.begin(), "foo", "bar"); 843 844 v2.emplace_back(Foo()); 845 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 846 // CHECK-FIXES: v2.emplace_back(); 847 848 v2.emplace_back(Foo(13)); 849 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 850 // CHECK-FIXES: v2.emplace_back(13); 851 852 v2.emplace_back(Foo{13}); 853 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 854 // CHECK-FIXES: v2.emplace_back(13); 855 856 int a = 31; 857 v2.emplace_back(Foo(13, a)); 858 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 859 // CHECK-FIXES: v2.emplace_back(13, a); 860 861 v2.emplace_back(std::make_pair(3, 3)); 862 863 m1.emplace(std::make_pair(13, "foo")); 864 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace 865 // CHECK-FIXES: m1.emplace(13, "foo"); 866 867 std::vector<std::pair<int, int>> v3; 868 v3.emplace_back(std::pair<int, int>(13, 71)); 869 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 870 v3.emplace_back(std::make_pair(13, 71)); 871 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 872 873 std::vector<std::tuple<int, int, int>> v4; 874 v4.emplace_back(std::tuple<int, int, int>(13, 31, 71)); 875 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 876 v4.emplace_back(std::make_tuple(13, 31, 71)); 877 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 878 879 std::vector<test::Single<int>> v5; 880 v5.emplace_back(test::Single<int>(13)); 881 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 882 v5.emplace_back(test::MakeSingle(13)); 883 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back 884 } 885 886 void testAllSTLEmplacyFunctions() { 887 std::vector<Foo> vector; 888 std::deque<Foo> deque; 889 std::forward_list<Foo> forward_list; 890 std::list<Foo> list; 891 std::set<Foo> set; 892 std::map<int, Foo> map; 893 std::multiset<Foo> multiset; 894 std::multimap<int, Foo> multimap; 895 std::unordered_set<Foo> unordered_set; 896 std::unordered_map<int, Foo> unordered_map; 897 std::unordered_multiset<Foo> unordered_multiset; 898 std::unordered_multimap<int, Foo> unordered_multimap; 899 std::stack<Foo> stack; 900 std::queue<Foo> queue; 901 std::priority_queue<Foo> priority_queue; 902 903 vector.emplace_back(Foo(13)); 904 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_back 905 // CHECK-FIXES: vector.emplace_back(13); 906 907 vector.emplace(vector.begin(), Foo(13)); 908 // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: unnecessary temporary object created while calling emplace 909 // CHECK-FIXES: vector.emplace(vector.begin(), 13); 910 911 deque.emplace(deque.begin(), Foo(13)); 912 // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: unnecessary temporary object created while calling emplace 913 // CHECK-FIXES: deque.emplace(deque.begin(), 13); 914 915 deque.emplace_front(Foo(13)); 916 // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_front 917 // CHECK-FIXES: deque.emplace_front(13); 918 919 deque.emplace_back(Foo(13)); 920 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_back 921 // CHECK-FIXES: deque.emplace_back(13); 922 923 forward_list.emplace_after(forward_list.begin(), Foo(13)); 924 // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: unnecessary temporary object created while calling emplace_after 925 // CHECK-FIXES: forward_list.emplace_after(forward_list.begin(), 13); 926 927 forward_list.emplace_front(Foo(13)); 928 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace_front 929 // CHECK-FIXES: forward_list.emplace_front(13); 930 931 list.emplace(list.begin(), Foo(13)); 932 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace 933 // CHECK-FIXES: list.emplace(list.begin(), 13); 934 935 list.emplace_back(Foo(13)); 936 // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_back 937 // CHECK-FIXES: list.emplace_back(13); 938 939 list.emplace_front(Foo(13)); 940 // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_front 941 // CHECK-FIXES: list.emplace_front(13); 942 943 set.emplace(Foo(13)); 944 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace 945 // CHECK-FIXES: set.emplace(13); 946 947 set.emplace_hint(set.begin(), Foo(13)); 948 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint 949 // CHECK-FIXES: set.emplace_hint(set.begin(), 13); 950 951 map.emplace(std::make_pair(13, Foo(13))); 952 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace 953 // CHECK-FIXES: map.emplace(13, Foo(13)); 954 955 map.emplace_hint(map.begin(), std::make_pair(13, Foo(13))); 956 // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint 957 // CHECK-FIXES: map.emplace_hint(map.begin(), 13, Foo(13)); 958 959 multiset.emplace(Foo(13)); 960 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace 961 // CHECK-FIXES: multiset.emplace(13); 962 963 multiset.emplace_hint(multiset.begin(), Foo(13)); 964 // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint 965 // CHECK-FIXES: multiset.emplace_hint(multiset.begin(), 13); 966 967 multimap.emplace(std::make_pair(13, Foo(13))); 968 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace 969 // CHECK-FIXES: multimap.emplace(13, Foo(13)); 970 971 multimap.emplace_hint(multimap.begin(), std::make_pair(13, Foo(13))); 972 // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint 973 // CHECK-FIXES: multimap.emplace_hint(multimap.begin(), 13, Foo(13)); 974 975 unordered_set.emplace(Foo(13)); 976 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace 977 // CHECK-FIXES: unordered_set.emplace(13); 978 979 unordered_set.emplace_hint(unordered_set.begin(), Foo(13)); 980 // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint 981 // CHECK-FIXES: unordered_set.emplace_hint(unordered_set.begin(), 13); 982 983 unordered_map.emplace(std::make_pair(13, Foo(13))); 984 // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace 985 // CHECK-FIXES: unordered_map.emplace(13, Foo(13)); 986 987 unordered_map.emplace_hint(unordered_map.begin(), std::make_pair(13, Foo(13))); 988 // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint 989 // CHECK-FIXES: unordered_map.emplace_hint(unordered_map.begin(), 13, Foo(13)); 990 991 unordered_multiset.emplace(Foo(13)); 992 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace 993 // CHECK-FIXES: unordered_multiset.emplace(13); 994 unordered_multiset.emplace_hint(unordered_multiset.begin(), Foo(13)); 995 // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint 996 // CHECK-FIXES: unordered_multiset.emplace_hint(unordered_multiset.begin(), 13); 997 998 unordered_multimap.emplace(std::make_pair(13, Foo(13))); 999 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace 1000 // CHECK-FIXES: unordered_multimap.emplace(13, Foo(13)); 1001 unordered_multimap.emplace_hint(unordered_multimap.begin(), std::make_pair(13, Foo(13))); 1002 // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint 1003 // CHECK-FIXES: unordered_multimap.emplace_hint(unordered_multimap.begin(), 13, Foo(13)); 1004 1005 stack.emplace(Foo(13)); 1006 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace 1007 // CHECK-FIXES: stack.emplace(13); 1008 1009 queue.emplace(Foo(13)); 1010 // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace 1011 // CHECK-FIXES: queue.emplace(13); 1012 1013 priority_queue.emplace(Foo(13)); 1014 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace 1015 // CHECK-FIXES: priority_queue.emplace(13); 1016 } 1017 1018 struct Bar { 1019 public: 1020 Bar(){}; 1021 void testWithPrivateAndProtectedCtor() { 1022 std::vector<Bar> vec; 1023 1024 vec.emplace_back(Bar(13)); 1025 vec.emplace_back(Bar(13, 13)); 1026 } 1027 1028 protected: 1029 Bar(int){}; 1030 1031 private: 1032 Bar(int, int){}; 1033 }; 1034 1035 void testPossibleFalsePositives() { 1036 struct Y { 1037 Y(std::pair<int, int> &&) {} 1038 }; 1039 std::vector<Y> y; 1040 y.emplace_back(std::make_pair(2, 3)); 1041 1042 std::vector<std::pair<int, int>> v; 1043 v.emplace_back(std::make_pair<char, char>(0, 3)); 1044 1045 struct D { 1046 D(...) {} 1047 operator char() const { return 0; } 1048 }; 1049 v.emplace_back(std::make_pair<D, int>(Something(), 2)); 1050 } 1051