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

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