// RUN: %check_clang_tidy %s performance-move-constructor-init,modernize-pass-by-value %t -- \ // RUN: -config='{CheckOptions: \ // RUN: [{key: modernize-pass-by-value.ValuesOnly, value: 1}]}' \ // RUN: -- -std=c++11 -isystem %S/Inputs/Headers #include // CHECK-FIXES: #include template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; template struct remove_reference {typedef T type;}; template typename remove_reference::type&& move(T&& arg) { return static_cast::type&&>(arg); } struct C { C() = default; C(const C&) = default; }; struct B { B() {} B(const B&) {} B(B &&) {} }; struct D : B { D() : B() {} D(const D &RHS) : B(RHS) {} // CHECK-MESSAGES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [performance-move-constructor-init] // CHECK-MESSAGES: 26:3: note: copy constructor being called // CHECK-MESSAGES: 27:3: note: candidate move constructor here D(D &&RHS) : B(RHS) {} }; struct E : B { E() : B() {} E(const E &RHS) : B(RHS) {} E(E &&RHS) : B(move(RHS)) {} // ok }; struct F { C M; F(F &&) : M(C()) {} // ok }; struct G { G() = default; G(const G&) = default; G(G&&) = delete; }; struct H : G { H() = default; H(const H&) = default; H(H &&RHS) : G(RHS) {} // ok }; struct I { I(const I &) = default; // suppresses move constructor creation }; struct J : I { J(J &&RHS) : I(RHS) {} // ok }; struct K {}; // Has implicit copy and move constructors, is trivially copyable struct L : K { L(L &&RHS) : K(RHS) {} // ok }; struct M { B Mem; // CHECK-MESSAGES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [performance-move-constructor-init] M(M &&RHS) : Mem(RHS.Mem) {} }; struct N { B Mem; N(N &&RHS) : Mem(move(RHS.Mem)) {} }; struct O { O(O&& other) : b(other.b) {} // ok const B b; }; struct P { P(O&& other) : b(other.b) {} // ok B b; }; struct Movable { Movable(Movable &&) = default; Movable(const Movable &) = default; Movable &operator=(const Movable &) = default; ~Movable() {} }; struct TriviallyCopyable { TriviallyCopyable() = default; TriviallyCopyable(TriviallyCopyable &&) = default; TriviallyCopyable(const TriviallyCopyable &) = default; }; struct Positive { Positive(Movable M) : M_(M) {} // CHECK-MESSAGES: [[@LINE-1]]:12: warning: pass by value and use std::move [modernize-pass-by-value] // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {} Movable M_; }; struct NegativeMultipleInitializerReferences { NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {} Movable M_; Movable n_; }; struct NegativeReferencedInConstructorBody { NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; } Movable M_; }; struct NegativeParamTriviallyCopyable { NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {} NegativeParamTriviallyCopyable(int I) : I_(I) {} TriviallyCopyable T_; int I_; }; struct NegativeNotPassedByValue { // This const ref constructor isn't warned about because the ValuesOnly option is set. NegativeNotPassedByValue(const Movable &M) : M_(M) {} NegativeNotPassedByValue(const Movable M) : M_(M) {} NegativeNotPassedByValue(Movable &M) : M_(M) {} NegativeNotPassedByValue(Movable *M) : M_(*M) {} NegativeNotPassedByValue(const Movable *M) : M_(*M) {} Movable M_; }; struct Immovable { Immovable(const Immovable &) = default; Immovable(Immovable &&) = delete; }; struct NegativeImmovableParameter { NegativeImmovableParameter(Immovable I) : I_(I) {} Immovable I_; };