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