157 lines · cpp
1// RUN: %check_clang_tidy %s performance-move-constructor-init,modernize-pass-by-value %t -- \2// RUN: -config='{CheckOptions: \3// RUN: {modernize-pass-by-value.ValuesOnly: true}}' \4// RUN: -- -isystem %clang_tidy_headers5 6#include <s.h>7 8// CHECK-FIXES: #include <utility>9 10template <class T> struct remove_reference {typedef T type;};11template <class T> struct remove_reference<T&> {typedef T type;};12template <class T> struct remove_reference<T&&> {typedef T type;};13 14template <typename T>15typename remove_reference<T>::type&& move(T&& arg) {16 return static_cast<typename remove_reference<T>::type&&>(arg);17}18 19struct C {20 C() = default;21 C(const C&) = default;22};23 24struct B {25 B() {}26 B(const B&) {}27 B(B &&) {}28};29 30struct D : B {31 D() : B() {}32 D(const D &RHS) : B(RHS) {}33 // CHECK-NOTES: :[[@LINE+3]]:16: warning: move constructor initializes base class by calling a copy constructor [performance-move-constructor-init]34 // CHECK-NOTES: 26:3: note: copy constructor being called35 // CHECK-NOTES: 27:3: note: candidate move constructor here36 D(D &&RHS) : B(RHS) {}37};38 39struct E : B {40 E() : B() {}41 E(const E &RHS) : B(RHS) {}42 E(E &&RHS) : B(move(RHS)) {} // ok43};44 45struct F {46 C M;47 48 F(F &&) : M(C()) {} // ok49};50 51struct G {52 G() = default;53 G(const G&) = default;54 G(G&&) = delete;55};56 57struct H : G {58 H() = default;59 H(const H&) = default;60 H(H &&RHS) : G(RHS) {} // ok61};62 63struct I {64 I(const I &) = default; // suppresses move constructor creation65};66 67struct J : I {68 J(J &&RHS) : I(RHS) {} // ok69};70 71struct K {}; // Has implicit copy and move constructors, is trivially copyable72struct L : K {73 L(L &&RHS) : K(RHS) {} // ok74};75 76struct M {77 B Mem;78 // CHECK-NOTES: :[[@LINE+1]]:16: warning: move constructor initializes class member by calling a copy constructor [performance-move-constructor-init]79 M(M &&RHS) : Mem(RHS.Mem) {}80 // CHECK-NOTES: 26:3: note: copy constructor being called81 // CHECK-NOTES: 27:3: note: candidate move constructor here82};83 84struct N {85 B Mem;86 N(N &&RHS) : Mem(move(RHS.Mem)) {}87};88 89struct O {90 O(O&& other) : b(other.b) {} // ok91 const B b;92};93 94struct P {95 P(O&& other) : b(other.b) {} // ok96 B b;97};98 99struct Movable {100 Movable(Movable &&) = default;101 Movable(const Movable &) = default;102 Movable &operator=(const Movable &) = default;103 ~Movable() {}104};105 106struct TriviallyCopyable {107 TriviallyCopyable() = default;108 TriviallyCopyable(TriviallyCopyable &&) = default;109 TriviallyCopyable(const TriviallyCopyable &) = default;110};111 112struct Positive {113 Positive(Movable M) : M_(M) {}114 // CHECK-NOTES: [[@LINE-1]]:12: warning: pass by value and use std::move [modernize-pass-by-value]115 // CHECK-FIXES: Positive(Movable M) : M_(std::move(M)) {}116 Movable M_;117};118 119struct NegativeMultipleInitializerReferences {120 NegativeMultipleInitializerReferences(Movable M) : M_(M), n_(M) {}121 Movable M_;122 Movable n_;123};124 125struct NegativeReferencedInConstructorBody {126 NegativeReferencedInConstructorBody(Movable M) : M_(M) { M_ = M; }127 Movable M_;128};129 130struct NegativeParamTriviallyCopyable {131 NegativeParamTriviallyCopyable(TriviallyCopyable T) : T_(T) {}132 NegativeParamTriviallyCopyable(int I) : I_(I) {}133 134 TriviallyCopyable T_;135 int I_;136};137 138struct NegativeNotPassedByValue {139 // This const ref constructor isn't warned about because the ValuesOnly option is set.140 NegativeNotPassedByValue(const Movable &M) : M_(M) {}141 NegativeNotPassedByValue(const Movable M) : M_(M) {}142 NegativeNotPassedByValue(Movable &M) : M_(M) {}143 NegativeNotPassedByValue(Movable *M) : M_(*M) {}144 NegativeNotPassedByValue(const Movable *M) : M_(*M) {}145 Movable M_;146};147 148struct Immovable {149 Immovable(const Immovable &) = default;150 Immovable(Immovable &&) = delete;151};152 153struct NegativeImmovableParameter {154 NegativeImmovableParameter(Immovable I) : I_(I) {}155 Immovable I_;156};157