941 lines · cpp
1// RUN: %check_clang_tidy -std=c++17-or-later %s performance-unnecessary-copy-initialization %t2 3template <typename T>4struct Iterator {5 void operator++();6 T &operator*() const;7 bool operator!=(const Iterator &) const;8 typedef const T &const_reference;9};10 11template <typename T>12struct ConstIterator {13 void operator++();14 const T &operator*() const;15 bool operator!=(const ConstIterator &) const;16 typedef const T &const_reference;17};18 19struct ExpensiveToCopyType {20 ExpensiveToCopyType();21 virtual ~ExpensiveToCopyType();22 const ExpensiveToCopyType &reference() const;23 using ConstRef = const ExpensiveToCopyType &;24 ConstRef referenceWithAlias() const;25 const ExpensiveToCopyType *pointer() const;26 void nonConstMethod();27 bool constMethod() const;28 template <typename A>29 const A &templatedAccessor() const;30 operator int() const; // Implicit conversion to int.31 32 static const ExpensiveToCopyType &instance();33};34 35template <typename T>36struct Container {37 using reference = T&;38 using const_reference = const T&;39 40 bool empty() const;41 const T& operator[](int) const;42 const T& operator[](int);43 Iterator<T> begin();44 Iterator<T> end();45 ConstIterator<T> begin() const;46 ConstIterator<T> end() const;47 void nonConstMethod();48 bool constMethod() const;49 50 reference at(int) const;51 const_reference at(int);52 53};54 55using ExpensiveToCopyContainerAlias = Container<ExpensiveToCopyType>;56 57struct TrivialToCopyType {58 const TrivialToCopyType &reference() const;59};60 61struct WeirdCopyCtorType {62 WeirdCopyCtorType();63 WeirdCopyCtorType(const WeirdCopyCtorType &w, bool oh_yes = true);64 65 void nonConstMethod();66 bool constMethod() const;67};68 69ExpensiveToCopyType global_expensive_to_copy_type;70 71const ExpensiveToCopyType &ExpensiveTypeReference();72const ExpensiveToCopyType &freeFunctionWithArg(const ExpensiveToCopyType &);73const ExpensiveToCopyType &freeFunctionWithDefaultArg(74 const ExpensiveToCopyType *arg = nullptr);75const TrivialToCopyType &TrivialTypeReference();76 77void mutate(ExpensiveToCopyType &);78void mutate(ExpensiveToCopyType *);79void useAsConstPointer(const ExpensiveToCopyType *);80void useAsConstReference(const ExpensiveToCopyType &);81void useByValue(ExpensiveToCopyType);82 83void PositiveFunctionCall() {84 const auto AutoAssigned = ExpensiveTypeReference();85 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' of type 'const ExpensiveToCopyType' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]86 // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();87 AutoAssigned.constMethod();88 89 const auto AutoCopyConstructed(ExpensiveTypeReference());90 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'91 // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());92 AutoCopyConstructed.constMethod();93 94 const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();95 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'96 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();97 VarAssigned.constMethod();98 99 const ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());100 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'101 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());102 VarCopyConstructed.constMethod();103}104 105void PositiveStaticMethodCall() {106 const auto AutoAssigned = ExpensiveToCopyType::instance();107 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' of type 'const ExpensiveToCopyType' is copy-constructed from a const reference; consider making it a const reference [performance-unnecessary-copy-initialization]108 // CHECK-FIXES: const auto& AutoAssigned = ExpensiveToCopyType::instance();109 AutoAssigned.constMethod();110 111 const auto AutoCopyConstructed(ExpensiveToCopyType::instance());112 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'113 // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveToCopyType::instance());114 AutoCopyConstructed.constMethod();115 116 const ExpensiveToCopyType VarAssigned = ExpensiveToCopyType::instance();117 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'118 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveToCopyType::instance();119 VarAssigned.constMethod();120 121 const ExpensiveToCopyType VarCopyConstructed(ExpensiveToCopyType::instance());122 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'123 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveToCopyType::instance());124 VarCopyConstructed.constMethod();125}126 127void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {128 const auto AutoAssigned = Obj.reference();129 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'130 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();131 AutoAssigned.constMethod();132 133 const auto AutoCopyConstructed(Obj.reference());134 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'135 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());136 AutoCopyConstructed.constMethod();137 138 const ExpensiveToCopyType VarAssigned = Obj.reference();139 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'140 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();141 VarAssigned.constMethod();142 143 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());144 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'145 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());146 VarCopyConstructed.constMethod();147}148 149void PositiveMethodCallConstParam(const ExpensiveToCopyType Obj) {150 const auto AutoAssigned = Obj.reference();151 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'152 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();153 AutoAssigned.constMethod();154 155 const auto AutoCopyConstructed(Obj.reference());156 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'157 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());158 AutoCopyConstructed.constMethod();159 160 const ExpensiveToCopyType VarAssigned = Obj.reference();161 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'162 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();163 VarAssigned.constMethod();164 165 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());166 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'167 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());168 VarCopyConstructed.constMethod();169}170 171void PositiveMethodCallConstPointerParam(const ExpensiveToCopyType *const Obj) {172 const auto AutoAssigned = Obj->reference();173 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'174 // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();175 AutoAssigned.constMethod();176 177 const auto AutoCopyConstructed(Obj->reference());178 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'179 // CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());180 AutoCopyConstructed.constMethod();181 182 const ExpensiveToCopyType VarAssigned = Obj->reference();183 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'184 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();185 VarAssigned.constMethod();186 187 const ExpensiveToCopyType VarCopyConstructed(Obj->reference());188 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'189 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());190 VarCopyConstructed.constMethod();191}192 193void PositiveOperatorCallConstReferenceParam(const Container<ExpensiveToCopyType> &C) {194 const auto AutoAssigned = C[42];195 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'196 // CHECK-FIXES: const auto& AutoAssigned = C[42];197 AutoAssigned.constMethod();198 199 const auto AutoCopyConstructed(C[42]);200 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'201 // CHECK-FIXES: const auto& AutoCopyConstructed(C[42]);202 AutoCopyConstructed.constMethod();203 204 const ExpensiveToCopyType VarAssigned = C[42];205 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'206 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = C[42];207 VarAssigned.constMethod();208 209 const ExpensiveToCopyType VarCopyConstructed(C[42]);210 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'211 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(C[42]);212 VarCopyConstructed.constMethod();213}214 215void PositiveOperatorCallConstValueParam(const Container<ExpensiveToCopyType> C) {216 const auto AutoAssigned = C[42];217 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'218 // CHECK-FIXES: const auto& AutoAssigned = C[42];219 AutoAssigned.constMethod();220 221 const auto AutoCopyConstructed(C[42]);222 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'223 // CHECK-FIXES: const auto& AutoCopyConstructed(C[42]);224 AutoCopyConstructed.constMethod();225 226 const ExpensiveToCopyType VarAssigned = C[42];227 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'228 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = C[42];229 VarAssigned.constMethod();230 231 const ExpensiveToCopyType VarCopyConstructed(C[42]);232 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'233 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(C[42]);234 VarCopyConstructed.constMethod();235}236 237void PositiveOperatorValueParam(Container<ExpensiveToCopyType> C) {238 const auto AutoAssigned = C[42];239 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'240 // CHECK-FIXES: const auto& AutoAssigned = C[42];241 AutoAssigned.constMethod();242 243 const auto AutoCopyConstructed(C[42]);244 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'245 // CHECK-FIXES: const auto& AutoCopyConstructed(C[42]);246 AutoCopyConstructed.constMethod();247 248 const ExpensiveToCopyType VarAssigned = C.at(42);249 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'250 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = C.at(42);251 VarAssigned.constMethod();252 253 const ExpensiveToCopyType VarCopyConstructed(C.at(42));254 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'255 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(C.at(42));256 VarCopyConstructed.constMethod();257}258 259void PositiveOperatorCallConstValueParamAlias(const ExpensiveToCopyContainerAlias C) {260 const auto AutoAssigned = C[42];261 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'262 // CHECK-FIXES: const auto& AutoAssigned = C[42];263 AutoAssigned.constMethod();264 265 const auto AutoCopyConstructed(C[42]);266 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'267 // CHECK-FIXES: const auto& AutoCopyConstructed(C[42]);268 AutoCopyConstructed.constMethod();269 270 const ExpensiveToCopyType VarAssigned = C[42];271 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'272 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = C[42];273 VarAssigned.constMethod();274 275 const ExpensiveToCopyType VarCopyConstructed(C[42]);276 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'277 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(C[42]);278 VarCopyConstructed.constMethod();279}280 281void PositiveOperatorCallConstPtrParam(const Container<ExpensiveToCopyType>* C) {282 const auto AutoAssigned = (*C)[42];283 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'284 // CHECK-FIXES: const auto& AutoAssigned = (*C)[42];285 AutoAssigned.constMethod();286 287 const auto AutoCopyConstructed((*C)[42]);288 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'289 // CHECK-FIXES: const auto& AutoCopyConstructed((*C)[42]);290 AutoCopyConstructed.constMethod();291 292 const ExpensiveToCopyType VarAssigned = C->at(42);293 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'294 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = C->at(42);295 VarAssigned.constMethod();296 297 const ExpensiveToCopyType VarCopyConstructed(C->at(42));298 // CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'299 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(C->at(42));300 VarCopyConstructed.constMethod();301}302 303void PositiveLocalConstValue() {304 const ExpensiveToCopyType Obj;305 const auto UnnecessaryCopy = Obj.reference();306 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'307 // CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();308 UnnecessaryCopy.constMethod();309}310 311void PositiveLocalConstRef() {312 const ExpensiveToCopyType Obj;313 const ExpensiveToCopyType &ConstReference = Obj.reference();314 const auto UnnecessaryCopy = ConstReference.reference();315 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'316 // CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();317 UnnecessaryCopy.constMethod();318}319 320void PositiveLocalConstPointer() {321 const ExpensiveToCopyType Obj;322 const ExpensiveToCopyType *const ConstPointer = &Obj;323 const auto UnnecessaryCopy = ConstPointer->reference();324 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'325 // CHECK-FIXES: const auto& UnnecessaryCopy = ConstPointer->reference();326 UnnecessaryCopy.constMethod();327}328 329void NegativeFunctionCallTrivialType() {330 const auto AutoAssigned = TrivialTypeReference();331 const auto AutoCopyConstructed(TrivialTypeReference());332 const TrivialToCopyType VarAssigned = TrivialTypeReference();333 const TrivialToCopyType VarCopyConstructed(TrivialTypeReference());334}335 336void NegativeStaticLocalVar(const ExpensiveToCopyType &Obj) {337 static const auto StaticVar = Obj.reference();338}339 340void PositiveFunctionCallExpensiveTypeNonConstVariable() {341 auto AutoAssigned = ExpensiveTypeReference();342 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoAssigned' of type 'ExpensiveToCopyType' is copy-constructed from a const reference but is only used as const reference; consider making it a const reference [performance-unnecessary-copy-initialization]343 // CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();344 AutoAssigned.constMethod();345 346 auto AutoCopyConstructed(ExpensiveTypeReference());347 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'348 // CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());349 AutoCopyConstructed.constMethod();350 351 ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();352 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'353 // CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();354 VarAssigned.constMethod();355 356 ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());357 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'358 // CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());359 VarCopyConstructed.constMethod();360}361 362void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {363 {364 auto Assigned = Obj.reference();365 // CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'366 // CHECK-FIXES: const auto& Assigned = Obj.reference();367 Assigned.reference();368 useAsConstReference(Assigned);369 useByValue(Assigned);370 }371}372 373void positiveNonConstVarInCodeBlockWithAlias(const ExpensiveToCopyType &Obj) {374 {375 const ExpensiveToCopyType Assigned = Obj.referenceWithAlias();376 // CHECK-MESSAGES: [[@LINE-1]]:31: warning: the const qualified variable377 // CHECK-FIXES: const ExpensiveToCopyType& Assigned = Obj.referenceWithAlias();378 useAsConstReference(Assigned);379 }380}381 382void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {383 {384 auto NonConstInvoked = Obj.reference();385 // CHECK-FIXES: auto NonConstInvoked = Obj.reference();386 NonConstInvoked.nonConstMethod();387 }388 {389 auto Reassigned = Obj.reference();390 // CHECK-FIXES: auto Reassigned = Obj.reference();391 Reassigned = ExpensiveToCopyType();392 }393 {394 auto MutatedByReference = Obj.reference();395 // CHECK-FIXES: auto MutatedByReference = Obj.reference();396 mutate(MutatedByReference);397 }398 {399 auto MutatedByPointer = Obj.reference();400 // CHECK-FIXES: auto MutatedByPointer = Obj.reference();401 mutate(&MutatedByPointer);402 }403}404 405void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {406 const auto AutoAssigned = Obj.reference();407 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'408 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();409 AutoAssigned.constMethod();410}411 412void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {413 const auto AutoAssigned = Obj.reference();414 const auto AutoCopyConstructed(Obj.reference());415 const ExpensiveToCopyType VarAssigned = Obj.reference();416 const ExpensiveToCopyType VarCopyConstructed(Obj.reference());417 mutate(&Obj);418}419 420void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {421 const auto AutoAssigned = Obj.reference();422 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'423 // CHECK-FIXES: const auto& AutoAssigned = Obj.reference();424 AutoAssigned.constMethod();425}426 427void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {428 Obj.nonConstMethod();429 const auto AutoAssigned = Obj.reference();430}431 432void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {433 const auto AutoAssigned = Obj->reference();434 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'435 // CHECK-FIXES: const auto& AutoAssigned = Obj->reference();436 Obj->constMethod();437 AutoAssigned.constMethod();438}439 440void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {441 const auto AutoAssigned = Obj->reference();442 const auto AutoCopyConstructed(Obj->reference());443 const ExpensiveToCopyType VarAssigned = Obj->reference();444 const ExpensiveToCopyType VarCopyConstructed(Obj->reference());445 mutate(Obj);446}447 448void PositiveLocalVarIsNotModified() {449 ExpensiveToCopyType LocalVar;450 const auto AutoAssigned = LocalVar.reference();451 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'452 // CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();453 AutoAssigned.constMethod();454}455 456void NegativeLocalVarIsModified() {457 ExpensiveToCopyType Obj;458 const auto AutoAssigned = Obj.reference();459 Obj = AutoAssigned;460}461 462struct NegativeConstructor {463 NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}464 ExpensiveToCopyType Obj;465};466 467#define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE) \468 void functionWith##TYPE(const TYPE &T) { \469 auto AssignedInMacro = T.reference(); \470 } \471// Ensure fix is not applied.472// CHECK-FIXES: auto AssignedInMacro = T.reference(); {{\\}}473 474UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)475// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' of type 'ExpensiveToCopyType' is copy-constructed476 477#define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT478 479void PositiveMacroArgument(const ExpensiveToCopyType &Obj) {480 UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());481 // CHECK-MESSAGES: [[@LINE-1]]:48: warning: the variable 'CopyInMacroArg' of type 'ExpensiveToCopyType' is copy-constructed482 // Ensure fix is not applied.483 // CHECK-FIXES: UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());484 CopyInMacroArg.constMethod();485}486 487void PositiveLocalCopyConstMethodInvoked() {488 ExpensiveToCopyType orig;489 ExpensiveToCopyType copy_1 = orig;490 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_1' of the variable 'orig' of type 'ExpensiveToCopyType' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]491 // CHECK-FIXES: const ExpensiveToCopyType& copy_1 = orig;492 copy_1.constMethod();493 orig.constMethod();494}495 496void PositiveLocalCopyUsingExplicitCopyCtor() {497 ExpensiveToCopyType orig;498 ExpensiveToCopyType copy_2(orig);499 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_2'500 // CHECK-FIXES: const ExpensiveToCopyType& copy_2(orig);501 copy_2.constMethod();502 orig.constMethod();503}504 505void PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType &orig) {506 ExpensiveToCopyType copy_3 = orig;507 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_3'508 // CHECK-FIXES: const ExpensiveToCopyType& copy_3 = orig;509 copy_3.constMethod();510}511 512void PositiveLocalCopyUsedAsConstRef() {513 ExpensiveToCopyType orig;514 ExpensiveToCopyType copy_4 = orig;515 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_4'516 // CHECK-FIXES: const ExpensiveToCopyType& copy_4 = orig;517 useAsConstReference(orig);518 copy_4.constMethod();519}520 521void PositiveLocalCopyTwice() {522 ExpensiveToCopyType orig;523 ExpensiveToCopyType copy_5 = orig;524 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_5'525 // CHECK-FIXES: const ExpensiveToCopyType& copy_5 = orig;526 ExpensiveToCopyType copy_6 = copy_5;527 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_6'528 // CHECK-FIXES: const ExpensiveToCopyType& copy_6 = copy_5;529 copy_5.constMethod();530 copy_6.constMethod();531 orig.constMethod();532}533 534 535void PositiveLocalCopyWeirdCopy() {536 WeirdCopyCtorType orig;537 WeirdCopyCtorType weird_1(orig);538 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_1'539 // CHECK-FIXES: const WeirdCopyCtorType& weird_1(orig);540 weird_1.constMethod();541 542 WeirdCopyCtorType weird_2 = orig;543 // CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_2'544 // CHECK-FIXES: const WeirdCopyCtorType& weird_2 = orig;545 weird_2.constMethod();546}547 548void NegativeLocalCopySimpleTypes() {549 int i1 = 0;550 int i2 = i1;551}552 553void NegativeLocalCopyCopyIsModified() {554 ExpensiveToCopyType orig;555 ExpensiveToCopyType neg_copy_1 = orig;556 neg_copy_1.nonConstMethod();557}558 559void NegativeLocalCopyOriginalIsModified() {560 ExpensiveToCopyType orig;561 ExpensiveToCopyType neg_copy_2 = orig;562 orig.nonConstMethod();563}564 565void NegativeLocalCopyUsedAsRefArg() {566 ExpensiveToCopyType orig;567 ExpensiveToCopyType neg_copy_3 = orig;568 mutate(neg_copy_3);569}570 571void NegativeLocalCopyUsedAsPointerArg() {572 ExpensiveToCopyType orig;573 ExpensiveToCopyType neg_copy_4 = orig;574 mutate(&neg_copy_4);575}576 577void NegativeLocalCopyCopyFromGlobal() {578 ExpensiveToCopyType neg_copy_5 = global_expensive_to_copy_type;579}580 581void NegativeLocalCopyCopyToStatic() {582 ExpensiveToCopyType orig;583 static ExpensiveToCopyType neg_copy_6 = orig;584}585 586void NegativeLocalCopyNonConstInForLoop() {587 ExpensiveToCopyType orig;588 for (ExpensiveToCopyType neg_copy_7 = orig; orig.constMethod();589 orig.nonConstMethod()) {590 orig.constMethod();591 }592}593 594void NegativeLocalCopyWeirdNonCopy() {595 WeirdCopyCtorType orig;596 WeirdCopyCtorType neg_weird_1(orig, false);597 WeirdCopyCtorType neg_weird_2(orig, true);598}599void WarningOnlyMultiDeclStmt() {600 ExpensiveToCopyType orig;601 ExpensiveToCopyType copy = orig, copy2;602 // CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' of type 'ExpensiveToCopyType' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]603 // CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;604 copy.constMethod();605}606 607class Element {};608 609void implicitVarFalsePositive() {610 for (const Element &E : Container<Element>()) {611 }612}613 614// This should not trigger the check as the argument could introduce an alias.615void negativeInitializedFromFreeFunctionWithArg() {616 ExpensiveToCopyType Orig;617 const ExpensiveToCopyType Copy = freeFunctionWithArg(Orig);618}619 620void negativeInitializedFromFreeFunctionWithDefaultArg() {621 const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg();622}623 624void negativeInitialzedFromFreeFunctionWithNonDefaultArg() {625 ExpensiveToCopyType Orig;626 const ExpensiveToCopyType Copy = freeFunctionWithDefaultArg(&Orig);627}628 629namespace std {630inline namespace __1 {631 632template <class>633class function;634template <class R, class... ArgTypes>635class function<R(ArgTypes...)> {636public:637 function();638 function(const function &Other);639 R operator()(ArgTypes... Args) const;640};641 642} // namespace __1643} // namespace std644 645void negativeStdFunction() {646 std::function<int()> Orig;647 std::function<int()> Copy = Orig;648 int i = Orig();649}650 651using Functor = std::function<int()>;652 653void negativeAliasedStdFunction() {654 Functor Orig;655 Functor Copy = Orig;656 int i = Orig();657}658 659typedef std::function<int()> TypedefFunc;660 661void negativeTypedefedStdFunction() {662 TypedefFunc Orig;663 TypedefFunc Copy = Orig;664 int i = Orig();665}666 667namespace fake {668namespace std {669template <class R, class... Args>670struct function {671 // Custom copy constructor makes it expensive to copy;672 function(const function &);673 void constMethod() const;674};675} // namespace std676 677void positiveFakeStdFunction(std::function<void(int)> F) {678 auto Copy = F;679 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'Copy' of the variable 'F' of type 'std::function<void (int)>' is never modified;680 // CHECK-FIXES: const auto& Copy = F;681 Copy.constMethod();682}683 684} // namespace fake685 686void positiveInvokedOnStdFunction(687 std::function<void(const ExpensiveToCopyType &)> Update,688 const ExpensiveToCopyType Orig) {689 auto Copy = Orig.reference();690 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'Copy' of type 'ExpensiveToCopyType' is copy-constructed from a const reference691 // CHECK-FIXES: const auto& Copy = Orig.reference();692 Update(Copy);693}694 695void negativeInvokedOnStdFunction(696 std::function<void(ExpensiveToCopyType &)> Update,697 const ExpensiveToCopyType Orig) {698 auto Copy = Orig.reference();699 Update(Copy);700}701 702void negativeCopiedFromReferenceToModifiedVar() {703 ExpensiveToCopyType Orig;704 const auto &Ref = Orig;705 const auto NecessaryCopy = Ref;706 Orig.nonConstMethod();707}708 709void positiveCopiedFromReferenceToConstVar() {710 ExpensiveToCopyType Orig;711 const auto &Ref = Orig;712 const auto UnnecessaryCopy = Ref;713 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: local copy 'UnnecessaryCopy' of714 // CHECK-FIXES: const auto& UnnecessaryCopy = Ref;715 Orig.constMethod();716 UnnecessaryCopy.constMethod();717}718 719void negativeCopiedFromGetterOfReferenceToModifiedVar() {720 ExpensiveToCopyType Orig;721 const auto &Ref = Orig.reference();722 const auto NecessaryCopy = Ref.reference();723 Orig.nonConstMethod();724}725 726void negativeAliasNonCanonicalPointerType() {727 ExpensiveToCopyType Orig;728 // The use of auto here hides that the type is a pointer type. The check needs729 // to look at the canonical type to detect the aliasing through this pointer.730 const auto Pointer = Orig.pointer();731 const auto NecessaryCopy = Pointer->reference();732 Orig.nonConstMethod();733}734 735void negativeAliasTypedefedType() {736 typedef const ExpensiveToCopyType &ReferenceType;737 ExpensiveToCopyType Orig;738 // The typedef hides the fact that this is a reference type. The check needs739 // to look at the canonical type to detect the aliasing.740 ReferenceType Ref = Orig.reference();741 const auto NecessaryCopy = Ref.reference();742 Orig.nonConstMethod();743}744 745void positiveCopiedFromGetterOfReferenceToConstVar() {746 ExpensiveToCopyType Orig;747 const auto &Ref = Orig.reference();748 auto UnnecessaryCopy = Ref.reference();749 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'UnnecessaryCopy' of type 'ExpensiveToCopyType' is750 // CHECK-FIXES: const auto& UnnecessaryCopy = Ref.reference();751 Orig.constMethod();752 UnnecessaryCopy.constMethod();753}754 755void positiveUnusedReferenceIsRemoved() {756 // clang-format off757 const auto AutoAssigned = ExpensiveTypeReference(); int i = 0; // Foo bar.758 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned' of type 'const ExpensiveToCopyType' is copy-constructed from a const reference but is never used; consider removing the statement [performance-unnecessary-copy-initialization]759 // CHECK-FIXES-NOT: const auto AutoAssigned = ExpensiveTypeReference();760 // CHECK-FIXES: int i = 0; // Foo bar.761 auto TrailingCommentRemoved = ExpensiveTypeReference(); // Trailing comment.762 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'TrailingCommentRemoved' of type 'ExpensiveToCopyType' is copy-constructed from a const reference but is never used;763 // CHECK-FIXES-NOT: auto TrailingCommentRemoved = ExpensiveTypeReference();764 // CHECK-FIXES-NOT: // Trailing comment.765 // clang-format on766 767 auto UnusedAndUnnecessary = ExpensiveTypeReference();768 // Comments on a new line should not be deleted.769 // CHECK-MESSAGES: [[@LINE-2]]:8: warning: the variable 'UnusedAndUnnecessary' of type 'ExpensiveToCopyType' is copy-constructed770 // CHECK-FIXES-NOT: auto UnusedAndUnnecessary = ExpensiveTypeReference();771 // CHECK-FIXES: // Comments on a new line should not be deleted.772}773 774void positiveLoopedOverObjectIsConst() {775 const Container<ExpensiveToCopyType> Orig;776 for (const auto &Element : Orig) {777 const auto Copy = Element;778 // CHECK-MESSAGES: [[@LINE-1]]:16: warning: local copy 'Copy'779 // CHECK-FIXES: const auto& Copy = Element;780 Orig.constMethod();781 Copy.constMethod();782 }783 784 auto Lambda = []() {785 const Container<ExpensiveToCopyType> Orig;786 for (const auto &Element : Orig) {787 const auto Copy = Element;788 // CHECK-MESSAGES: [[@LINE-1]]:18: warning: local copy 'Copy'789 // CHECK-FIXES: const auto& Copy = Element;790 Orig.constMethod();791 Copy.constMethod();792 }793 };794}795 796void negativeLoopedOverObjectIsModified() {797 Container<ExpensiveToCopyType> Orig;798 for (const auto &Element : Orig) {799 const auto Copy = Element;800 Orig.nonConstMethod();801 Copy.constMethod();802 }803 804 auto Lambda = []() {805 Container<ExpensiveToCopyType> Orig;806 for (const auto &Element : Orig) {807 const auto Copy = Element;808 Orig.nonConstMethod();809 Copy.constMethod();810 }811 };812}813 814void negativeReferenceIsInitializedOutsideOfBlock() {815 ExpensiveToCopyType Orig;816 const auto &E2 = Orig;817 if (1 != 2 * 3) {818 const auto C2 = E2;819 Orig.nonConstMethod();820 C2.constMethod();821 }822 823 auto Lambda = []() {824 ExpensiveToCopyType Orig;825 const auto &E2 = Orig;826 if (1 != 2 * 3) {827 const auto C2 = E2;828 Orig.nonConstMethod();829 C2.constMethod();830 }831 };832}833 834void negativeStructuredBinding() {835 // Structured bindings are not yet supported but can trigger false positives836 // since the DecompositionDecl itself is unused and the check doesn't traverse837 // VarDecls of the BindingDecls.838 struct Pair {839 ExpensiveToCopyType first;840 ExpensiveToCopyType second;841 };842 843 Pair P;844 const auto [C, D] = P;845 C.constMethod();846 D.constMethod();847}848 849template <typename A>850const A &templatedReference();851 852template <typename A, typename B>853void negativeTemplateTypes() {854 A Orig;855 // Different replaced template type params do not trigger the check. In some856 // template instantiation this might not be a copy but an implicit857 // conversion, so converting this to a reference might not work.858 B AmbiguousCopy = Orig;859 // CHECK-NOT-FIXES: B AmbiguousCopy = Orig;860 861 B NecessaryCopy = templatedReference<A>();862 // CHECK-NOT-FIXES: B NecessaryCopy = templatedReference<A>();863 864 B NecessaryCopy2 = Orig.template templatedAccessor<A>();865 866 // Non-dependent types in template still trigger the check.867 const auto UnnecessaryCopy = ExpensiveTypeReference();868 // CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy' of type 'const ExpensiveToCopyType' is copy-constructed869 // CHECK-FIXES: const auto& UnnecessaryCopy = ExpensiveTypeReference();870 UnnecessaryCopy.constMethod();871}872 873void instantiateNegativeTemplateTypes() {874 negativeTemplateTypes<ExpensiveToCopyType, ExpensiveToCopyType>();875 // This template instantiation would not compile if the `AmbiguousCopy` above was made a reference.876 negativeTemplateTypes<ExpensiveToCopyType, int>();877}878 879template <typename A>880void positiveSingleTemplateType() {881 A Orig;882 A SingleTmplParmTypeCopy = Orig;883 // CHECK-MESSAGES: [[@LINE-1]]:5: warning: local copy 'SingleTmplParmTypeCopy' of the variable 'Orig' of type 'ExpensiveToCopyType' is never modified884 // CHECK-FIXES: const A& SingleTmplParmTypeCopy = Orig;885 SingleTmplParmTypeCopy.constMethod();886 887 A UnnecessaryCopy2 = templatedReference<A>();888 // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the variable 'UnnecessaryCopy2' of type 'ExpensiveToCopyType' is copy-constructed from a const reference889 // CHECK-FIXES: const A& UnnecessaryCopy2 = templatedReference<A>();890 UnnecessaryCopy2.constMethod();891 892 A UnnecessaryCopy3 = Orig.template templatedAccessor<A>();893 // CHECK-MESSAGES: [[@LINE-1]]:5: warning: the variable 'UnnecessaryCopy3' of type 'ExpensiveToCopyType' is copy-constructed from a const reference894 // CHECK-FIXES: const A& UnnecessaryCopy3 = Orig.template templatedAccessor<A>();895 UnnecessaryCopy3.constMethod();896}897 898void instantiatePositiveSingleTemplateType() { positiveSingleTemplateType<ExpensiveToCopyType>(); }899 900struct Struct {901 ExpensiveToCopyType Member;902};903 904void positiveConstMemberExpr() {905 Struct Orig;906 auto UC = Orig;907 // CHECK-MESSAGES: [[@LINE-1]]:8: warning: local copy 'UC'908 // CHECK-FIXES: const auto& UC = Orig;909 const auto &ConstRef = UC.Member;910 auto MemberCopy = UC.Member;911 bool b = UC.Member.constMethod();912 useByValue(UC.Member);913 useAsConstReference(UC.Member);914 useByValue(UC.Member);915}916 917void negativeNonConstMemberExpr() {918 Struct Orig;919 {920 auto Copy = Orig;921 Copy.Member.nonConstMethod();922 }923 {924 auto Copy = Orig;925 mutate(Copy.Member);926 }927 {928 auto Copy = Orig;929 mutate(&Copy.Member);930 }931}932 933 934bool operator==(ExpensiveToCopyType, ExpensiveToCopyType);935 936template<typename T> bool OperatorWithNoDirectCallee(T t) {937 ExpensiveToCopyType a1;938 ExpensiveToCopyType a2 = a1;939 return a1 == t;940}941