1 // RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
2
3 struct ExpensiveToCopyType {
4 ExpensiveToCopyType();
5 virtual ~ExpensiveToCopyType();
6 const ExpensiveToCopyType &reference() const;
7 void nonConstMethod();
8 bool constMethod() const;
9 };
10
11 struct TrivialToCopyType {
12 const TrivialToCopyType &reference() const;
13 };
14
15 struct WeirdCopyCtorType {
16 WeirdCopyCtorType();
17 WeirdCopyCtorType(const WeirdCopyCtorType &w, bool oh_yes = true);
18
19 void nonConstMethod();
20 bool constMethod() const;
21 };
22
23 ExpensiveToCopyType global_expensive_to_copy_type;
24
25 const ExpensiveToCopyType &ExpensiveTypeReference();
26 const ExpensiveToCopyType &freeFunctionWithArg(const ExpensiveToCopyType &);
27 const ExpensiveToCopyType &freeFunctionWithDefaultArg(
28 const ExpensiveToCopyType *arg = nullptr);
29 const TrivialToCopyType &TrivialTypeReference();
30
31 void mutate(ExpensiveToCopyType &);
32 void mutate(ExpensiveToCopyType *);
33 void useAsConstPointer(const ExpensiveToCopyType *);
34 void useAsConstReference(const ExpensiveToCopyType &);
35 void useByValue(ExpensiveToCopyType);
36
PositiveFunctionCall()37 void PositiveFunctionCall() {
38 const auto AutoAssigned = ExpensiveTypeReference();
39 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
40 // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
41 const auto AutoCopyConstructed(ExpensiveTypeReference());
42 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
43 // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
44 const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
45 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
46 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
47 const ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
48 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
49 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
50 }
51
PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType & Obj)52 void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {
53 const auto AutoAssigned = Obj.reference();
54 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
55 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
56 const auto AutoCopyConstructed(Obj.reference());
57 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
58 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
59 const ExpensiveToCopyType VarAssigned = Obj.reference();
60 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
61 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
62 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
63 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
64 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
65 }
66
PositiveMethodCallConstParam(const ExpensiveToCopyType Obj)67 void PositiveMethodCallConstParam(const ExpensiveToCopyType Obj) {
68 const auto AutoAssigned = Obj.reference();
69 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
70 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
71 const auto AutoCopyConstructed(Obj.reference());
72 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
73 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
74 const ExpensiveToCopyType VarAssigned = Obj.reference();
75 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
76 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
77 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
78 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
79 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
80 }
81
PositiveMethodCallConstPointerParam(const ExpensiveToCopyType * const Obj)82 void PositiveMethodCallConstPointerParam(const ExpensiveToCopyType *const Obj) {
83 const auto AutoAssigned = Obj->reference();
84 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
85 // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
86 const auto AutoCopyConstructed(Obj->reference());
87 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
88 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());
89 const ExpensiveToCopyType VarAssigned = Obj->reference();
90 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
91 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();
92 const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
93 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
94 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());
95 }
96
PositiveLocalConstValue()97 void PositiveLocalConstValue() {
98 const ExpensiveToCopyType Obj;
99 const auto UnnecessaryCopy = Obj.reference();
100 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
101 // CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();
102 }
103
PositiveLocalConstRef()104 void PositiveLocalConstRef() {
105 const ExpensiveToCopyType Obj;
106 const ExpensiveToCopyType &ConstReference = Obj.reference();
107 const auto UnnecessaryCopy = ConstReference.reference();
108 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
109 // CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();
110 }
111
PositiveLocalConstPointer()112 void PositiveLocalConstPointer() {
113 const ExpensiveToCopyType Obj;
114 const ExpensiveToCopyType *const ConstPointer = &Obj;
115 const auto UnnecessaryCopy = ConstPointer->reference();
116 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
117 // CHECK-FIXES: const auto& UnnecessaryCopy = ConstPointer->reference();
118 }
119
NegativeFunctionCallTrivialType()120 void NegativeFunctionCallTrivialType() {
121 const auto AutoAssigned = TrivialTypeReference();
122 const auto AutoCopyConstructed(TrivialTypeReference());
123 const TrivialToCopyType VarAssigned = TrivialTypeReference();
124 const TrivialToCopyType VarCopyConstructed(TrivialTypeReference());
125 }
126
NegativeStaticLocalVar(const ExpensiveToCopyType & Obj)127 void NegativeStaticLocalVar(const ExpensiveToCopyType &Obj) {
128 static const auto StaticVar = Obj.reference();
129 }
130
PositiveFunctionCallExpensiveTypeNonConstVariable()131 void PositiveFunctionCallExpensiveTypeNonConstVariable() {
132 auto AutoAssigned = ExpensiveTypeReference();
133 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoAssigned' is copy-constructed from a const reference but is only used as const reference; consider making it a const reference [performance-unnecessary-copy-initialization]
134 // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
135 auto AutoCopyConstructed(ExpensiveTypeReference());
136 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'
137 // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
138 ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
139 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'
140 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
141 ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
142 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'
143 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
144 }
145
positiveNonConstVarInCodeBlock(const ExpensiveToCopyType & Obj)146 void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {
147 {
148 auto Assigned = Obj.reference();
149 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'
150 // CHECK-FIXES: const auto& Assigned = Obj.reference();
151 Assigned.reference();
152 useAsConstReference(Assigned);
153 useByValue(Assigned);
154 }
155 }
156
negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType & Obj)157 void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {
158 {
159 auto NonConstInvoked = Obj.reference();
160 // CHECK-FIXES: auto NonConstInvoked = Obj.reference();
161 NonConstInvoked.nonConstMethod();
162 }
163 {
164 auto Reassigned = Obj.reference();
165 // CHECK-FIXES: auto Reassigned = Obj.reference();
166 Reassigned = ExpensiveToCopyType();
167 }
168 {
169 auto MutatedByReference = Obj.reference();
170 // CHECK-FIXES: auto MutatedByReference = Obj.reference();
171 mutate(MutatedByReference);
172 }
173 {
174 auto MutatedByPointer = Obj.reference();
175 // CHECK-FIXES: auto MutatedByPointer = Obj.reference();
176 mutate(&MutatedByPointer);
177 }
178 }
179
PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType & Obj)180 void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {
181 const auto AutoAssigned = Obj.reference();
182 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
183 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
184 }
185
NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType & Obj)186 void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {
187 const auto AutoAssigned = Obj.reference();
188 const auto AutoCopyConstructed(Obj.reference());
189 const ExpensiveToCopyType VarAssigned = Obj.reference();
190 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
191 mutate(&Obj);
192 }
193
PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj)194 void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {
195 const auto AutoAssigned = Obj.reference();
196 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
197 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
198 }
199
NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj)200 void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {
201 Obj.nonConstMethod();
202 const auto AutoAssigned = Obj.reference();
203 }
204
PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType * const Obj)205 void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {
206 const auto AutoAssigned = Obj->reference();
207 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
208 // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
209 Obj->constMethod();
210 }
211
NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType * const Obj)212 void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {
213 const auto AutoAssigned = Obj->reference();
214 const auto AutoCopyConstructed(Obj->reference());
215 const ExpensiveToCopyType VarAssigned = Obj->reference();
216 const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
217 mutate(Obj);
218 }
219
PositiveLocalVarIsNotModified()220 void PositiveLocalVarIsNotModified() {
221 ExpensiveToCopyType LocalVar;
222 const auto AutoAssigned = LocalVar.reference();
223 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
224 // CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();
225 }
226
NegativeLocalVarIsModified()227 void NegativeLocalVarIsModified() {
228 ExpensiveToCopyType Obj;
229 const auto AutoAssigned = Obj.reference();
230 Obj = AutoAssigned;
231 }
232
233 struct NegativeConstructor {
NegativeConstructorNegativeConstructor234 NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}
235 ExpensiveToCopyType Obj;
236 };
237
238 #define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE) \
239 void functionWith##TYPE(const TYPE &T) { \
240 auto AssignedInMacro = T.reference(); \
241 } \
242 // Ensure fix is not applied.
243 // CHECK-FIXES: auto AssignedInMacro = T.reference();
244
UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)245 UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)
246 // CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' is copy-constructed
247
248 #define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT
249
250 void PositiveMacroArgument(const ExpensiveToCopyType &Obj) {
251 UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());
252 // CHECK-MESSAGES: [[@LINE-1]]:48: warning: the variable 'CopyInMacroArg' is copy-constructed
253 // Ensure fix is not applied.
254 // CHECK-FIXES: auto CopyInMacroArg = Obj.reference()
255 }
256
PositiveLocalCopyConstMethodInvoked()257 void PositiveLocalCopyConstMethodInvoked() {
258 ExpensiveToCopyType orig;
259 ExpensiveToCopyType copy_1 = orig;
260 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_1' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
261 // CHECK-FIXES: const ExpensiveToCopyType& copy_1 = orig;
262 copy_1.constMethod();
263 orig.constMethod();
264 }
265
PositiveLocalCopyUsingExplicitCopyCtor()266 void PositiveLocalCopyUsingExplicitCopyCtor() {
267 ExpensiveToCopyType orig;
268 ExpensiveToCopyType copy_2(orig);
269 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_2'
270 // CHECK-FIXES: const ExpensiveToCopyType& copy_2(orig);
271 copy_2.constMethod();
272 orig.constMethod();
273 }
274
PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType & orig)275 void PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType &orig) {
276 ExpensiveToCopyType copy_3 = orig;
277 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_3'
278 // CHECK-FIXES: const ExpensiveToCopyType& copy_3 = orig;
279 copy_3.constMethod();
280 }
281
PositiveLocalCopyUsedAsConstRef()282 void PositiveLocalCopyUsedAsConstRef() {
283 ExpensiveToCopyType orig;
284 ExpensiveToCopyType copy_4 = orig;
285 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_4'
286 // CHECK-FIXES: const ExpensiveToCopyType& copy_4 = orig;
287 useAsConstReference(orig);
288 }
289
PositiveLocalCopyTwice()290 void PositiveLocalCopyTwice() {
291 ExpensiveToCopyType orig;
292 ExpensiveToCopyType copy_5 = orig;
293 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_5'
294 // CHECK-FIXES: const ExpensiveToCopyType& copy_5 = orig;
295 ExpensiveToCopyType copy_6 = copy_5;
296 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_6'
297 // CHECK-FIXES: const ExpensiveToCopyType& copy_6 = copy_5;
298 copy_5.constMethod();
299 copy_6.constMethod();
300 orig.constMethod();
301 }
302
303
PositiveLocalCopyWeirdCopy()304 void PositiveLocalCopyWeirdCopy() {
305 WeirdCopyCtorType orig;
306 WeirdCopyCtorType weird_1(orig);
307 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_1'
308 // CHECK-FIXES: const WeirdCopyCtorType& weird_1(orig);
309 weird_1.constMethod();
310
311 WeirdCopyCtorType weird_2 = orig;
312 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_2'
313 // CHECK-FIXES: const WeirdCopyCtorType& weird_2 = orig;
314 weird_2.constMethod();
315 }
316
NegativeLocalCopySimpleTypes()317 void NegativeLocalCopySimpleTypes() {
318 int i1 = 0;
319 int i2 = i1;
320 }
321
NegativeLocalCopyCopyIsModified()322 void NegativeLocalCopyCopyIsModified() {
323 ExpensiveToCopyType orig;
324 ExpensiveToCopyType neg_copy_1 = orig;
325 neg_copy_1.nonConstMethod();
326 }
327
NegativeLocalCopyOriginalIsModified()328 void NegativeLocalCopyOriginalIsModified() {
329 ExpensiveToCopyType orig;
330 ExpensiveToCopyType neg_copy_2 = orig;
331 orig.nonConstMethod();
332 }
333
NegativeLocalCopyUsedAsRefArg()334 void NegativeLocalCopyUsedAsRefArg() {
335 ExpensiveToCopyType orig;
336 ExpensiveToCopyType neg_copy_3 = orig;
337 mutate(neg_copy_3);
338 }
339
NegativeLocalCopyUsedAsPointerArg()340 void NegativeLocalCopyUsedAsPointerArg() {
341 ExpensiveToCopyType orig;
342 ExpensiveToCopyType neg_copy_4 = orig;
343 mutate(&neg_copy_4);
344 }
345
NegativeLocalCopyCopyFromGlobal()346 void NegativeLocalCopyCopyFromGlobal() {
347 ExpensiveToCopyType neg_copy_5 = global_expensive_to_copy_type;
348 }
349
NegativeLocalCopyCopyToStatic()350 void NegativeLocalCopyCopyToStatic() {
351 ExpensiveToCopyType orig;
352 static ExpensiveToCopyType neg_copy_6 = orig;
353 }
354
NegativeLocalCopyNonConstInForLoop()355 void NegativeLocalCopyNonConstInForLoop() {
356 ExpensiveToCopyType orig;
357 for (ExpensiveToCopyType neg_copy_7 = orig; orig.constMethod();
358 orig.nonConstMethod()) {
359 orig.constMethod();
360 }
361 }
362
NegativeLocalCopyWeirdNonCopy()363 void NegativeLocalCopyWeirdNonCopy() {
364 WeirdCopyCtorType orig;
365 WeirdCopyCtorType neg_weird_1(orig, false);
366 WeirdCopyCtorType neg_weird_2(orig, true);
367 }
WarningOnlyMultiDeclStmt()368 void WarningOnlyMultiDeclStmt() {
369 ExpensiveToCopyType orig;
370 ExpensiveToCopyType copy = orig, copy2;
371 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
372 // CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;
373 }
374
375 class Element {};
376 class Container {
377 public:
378 class Iterator {
379 public:
380 void operator++();
381 Element operator*();
382 bool operator!=(const Iterator &);
383 WeirdCopyCtorType c;
384 };
385 const Iterator &begin() const;
386 const Iterator &end() const;
387 };
388
implicitVarFalsePositive()389 void implicitVarFalsePositive() {
390 for (const Element &E : Container()) {
391 }
392 }
393
394 // This should not trigger the check as the argument could introduce an alias.
negativeInitializedFromFreeFunctionWithArg()395 void negativeInitializedFromFreeFunctionWithArg() {
396 ExpensiveToCopyType Orig;
397 const ExpensiveToCopyType Copy = freeFunctionWithArg(Orig);
398 }
399
negativeInitializedFromFreeFunctionWithDefaultArg()400 void negativeInitializedFromFreeFunctionWithDefaultArg() {
401 const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg();
402 }
403
negativeInitialzedFromFreeFunctionWithNonDefaultArg()404 void negativeInitialzedFromFreeFunctionWithNonDefaultArg() {
405 ExpensiveToCopyType Orig;
406 const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg(&Orig);
407 }
408
409 namespace std {
410 inline namespace __1 {
411
412 template <class>
413 class function;
414 template <class R, class... ArgTypes>
415 class function<R(ArgTypes...)> {
416 public:
417 function();
418 function(const function &Other);
419 R operator()(ArgTypes... Args) const;
420 };
421
422 } // namespace __1
423 } // namespace std
424
negativeStdFunction()425 void negativeStdFunction() {
426 std::function<int()> Orig;
427 std::function<int()> Copy = Orig;
428 int i = Orig();
429 }
430
431 using Functor = std::function<int()>;
432
negativeAliasedStdFunction()433 void negativeAliasedStdFunction() {
434 Functor Orig;
435 Functor Copy = Orig;
436 int i = Orig();
437 }
438
439 typedef std::function<int()> TypedefFunc;
440
negativeTypedefedStdFunction()441 void negativeTypedefedStdFunction() {
442 TypedefFunc Orig;
443 TypedefFunc Copy = Orig;
444 int i = Orig();
445 }
446
447 namespace fake {
448 namespace std {
449 template <class R, class... Args>
450 struct function {
451 // Custom copy constructor makes it expensive to copy;
452 function(const function &);
453 };
454 } // namespace std
455
positiveFakeStdFunction(std::function<void (int)> F)456 void positiveFakeStdFunction(std::function<void(int)> F) {
457 auto Copy = F;
458 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'Copy' of the variable 'F' is never modified;
459 // CHECK-FIXES: const auto& Copy = F;
460 }
461
462 } // namespace fake
463
positiveInvokedOnStdFunction(std::function<void (const ExpensiveToCopyType &)> Update,const ExpensiveToCopyType Orig)464 void positiveInvokedOnStdFunction(
465 std::function<void(const ExpensiveToCopyType &)> Update,
466 const ExpensiveToCopyType Orig) {
467 auto Copy = Orig.reference();
468 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'Copy' is copy-constructed from a const reference
469 // CHECK-FIXES: const auto& Copy = Orig.reference();
470 Update(Copy);
471 }
472
negativeInvokedOnStdFunction(std::function<void (ExpensiveToCopyType &)> Update,const ExpensiveToCopyType Orig)473 void negativeInvokedOnStdFunction(
474 std::function<void(ExpensiveToCopyType &)> Update,
475 const ExpensiveToCopyType Orig) {
476 auto Copy = Orig.reference();
477 Update(Copy);
478 }
479
negativeCopiedFromReferenceToModifiedVar()480 void negativeCopiedFromReferenceToModifiedVar() {
481 ExpensiveToCopyType Orig;
482 const auto &Ref = Orig;
483 const auto NecessaryCopy = Ref;
484 Orig.nonConstMethod();
485 }
486
positiveCopiedFromReferenceToConstVar()487 void positiveCopiedFromReferenceToConstVar() {
488 ExpensiveToCopyType Orig;
489 const auto &Ref = Orig;
490 const auto UnnecessaryCopy = Ref;
491 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: local copy 'UnnecessaryCopy' of
492 // CHECK-FIXES: const auto& UnnecessaryCopy = Ref;
493 Orig.constMethod();
494 }
495
negativeCopiedFromGetterOfReferenceToModifiedVar()496 void negativeCopiedFromGetterOfReferenceToModifiedVar() {
497 ExpensiveToCopyType Orig;
498 const auto &Ref = Orig.reference();
499 const auto NecessaryCopy = Ref.reference();
500 Orig.nonConstMethod();
501 }
502
positiveCopiedFromGetterOfReferenceToConstVar()503 void positiveCopiedFromGetterOfReferenceToConstVar() {
504 ExpensiveToCopyType Orig;
505 const auto &Ref = Orig.reference();
506 auto UnnecessaryCopy = Ref.reference();
507 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'UnnecessaryCopy' is
508 // CHECK-FIXES: const auto& UnnecessaryCopy = Ref.reference();
509 Orig.constMethod();
510 }
511