1// RUN: %check_clang_tidy --match-partial-fixes %s performance-unnecessary-value-param %t -- -- -fno-delayed-template-parsing
2
3// CHECK-FIXES: #include <utility>
4
5namespace std {
6template <typename>
7struct remove_reference;
8
9template <typename _Tp>
10struct remove_reference {
11 typedef _Tp type;
12};
13
14template <typename _Tp>
15struct remove_reference<_Tp &> {
16 typedef _Tp type;
17};
18
19template <typename _Tp>
20struct remove_reference<_Tp &&> {
21 typedef _Tp type;
22};
23
24template <typename _Tp>
25constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {
26 return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);
27}
28} // namespace std
29
30struct ExpensiveToCopyType {
31 const ExpensiveToCopyType & constReference() const {
32 return *this;
33 }
34 void nonConstMethod();
35 virtual ~ExpensiveToCopyType();
36};
37
38void mutate(ExpensiveToCopyType &);
39void mutate(ExpensiveToCopyType *);
40void useAsConstReference(const ExpensiveToCopyType &);
41void useByValue(ExpensiveToCopyType);
42
43template <class T> class Vector {
44 public:
45 using iterator = T*;
46 using const_iterator = const T*;
47
48 Vector(const Vector&);
49 Vector& operator=(const Vector&);
50
51 iterator begin();
52 iterator end();
53 const_iterator begin() const;
54 const_iterator end() const;
55};
56
57// This class simulates std::pair<>. It is trivially copy constructible
58// and trivially destructible, but not trivially copy assignable.
59class SomewhatTrivial {
60 public:
61 SomewhatTrivial();
62 SomewhatTrivial(const SomewhatTrivial&) = default;
63 ~SomewhatTrivial() = default;
64 SomewhatTrivial& operator=(const SomewhatTrivial&);
65};
66
67struct MoveOnlyType {
68 MoveOnlyType(const MoveOnlyType &) = delete;
69 MoveOnlyType(MoveOnlyType &&) = default;
70 ~MoveOnlyType();
71 void constMethod() const;
72};
73
74struct ExpensiveMovableType {
75 ExpensiveMovableType();
76 ExpensiveMovableType(ExpensiveMovableType &&);
77 ExpensiveMovableType(const ExpensiveMovableType &) = default;
78 ExpensiveMovableType &operator=(const ExpensiveMovableType &) = default;
79 ExpensiveMovableType &operator=(ExpensiveMovableType &&);
80 ~ExpensiveMovableType();
81};
82
83void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
84// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
85void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
86 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]
87 // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
88}
89
90void positiveExpensiveValue(ExpensiveToCopyType Obj);
91// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
92void positiveExpensiveValue(ExpensiveToCopyType Obj) {
93 // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
94 // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
95 Obj.constReference();
96 useAsConstReference(Obj);
97 auto Copy = Obj;
98 useByValue(Obj);
99}
100
101void positiveVector(Vector<ExpensiveToCopyType> V) {
102 // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'V' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]
103 // CHECK-FIXES: void positiveVector(const Vector<ExpensiveToCopyType>& V) {
104 for (const auto& Obj : V) {
105 useByValue(Obj);
106 }
107}
108
109void positiveWithComment(const ExpensiveToCopyType /* important */ S);
110// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
111void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
112 // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
113 // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
114}
115
116void positiveUnnamedParam(const ExpensiveToCopyType) {
117 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
118 // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
119}
120
121void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
122// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
123void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
124 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
125 // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
126 // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
127}
128
129struct PositiveConstValueConstructor {
130 PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
131 // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
132 // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
133};
134
135void negativeArray(const ExpensiveToCopyType[]) {
136}
137
138void negativePointer(ExpensiveToCopyType* Obj) {
139}
140
141void negativeConstPointer(const ExpensiveToCopyType* Obj) {
142}
143
144void negativeConstReference(const ExpensiveToCopyType& Obj) {
145}
146
147void negativeReference(ExpensiveToCopyType& Obj) {
148}
149
150void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
151}
152
153void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
154}
155
156void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
157}
158
159void negativeConstBuiltIn(const int I) {
160}
161
162void negativeValueBuiltIn(int I) {
163}
164
165void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
166 mutate(Obj);
167}
168
169void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
170 mutate(&Obj);
171}
172
173void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
174 Obj = ExpensiveToCopyType();
175}
176
177void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
178 Obj.nonConstMethod();
179}
180
181struct PositiveValueUnusedConstructor {
182 PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
183 // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
184 // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
185};
186
187struct PositiveValueCopiedConstructor {
188 PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
189 // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
190 // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
191 ExpensiveToCopyType Field;
192};
193
194struct PositiveValueMovableConstructor {
195 PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {}
196 // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy'
197 // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {}
198 ExpensiveMovableType Field;
199};
200
201struct NegativeValueMovedConstructor {
202 NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast<ExpensiveMovableType &&>(Copy)) {}
203 ExpensiveMovableType Field;
204};
205
206template <typename T>
207struct Container {
208 typedef const T & const_reference;
209};
210
211void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
212}
213
214#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() \
215 void inMacro(const ExpensiveToCopyType T) { \
216 } \
217// Ensure fix is not applied.
218// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
219
220UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
221// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
222
223#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT) \
224 ARGUMENT
225
226UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
227// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
228// CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
229
230struct VirtualMethod {
231 virtual ~VirtualMethod() {}
232 virtual void handle(ExpensiveToCopyType T) const = 0;
233};
234
235struct NegativeOverriddenMethod : public VirtualMethod {
236 void handle(ExpensiveToCopyType Overridden) const {
237 // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
238 }
239};
240
241struct VirtualMethodWarningOnly {
242 virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
243 // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'T' is copied
244 // CHECK-FIXES: virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}
245 virtual ~VirtualMethodWarningOnly() {}
246};
247
248struct PositiveNonVirualMethod {
249 void method(const ExpensiveToCopyType T) {}
250 // CHECK-MESSAGES: [[@LINE-1]]:41: warning: the const qualified parameter 'T' is copied
251 // CHECK-FIXES: void method(const ExpensiveToCopyType& T) {}
252};
253
254struct NegativeDeletedMethod {
255 ~NegativeDeletedMethod() {}
256 NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
257 // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
258};
259
260void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {
261 M.constMethod();
262}
263
264void PositiveMoveOnCopyConstruction(ExpensiveMovableType E) {
265 auto F = E;
266 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: parameter 'E' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]
267 // CHECK-FIXES: auto F = std::move(E);
268}
269
270void PositiveConstRefNotMoveSinceReferencedMultipleTimes(ExpensiveMovableType E) {
271 // CHECK-MESSAGES: [[@LINE-1]]:79: warning: the parameter 'E' is copied
272 // CHECK-FIXES: void PositiveConstRefNotMoveSinceReferencedMultipleTimes(const ExpensiveMovableType& E) {
273 auto F = E;
274 auto G = E;
275}
276
277void PositiveMoveOnCopyAssignment(ExpensiveMovableType E) {
278 ExpensiveMovableType F;
279 F = E;
280 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: parameter 'E' is passed by value
281 // CHECK-FIXES: F = std::move(E);
282}
283
284struct NotCopyAssigned {
285 NotCopyAssigned &operator=(const ExpensiveMovableType &);
286};
287
288void PositiveNoMoveForNonCopyAssigmentOperator(ExpensiveMovableType E) {
289 // CHECK-MESSAGES: [[@LINE-1]]:69: warning: the parameter 'E' is copied
290 // CHECK-FIXES: void PositiveNoMoveForNonCopyAssigmentOperator(const ExpensiveMovableType& E) {
291 NotCopyAssigned N;
292 N = E;
293}
294
295// The argument could be moved but is not since copy statement is inside a loop.
296void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {
297 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied
298 // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) {
299 for (;;) {
300 auto F = E;
301 }
302}
303
304void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) {
305 // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' is copied
306 // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const ExpensiveToCopyType& T) {
307 auto U = T;
308}
309
310void PositiveConstRefNotMoveAssignable(ExpensiveToCopyType A) {
311 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the parameter 'A' is copied
312 // CHECK-FIXES: void PositiveConstRefNotMoveAssignable(const ExpensiveToCopyType& A) {
313 ExpensiveToCopyType B;
314 B = A;
315}
316
317// Case where parameter in declaration is already const-qualified but not in
318// implementation. Make sure a second 'const' is not added to the declaration.
319void PositiveConstDeclaration(const ExpensiveToCopyType A);
320// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);
321void PositiveConstDeclaration(ExpensiveToCopyType A) {
322 // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied
323 // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {
324}
325
326void PositiveNonConstDeclaration(ExpensiveToCopyType A);
327// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);
328void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {
329 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A'
330 // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {
331}
332
333void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {
334 // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied
335 // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(const ExpensiveToCopyType& A) {
336}
337
338void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {
339 // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied
340 // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {
341}
342
343void ReferenceFunctionByCallingIt() {
344 PositiveMessageAndFixAsFunctionIsCalled(A: ExpensiveToCopyType());
345}
346
347// Virtual method overrides of dependent types cannot be recognized unless they
348// are marked as override or final. Test that check is not triggered on methods
349// marked with override or final.
350template <typename T>
351struct NegativeDependentTypeInterface {
352 virtual void Method(ExpensiveToCopyType E) = 0;
353};
354
355template <typename T>
356struct NegativeOverrideImpl : public NegativeDependentTypeInterface<T> {
357 void Method(ExpensiveToCopyType E) override {}
358};
359
360template <typename T>
361struct NegativeFinalImpl : public NegativeDependentTypeInterface<T> {
362 void Method(ExpensiveToCopyType E) final {}
363};
364
365struct PositiveConstructor {
366 PositiveConstructor(ExpensiveToCopyType E) : E(E) {}
367 // CHECK-MESSAGES: [[@LINE-1]]:43: warning: the parameter 'E' is copied
368 // CHECK-FIXES: PositiveConstructor(const ExpensiveToCopyType& E) : E(E) {}
369
370 ExpensiveToCopyType E;
371};
372
373struct NegativeUsingConstructor : public PositiveConstructor {
374 using PositiveConstructor::PositiveConstructor;
375};
376
377void fun() {
378 ExpensiveToCopyType E;
379 NegativeUsingConstructor S(E);
380}
381
382struct B {
383 static void bar(ExpensiveMovableType a, ExpensiveMovableType b);
384};
385
386template <typename T>
387void NegativeCallWithDependentAndNondependentArgs(ExpensiveMovableType a, T b) {
388 B::bar(a: std::move(a), b);
389}
390

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang-tools-extra/test/clang-tidy/checkers/performance/unnecessary-value-param.cpp