brintos

brintos / llvm-project-archived public Read only

0
0
Text · 34.2 KiB · 4818e9d Raw
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