1// RUN: %check_clang_tidy --match-partial-fixes %s modernize-pass-by-value %t -- -- -fno-delayed-template-parsing
2
3namespace {
4// POD types are trivially move constructible.
5struct POD {
6 int a, b, c;
7};
8
9struct Movable {
10 int a, b, c;
11 Movable() = default;
12 Movable(const Movable &) {}
13 Movable(Movable &&) {}
14};
15
16struct NotMovable {
17 NotMovable() = default;
18 NotMovable(const NotMovable &) = default;
19 NotMovable(NotMovable &&) = delete;
20 int a, b, c;
21};
22}
23
24struct A {
25 A(const Movable &M) : M(M) {}
26 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move [modernize-pass-by-value]
27 // CHECK-FIXES: A(Movable M) : M(std::move(M)) {}
28 Movable M;
29};
30
31// Test that we aren't modifying other things than a parameter.
32Movable GlobalObj;
33struct B {
34 B(const Movable &M) : M(GlobalObj) {}
35 Movable M;
36};
37
38// Test that a parameter with more than one reference to it won't be changed.
39struct C {
40 // Tests extra-reference in body.
41 C(const Movable &M) : M(M) { this->i = M.a; }
42
43 // Tests extra-reference in init-list.
44 C(const Movable &M, int) : M(M), i(M.a) {}
45 Movable M;
46 int i;
47};
48
49// Test that both declaration and definition are updated.
50struct D {
51 D(const Movable &M);
52 // CHECK-FIXES: D(Movable M);
53 Movable M;
54};
55D::D(const Movable &M) : M(M) {}
56// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
57// CHECK-FIXES: D::D(Movable M) : M(std::move(M)) {}
58
59// Test with default parameter.
60struct E {
61 E(const Movable &M = Movable()) : M(M) {}
62 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
63 // CHECK-FIXES: E(Movable M = Movable()) : M(std::move(M)) {}
64 Movable M;
65};
66
67// Test with object that can't be moved.
68struct F {
69 F(const NotMovable &NM) : NM(NM) {}
70 NotMovable NM;
71};
72
73// Test unnamed parameter in declaration.
74struct G {
75 G(const Movable &);
76 // CHECK-FIXES: G(Movable );
77 Movable M;
78};
79G::G(const Movable &M) : M(M) {}
80// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
81// CHECK-FIXES: G::G(Movable M) : M(std::move(M)) {}
82
83// Test parameter with and without qualifier.
84namespace ns_H {
85typedef ::Movable HMovable;
86}
87struct H {
88 H(const ns_H::HMovable &M);
89 // CHECK-FIXES: H(ns_H::HMovable M);
90 ns_H::HMovable M;
91};
92using namespace ns_H;
93H::H(const HMovable &M) : M(M) {}
94// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
95// CHECK-FIXES: H(HMovable M) : M(std::move(M)) {}
96
97// Try messing up with macros.
98#define MOVABLE_PARAM(Name) const Movable & Name
99// CHECK-FIXES: #define MOVABLE_PARAM(Name) const Movable & Name
100struct I {
101 I(MOVABLE_PARAM(M)) : M(M) {}
102 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
103 // CHECK-FIXES: I(MOVABLE_PARAM(M)) : M(M) {}
104 Movable M;
105};
106#undef MOVABLE_PARAM
107
108// Test that templates aren't modified.
109template <typename T> struct J {
110 J(const T &M) : M(M) {}
111 T M;
112};
113J<Movable> j1(Movable());
114J<NotMovable> j2(NotMovable());
115
116template<class T>
117struct MovableTemplateT
118{
119 MovableTemplateT() {}
120 MovableTemplateT(const MovableTemplateT& o) { }
121 MovableTemplateT(MovableTemplateT&& o) { }
122};
123
124template <class T>
125struct J2 {
126 J2(const MovableTemplateT<T>& A);
127 MovableTemplateT<T> M;
128};
129
130template <class T>
131J2<T>::J2(const MovableTemplateT<T>& A) : M(A) {}
132J2<int> j3(MovableTemplateT<int>{});
133
134struct K_Movable {
135 K_Movable() = default;
136 K_Movable(const K_Movable &) = default;
137 K_Movable(K_Movable &&o) { dummy = o.dummy; }
138 int dummy;
139};
140
141// Test with movable type with an user defined move constructor.
142struct K {
143 K(const K_Movable &M) : M(M) {}
144 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
145 // CHECK-FIXES: K(K_Movable M) : M(std::move(M)) {}
146 K_Movable M;
147};
148
149template <typename T> struct L {
150 L(const Movable &M) : M(M) {}
151 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
152 // CHECK-FIXES: L(Movable M) : M(std::move(M)) {}
153 Movable M;
154};
155L<int> l(Movable());
156
157// Test with a non-instantiated template class.
158template <typename T> struct N {
159 N(const Movable &M) : M(M) {}
160 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
161 // CHECK-FIXES: N(Movable M) : M(std::move(M)) {}
162
163 Movable M;
164 T A;
165};
166
167// Test with value parameter.
168struct O {
169 O(Movable M) : M(M) {}
170 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
171 // CHECK-FIXES: O(Movable M) : M(std::move(M)) {}
172 Movable M;
173};
174
175// Test with a const-value parameter.
176struct P {
177 P(const Movable M) : M(M) {}
178 Movable M;
179};
180
181// Test with multiples parameters where some need to be changed and some don't.
182// need to.
183struct Q {
184 Q(const Movable &A, const Movable &B, const Movable &C, double D)
185 : A(A), B(B), C(C), D(D) {}
186 // CHECK-MESSAGES: :[[@LINE-2]]:23: warning: pass by value and use std::move
187 // CHECK-MESSAGES: :[[@LINE-3]]:41: warning: pass by value and use std::move
188 // CHECK-FIXES: Q(const Movable &A, Movable B, Movable C, double D)
189 // CHECK-FIXES: : A(A), B(std::move(B)), C(std::move(C)), D(D) {}
190 const Movable &A;
191 Movable B;
192 Movable C;
193 double D;
194};
195
196// Test that value-parameters with a nested name specifier are left as-is.
197namespace ns_R {
198typedef ::Movable RMovable;
199}
200struct R {
201 R(ns_R::RMovable M) : M(M) {}
202 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: pass by value and use std::move
203 // CHECK-FIXES: R(ns_R::RMovable M) : M(std::move(M)) {}
204 ns_R::RMovable M;
205};
206
207// Test with rvalue parameter.
208struct S {
209 S(Movable &&M) : M(M) {}
210 Movable M;
211};
212
213template <typename T, int N> struct array { T A[N]; };
214
215// Test that types that are trivially copyable will not use std::move. This will
216// cause problems with performance-move-const-arg, as it will revert it.
217struct T {
218 T(array<int, 10> a) : a_(a) {}
219 array<int, 10> a_;
220};
221
222struct U {
223 U(const POD &M) : M(M) {}
224 POD M;
225};
226
227// The rewrite can't look through `typedefs` and `using`.
228// Test that we don't partially rewrite one decl without rewriting the other.
229using MovableConstRef = const Movable &;
230struct V {
231 V(MovableConstRef M);
232 // CHECK-FIXES: V(MovableConstRef M);
233 Movable M;
234};
235V::V(const Movable &M) : M(M) {}
236// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: pass by value and use std::move
237// CHECK-FIXES: V::V(const Movable &M) : M(M) {}
238
239// Test with paired lvalue/rvalue overloads.
240struct W1 {
241 W1(const Movable &M) : M(M) {}
242 W1(Movable &&M);
243 Movable M;
244};
245struct W2 {
246 W2(const Movable &M, int) : M(M) {}
247 W2(Movable &&M, int);
248 Movable M;
249};
250struct W3 {
251 W3(const W1 &, const Movable &M) : M(M) {}
252 W3(W1 &&, Movable &&M);
253 Movable M;
254};
255

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of clang-tools-extra/test/clang-tidy/checkers/modernize/pass-by-value.cpp