// RUN: %check_clang_tidy %s modernize-use-emplace %t -- \ // RUN: -config="{CheckOptions: \ // RUN: {modernize-use-emplace.ContainersWithPushBack: \ // RUN: '::std::vector; ::std::list; ::std::deque; llvm::LikeASmallVector', \ // RUN: modernize-use-emplace.TupleTypes: \ // RUN: '::std::pair; std::tuple; ::test::Single', \ // RUN: modernize-use-emplace.TupleMakeFunctions: \ // RUN: '::std::make_pair; ::std::make_tuple; ::test::MakeSingle'}}" namespace std { template class initializer_list { public: initializer_list() noexcept {} }; template class pair { public: pair() = default; pair(const pair &) = default; pair(pair &&) = default; pair(const T1 &, const T2 &) {} pair(T1 &&, T2 &&) {} template pair(const pair &){}; template pair(pair &&){}; }; template class vector { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } vector() = default; vector(initializer_list) {} void push_back(const T &) {} void push_back(T &&) {} template void emplace_back(Args &&... args){}; template iterator emplace(const_iterator pos, Args &&...args){}; ~vector(); }; template class list { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } void push_front(const T &) {} void push_front(T &&) {} void push_back(const T &) {} void push_back(T &&) {} template iterator emplace(const_iterator pos, Args &&...args){}; template void emplace_back(Args &&... args){}; template void emplace_front(Args &&...args){}; ~list(); }; template class deque { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } void push_back(const T &) {} void push_back(T &&) {} void push_front(const T &) {} void push_front(T &&) {} template iterator emplace(const_iterator pos, Args &&...args){}; template void emplace_back(Args &&... args){}; template void emplace_front(Args &&...args){}; ~deque(); }; template class forward_list { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } void push_front(const T &) {} void push_front(T &&) {} template void emplace_front(Args &&...args){}; template iterator emplace_after(const_iterator pos, Args &&...args){}; }; template class set { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class map { public: using value_type = std::pair; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class multiset { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class multimap { public: using value_type = std::pair; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class unordered_set { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class unordered_map { public: using value_type = std::pair; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class unordered_multiset { public: using value_type = T; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class unordered_multimap { public: using value_type = std::pair; class iterator {}; class const_iterator {}; const_iterator begin() { return const_iterator{}; } template void emplace(Args &&...args){}; template iterator emplace_hint(const_iterator pos, Args &&...args){}; }; template class stack { public: using value_type = T; void push(const T &) {} void push(T &&) {} template void emplace(Args &&...args){}; }; template class queue { public: using value_type = T; void push(const T &) {} void push(T &&) {} template void emplace(Args &&...args){}; }; template class priority_queue { public: using value_type = T; void push(const T &) {} void push(T &&) {} template void emplace(Args &&...args){}; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template struct remove_reference { using type = T; }; template pair::type, typename remove_reference::type> make_pair(T1 &&, T2 &&) { return {}; }; template class tuple { public: tuple() = default; tuple(const tuple &) = default; tuple(tuple &&) = default; tuple(const Ts &...) {} tuple(Ts &&...) {} template tuple(const tuple &){}; template tuple(tuple &&) {} template tuple(const pair &) { static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); }; template tuple(pair &&) { static_assert(sizeof...(Ts) == 2, "Wrong tuple size"); }; }; template tuple::type...> make_tuple(Ts &&...) { return {}; } template class unique_ptr { public: explicit unique_ptr(T *) {} ~unique_ptr(); }; } // namespace std namespace llvm { template class LikeASmallVector { public: void push_back(const T &) {} void push_back(T &&) {} template void emplace_back(Args &&... args){}; }; } // namespace llvm void testInts() { std::vector v; v.push_back(42); v.push_back(int(42)); v.push_back(int{42}); v.push_back(42.0); int z; v.push_back(z); } struct Something { Something(int a, int b = 41) {} Something() {} void push_back(Something); int getInt() { return 42; } }; struct Convertable { operator Something() { return Something{}; } }; struct Zoz { Zoz(Something, int = 42) {} }; Zoz getZoz(Something s) { return Zoz(s); } void test_Something() { std::vector v; v.push_back(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: v.emplace_back(1, 2); v.push_back(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2); v.push_back(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(); v.push_back(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(); Something Different; v.push_back(Something(Different.getInt(), 42)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(Different.getInt(), 42); v.push_back(Different.getInt()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(Different.getInt()); v.push_back(42); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42); Something temporary(42, 42); temporary.push_back(temporary); v.push_back(temporary); v.push_back(Convertable()); v.push_back(Convertable{}); Convertable s; v.push_back(s); } template void dependOnElem() { std::vector v; v.push_back(ElemType(42)); } template void dependOnContainer() { ContainerType v; v.push_back(Something(42)); } void callDependent() { dependOnElem(); dependOnContainer>(); } void test2() { std::vector v; v.push_back(Zoz(Something(21, 37))); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(Something(21, 37)); v.push_back(Zoz(Something(21, 37), 42)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(Something(21, 37), 42); v.push_back(getZoz(Something(1, 2))); } struct GetPair { std::pair getPair(); }; void testPair() { std::vector> v; v.push_back(std::pair(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2); GetPair g; v.push_back(g.getPair()); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(g.getPair()); std::vector> v2; v2.push_back(std::pair(Something(42, 42), Zoz(Something(21, 37)))); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(Something(42, 42), Zoz(Something(21, 37))); } void testTuple() { std::vector> v; v.push_back(std::tuple(false, 'x', 1)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(false, 'x', 1); v.push_back(std::tuple{false, 'y', 2}); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(false, 'y', 2); v.push_back({true, 'z', 3}); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(true, 'z', 3); std::vector> x; x.push_back(std::make_pair(1, false)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: x.emplace_back(1, false); x.push_back(std::make_pair(2LL, 1)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: x.emplace_back(2LL, 1); } struct Base { Base(int, int *, int = 42); }; struct Derived : Base { Derived(int *, Something) : Base(42, nullptr) {} }; void testDerived() { std::vector v; v.push_back(Derived(nullptr, Something{})); } void testNewExpr() { std::vector v; v.push_back(Derived(new int, Something{})); } void testSpaces() { std::vector v; // clang-format off v.push_back(Something(1, //arg1 2 // arg2 ) // Something ); // CHECK-MESSAGES: :[[@LINE-4]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, //arg1 // CHECK-FIXES: 2 // arg2 // CHECK-FIXES: // Something // CHECK-FIXES: ); v.push_back( Something (1, 2) ); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2 ); v.push_back( Something {1, 2} ); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2 ); v.push_back( Something {} ); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back( ); v.push_back( Something(1, 2) ); // CHECK-MESSAGES: :[[@LINE-2]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2 ); std::vector v2; v2.push_back( Base(42, nullptr)); // CHECK-MESSAGES: :[[@LINE-2]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(42, nullptr); // clang-format on } void testPointers() { std::vector v; v.push_back(new int(5)); std::vector> v2; v2.push_back(std::unique_ptr(new int(42))); // This call can't be replaced with emplace_back. // If emplacement will fail (not enough memory to add to vector) // we will have leak of int because unique_ptr won't be constructed // (and destructed) as in push_back case. auto *ptr = new int; v2.push_back(std::unique_ptr(ptr)); // Same here } void testMakePair() { std::vector> v; v.push_back(std::make_pair(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, 2); v.push_back(std::make_pair(42LL, 13)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42LL, 13); v.push_back(std::make_pair(0, 3)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(std::make_pair(0, 3)); // // Even though the call above could be turned into v.emplace_back(0, 3), // we don't eliminate the make_pair call here, because of the explicit // template parameters provided. make_pair's arguments can be convertible // to its explicitly provided template parameter, but not to the pair's // element type. The examples below illustrate the problem. struct D { D(...) {} operator char() const { return 0; } }; v.push_back(std::make_pair(Something(), 2)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(std::make_pair(Something(), 2)); struct X { X(std::pair) {} }; std::vector x; x.push_back(std::make_pair(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: x.emplace_back(std::make_pair(1, 2)); // make_pair cannot be removed here, as X is not constructible with two ints. struct Y { Y(std::pair &&) {} }; std::vector y; y.push_back(std::make_pair(2, 3)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: y.emplace_back(std::make_pair(2, 3)); // make_pair cannot be removed here, as Y is not constructible with two ints. } void testMakeTuple() { std::vector> v; v.push_back(std::make_tuple(1, true, 'v')); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1, true, 'v'); v.push_back(std::make_tuple(2ULL, 1, 0)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(2ULL, 1, 0); v.push_back(std::make_tuple(3LL, 1, 0)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(std::make_tuple(3LL, 1, 0)); // make_tuple is not removed when there are explicit template // arguments provided. } namespace test { template struct Single { Single() = default; Single(const Single &) = default; Single(Single &&) = default; Single(const T &) {} Single(T &&) {} template Single(const Single &) {} template Single(Single &&) {} template Single(const std::tuple &) {} template Single(std::tuple &&) {} }; template Single::type> MakeSingle(T &&) { return {}; } } // namespace test void testOtherTuples() { std::vector> v; v.push_back(test::Single(1)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(1); v.push_back({2}); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(2); v.push_back(test::MakeSingle(3)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(3); v.push_back(test::MakeSingle(4)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(test::MakeSingle(4)); // We don't remove make functions with explicit template parameters. v.push_back(test::MakeSingle(5LL)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(5LL); v.push_back(std::make_tuple(6)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(6); v.push_back(std::make_tuple(7LL)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(7LL); } void testOtherContainers() { std::list l; l.push_back(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: l.emplace_back(42, 41); l.push_front(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_front // CHECK-FIXES: l.emplace_front(42, 41); std::deque d; d.push_back(Something(42)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: d.emplace_back(42); d.push_front(Something(42)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_front // CHECK-FIXES: d.emplace_front(42); llvm::LikeASmallVector ls; ls.push_back(Something(42)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: ls.emplace_back(42); std::stack s; s.push(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace // CHECK-FIXES: s.emplace(42, 41); std::queue q; q.push(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace // CHECK-FIXES: q.emplace(42, 41); std::priority_queue pq; pq.push(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace // CHECK-FIXES: pq.emplace(42, 41); std::forward_list fl; fl.push_front(Something(42, 41)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_front // CHECK-FIXES: fl.emplace_front(42, 41); } class IntWrapper { public: IntWrapper(int x) : value(x) {} IntWrapper operator+(const IntWrapper other) const { return IntWrapper(value + other.value); } private: int value; }; void testMultipleOpsInPushBack() { std::vector v; v.push_back(IntWrapper(42) + IntWrapper(27)); } // Macro tests. #define PUSH_BACK_WHOLE(c, x) c.push_back(x) #define PUSH_BACK_NAME push_back #define PUSH_BACK_ARG(x) (x) #define SOME_OBJ Something(10) #define MILLION 3 #define SOME_WEIRD_PUSH(v) v.push_back(Something( #define OPEN ( #define CLOSE ) void macroTest() { std::vector v; Something s; PUSH_BACK_WHOLE(v, Something(5, 6)); // CHECK-MESSAGES: :[[@LINE-1]]:3: warning: use emplace_back v.PUSH_BACK_NAME(Something(5)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back v.push_back PUSH_BACK_ARG(Something(5, 6)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back v.push_back(SOME_OBJ); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back v.push_back(Something(MILLION)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(MILLION); // clang-format off v.push_back( Something OPEN 3 CLOSE ); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // clang-format on PUSH_BACK_WHOLE(s, Something(1)); } struct A { int value1, value2; }; struct B { B(A) {} }; struct C { int value1, value2, value3; }; void testAggregation() { // This should not be noticed or fixed; after the correction, the code won't // compile. std::vector v; v.push_back(A({1, 2})); std::vector vb; vb.push_back(B({10, 42})); } struct Bitfield { unsigned bitfield : 1; unsigned notBitfield; }; void testBitfields() { std::vector v; Bitfield b; v.push_back(Something(42, b.bitfield)); v.push_back(Something(b.bitfield)); v.push_back(Something(42, b.notBitfield)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42, b.notBitfield); int var; v.push_back(Something(42, var)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42, var); } class PrivateCtor { PrivateCtor(int z); public: void doStuff() { std::vector v; // This should not change it because emplace back doesn't have permission. // Check currently doesn't support friend declarations because pretty much // nobody would want to be friend with std::vector :(. v.push_back(PrivateCtor(42)); } }; struct WithDtor { WithDtor(int) {} ~WithDtor(); }; void testWithDtor() { std::vector v; v.push_back(WithDtor(42)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back // CHECK-FIXES: v.emplace_back(42); } void testInitializerList() { std::vector> v; v.push_back(std::vector({1})); // Test against the bug reported in PR32896. v.push_back({{2}}); using PairIntVector = std::pair>; std::vector x; x.push_back(PairIntVector(3, {4})); x.push_back({5, {6}}); } class Foo { public: Foo(){}; Foo(int){}; Foo(int, int){}; Foo(std::pair){}; protected: Foo(char *) : Foo(){}; }; void testSomeEmplaceCases() { std::vector> v1; std::vector v2; std::unordered_map m1; v1.emplace_back(std::make_pair("foo", "bar")); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back("foo", "bar"); char *foo = "bar"; v1.emplace_back(std::make_pair(foo, "bar")); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back(foo, "bar"); v1.emplace(v1.begin(), std::make_pair("foo", "bar")); // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: v1.emplace(v1.begin(), "foo", "bar"); v2.emplace_back(Foo()); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(); v2.emplace_back(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(13); v2.emplace_back(Foo{13}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(13); int a = 31; v2.emplace_back(Foo(13, a)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(13, a); v2.emplace_back(std::make_pair(3, 3)); m1.emplace(std::make_pair(13, "foo")); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: m1.emplace(13, "foo"); std::vector> v3; v3.emplace_back(std::pair(13, 71)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back v3.emplace_back(std::make_pair(13, 71)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back std::vector> v4; v4.emplace_back(std::tuple(13, 31, 71)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back v4.emplace_back(std::make_tuple(13, 31, 71)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back std::vector> v5; v5.emplace_back(test::Single(13)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back v5.emplace_back(test::MakeSingle(13)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back } void testAllSTLEmplacyFunctions() { std::vector vector; std::deque deque; std::forward_list forward_list; std::list list; std::set set; std::map map; std::multiset multiset; std::multimap multimap; std::unordered_set unordered_set; std::unordered_map unordered_map; std::unordered_multiset unordered_multiset; std::unordered_multimap unordered_multimap; std::stack stack; std::queue queue; std::priority_queue priority_queue; vector.emplace_back(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: vector.emplace_back(13); vector.emplace(vector.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:34: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: vector.emplace(vector.begin(), 13); deque.emplace(deque.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:32: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: deque.emplace(deque.begin(), 13); deque.emplace_front(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:23: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: deque.emplace_front(13); deque.emplace_back(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: deque.emplace_back(13); forward_list.emplace_after(forward_list.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:52: warning: unnecessary temporary object created while calling emplace_after // CHECK-FIXES: forward_list.emplace_after(forward_list.begin(), 13); forward_list.emplace_front(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: forward_list.emplace_front(13); list.emplace(list.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: list.emplace(list.begin(), 13); list.emplace_back(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: list.emplace_back(13); list.emplace_front(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:22: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: list.emplace_front(13); set.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: set.emplace(13); set.emplace_hint(set.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: set.emplace_hint(set.begin(), 13); map.emplace(std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: map.emplace(13, Foo(13)); map.emplace_hint(map.begin(), std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:33: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: map.emplace_hint(map.begin(), 13, Foo(13)); multiset.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: multiset.emplace(13); multiset.emplace_hint(multiset.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: multiset.emplace_hint(multiset.begin(), 13); multimap.emplace(std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: multimap.emplace(13, Foo(13)); multimap.emplace_hint(multimap.begin(), std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:43: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: multimap.emplace_hint(multimap.begin(), 13, Foo(13)); unordered_set.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: unordered_set.emplace(13); unordered_set.emplace_hint(unordered_set.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: unordered_set.emplace_hint(unordered_set.begin(), 13); unordered_map.emplace(std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:25: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: unordered_map.emplace(13, Foo(13)); unordered_map.emplace_hint(unordered_map.begin(), std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:53: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: unordered_map.emplace_hint(unordered_map.begin(), 13, Foo(13)); unordered_multiset.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: unordered_multiset.emplace(13); unordered_multiset.emplace_hint(unordered_multiset.begin(), Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: unordered_multiset.emplace_hint(unordered_multiset.begin(), 13); unordered_multimap.emplace(std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: unordered_multimap.emplace(13, Foo(13)); unordered_multimap.emplace_hint(unordered_multimap.begin(), std::make_pair(13, Foo(13))); // CHECK-MESSAGES: :[[@LINE-1]]:63: warning: unnecessary temporary object created while calling emplace_hint // CHECK-FIXES: unordered_multimap.emplace_hint(unordered_multimap.begin(), 13, Foo(13)); stack.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: stack.emplace(13); queue.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: queue.emplace(13); priority_queue.emplace(Foo(13)); // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: priority_queue.emplace(13); } void test_AliasEmplacyFunctions() { typedef std::list L; using DQ = std::deque; L l; l.emplace_back(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: l.emplace_back(3); DQ dq; dq.emplace_back(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: dq.emplace_back(3); typedef std::stack STACK; using PQ = std::priority_queue; STACK stack; stack.emplace(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:17: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: stack.emplace(3); PQ pq; pq.emplace(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: pq.emplace(3); typedef std::forward_list FL; using DQ2 = std::deque; FL fl; fl.emplace_front(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: fl.emplace_front(3); DQ2 dq2; dq2.emplace_front(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: dq2.emplace_front(3); } void test_Alias() { typedef std::list L; using DQ = std::deque; L l; l.push_back(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: l.emplace_back(3); DQ dq; dq.push_back(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: dq.emplace_back(3); typedef std::stack STACK; using PQ = std::priority_queue; STACK stack; stack.push(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:9: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: stack.emplace(3); PQ pq; pq.push(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: pq.emplace(3); typedef std::forward_list FL; using DQ2 = std::deque; FL fl; fl.push_front(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: fl.emplace_front(3); DQ2 dq2; dq2.push_front(Foo(3)); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: dq2.emplace_front(3); } struct Bar { public: Bar(){}; void testWithPrivateAndProtectedCtor() { std::vector vec; vec.emplace_back(Bar(13)); vec.emplace_back(Bar(13, 13)); } protected: Bar(int){}; private: Bar(int, int){}; }; void testPossibleFalsePositives() { struct Y { Y(std::pair &&) {} }; std::vector y; y.emplace_back(std::make_pair(2, 3)); std::vector> v; v.emplace_back(std::make_pair(0, 3)); struct D { D(...) {} operator char() const { return 0; } }; v.emplace_back(std::make_pair(Something(), 2)); } struct InnerType { InnerType(); InnerType(char const*); }; struct NonTrivialNoCtor { InnerType it; }; struct NonTrivialWithVector { std::vector it; }; struct NonTrivialWithIntAndVector { int x; std::vector it; }; struct NonTrivialWithCtor { NonTrivialWithCtor(); NonTrivialWithCtor(std::vector const&); }; void testBracedInitTemporaries() { std::vector v1; v1.push_back(NonTrivialNoCtor()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back(NonTrivialNoCtor{}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back({}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back(NonTrivialNoCtor{InnerType{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back({InnerType{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back(NonTrivialNoCtor{InnerType()}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back({InnerType()}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.push_back({{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v1.emplace_back(); v1.emplace_back(NonTrivialNoCtor()); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back(); v1.emplace_back(NonTrivialNoCtor{}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back(); v1.emplace_back(NonTrivialNoCtor{InnerType{}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back(); v1.emplace_back(NonTrivialNoCtor{{}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v1.emplace_back(); // These should not be noticed or fixed; after the correction, the code won't // compile. v1.push_back(NonTrivialNoCtor{""}); v1.push_back({""}); v1.push_back(NonTrivialNoCtor{InnerType{""}}); v1.push_back({InnerType{""}}); v1.emplace_back(NonTrivialNoCtor{""}); std::vector v2; v2.push_back(NonTrivialWithVector()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back(NonTrivialWithVector{}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back({}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back(NonTrivialWithVector{std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back({std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back(NonTrivialWithVector{std::vector()}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back({std::vector()}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.push_back({{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v2.emplace_back(); v2.emplace_back(NonTrivialWithVector()); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(); v2.emplace_back(NonTrivialWithVector{}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(); v2.emplace_back(NonTrivialWithVector{std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(); v2.emplace_back(NonTrivialWithVector{{}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v2.emplace_back(); // These should not be noticed or fixed; after the correction, the code won't // compile. v2.push_back(NonTrivialWithVector{{0}}); v2.push_back({{0}}); v2.push_back(NonTrivialWithVector{std::vector{0}}); v2.push_back({std::vector{0}}); v2.emplace_back(NonTrivialWithVector{std::vector{0}}); std::vector v3; v3.push_back(NonTrivialWithCtor()); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(); v3.push_back(NonTrivialWithCtor{}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(); v3.push_back({}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(); v3.push_back(NonTrivialWithCtor{std::vector()}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(std::vector()); v3.push_back(NonTrivialWithCtor{std::vector{0}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{0}); v3.push_back(NonTrivialWithCtor{std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{}); v3.push_back({std::vector{0}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{0}); v3.push_back({std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{}); v3.emplace_back(NonTrivialWithCtor()); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v3.emplace_back(); v3.emplace_back(NonTrivialWithCtor{}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v3.emplace_back(); v3.emplace_back(NonTrivialWithCtor{std::vector{}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{}); v3.emplace_back(NonTrivialWithCtor{std::vector{0}}); // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: v3.emplace_back(std::vector{0}); // These should not be noticed or fixed; after the correction, the code won't // compile. v3.push_back(NonTrivialWithCtor{{0}}); v3.push_back(NonTrivialWithCtor{{}}); v3.push_back({{0}}); v3.push_back({{}}); std::vector v4; // These should not be noticed or fixed; after the correction, the code won't // compile. v4.push_back(NonTrivialWithIntAndVector{1, {}}); v4.push_back(NonTrivialWithIntAndVector{}); v4.push_back({}); } void testWithPointerTypes() { std::list l; std::list* lp = &l; std::stack s; std::stack* sp; lp->push_back(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: lp->emplace_back(1, 2); lp->push_front(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: lp->emplace_front(1, 2); sp->push(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: sp->emplace(1, 2); lp->push_back(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: lp->emplace_back(1, 2); lp->push_front(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: lp->emplace_front(1, 2); sp->push(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: sp->emplace(1, 2); lp->push_back(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: lp->emplace_back(); lp->push_front(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: lp->emplace_front(); sp->push(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: sp->emplace(); lp->push_back(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_back instead of push_back [modernize-use-emplace] // CHECK-FIXES: lp->emplace_back(); lp->push_front(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace_front instead of push_front [modernize-use-emplace] // CHECK-FIXES: lp->emplace_front(); sp->push(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: use emplace instead of push [modernize-use-emplace] // CHECK-FIXES: sp->emplace(); lp->emplace_back(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: lp->emplace_back(1, 2); lp->emplace_front(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: lp->emplace_front(1, 2); sp->emplace(Something(1, 2)); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: sp->emplace(1, 2); lp->emplace_back(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: lp->emplace_back(1, 2); lp->emplace_front(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: lp->emplace_front(1, 2); sp->emplace(Something{1, 2}); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: sp->emplace(1, 2); lp->emplace_back(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: lp->emplace_back(); lp->emplace_front(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: lp->emplace_front(); sp->emplace(Something()); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: sp->emplace(); lp->emplace_back(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: unnecessary temporary object created while calling emplace_back // CHECK-FIXES: lp->emplace_back(); lp->emplace_front(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:21: warning: unnecessary temporary object created while calling emplace_front // CHECK-FIXES: lp->emplace_front(); sp->emplace(Something{}); // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: unnecessary temporary object created while calling emplace // CHECK-FIXES: sp->emplace(); }