blob: 50dcfd8f8bf22656745b26053f3c078453fc27c1 [file] [log] [blame]
// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
struct ExpensiveToCopyType {
ExpensiveToCopyType();
virtual ~ExpensiveToCopyType();
const ExpensiveToCopyType &reference() const;
void nonConstMethod();
bool constMethod() const;
};
struct TrivialToCopyType {
const TrivialToCopyType &reference() const;
};
struct WeirdCopyCtorType {
WeirdCopyCtorType();
WeirdCopyCtorType(const WeirdCopyCtorType &w, bool oh_yes = true);
void nonConstMethod();
bool constMethod() const;
};
ExpensiveToCopyType global_expensive_to_copy_type;
const ExpensiveToCopyType &ExpensiveTypeReference();
const TrivialToCopyType &TrivialTypeReference();
void mutate(ExpensiveToCopyType &);
void mutate(ExpensiveToCopyType *);
void useAsConstPointer(const ExpensiveToCopyType *);
void useAsConstReference(const ExpensiveToCopyType &);
void useByValue(ExpensiveToCopyType);
void PositiveFunctionCall() {
const auto AutoAssigned = ExpensiveTypeReference();
// 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]
// CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
const auto AutoCopyConstructed(ExpensiveTypeReference());
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
// CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
const ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
}
void PositiveMethodCallConstReferenceParam(const ExpensiveToCopyType &Obj) {
const auto AutoAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
const auto AutoCopyConstructed(Obj.reference());
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
const ExpensiveToCopyType VarAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
}
void PositiveMethodCallConstParam(const ExpensiveToCopyType Obj) {
const auto AutoAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
const auto AutoCopyConstructed(Obj.reference());
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
const ExpensiveToCopyType VarAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
}
void PositiveMethodCallConstPointerParam(const ExpensiveToCopyType *const Obj) {
const auto AutoAssigned = Obj->reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
const auto AutoCopyConstructed(Obj->reference());
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());
const ExpensiveToCopyType VarAssigned = Obj->reference();
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();
const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());
}
void PositiveLocalConstValue() {
const ExpensiveToCopyType Obj;
const auto UnnecessaryCopy = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
// CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();
}
void PositiveLocalConstRef() {
const ExpensiveToCopyType Obj;
const ExpensiveToCopyType &ConstReference = Obj.reference();
const auto UnnecessaryCopy = ConstReference.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
// CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();
}
void PositiveLocalConstPointer() {
const ExpensiveToCopyType Obj;
const ExpensiveToCopyType *const ConstPointer = &Obj;
const auto UnnecessaryCopy = ConstPointer->reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
// CHECK-FIXES: const auto& UnnecessaryCopy = ConstPointer->reference();
}
void NegativeFunctionCallTrivialType() {
const auto AutoAssigned = TrivialTypeReference();
const auto AutoCopyConstructed(TrivialTypeReference());
const TrivialToCopyType VarAssigned = TrivialTypeReference();
const TrivialToCopyType VarCopyConstructed(TrivialTypeReference());
}
void NegativeStaticLocalVar(const ExpensiveToCopyType &Obj) {
static const auto StaticVar = Obj.reference();
}
void PositiveFunctionCallExpensiveTypeNonConstVariable() {
auto AutoAssigned = ExpensiveTypeReference();
// 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]
// CHECK-FIXES: const auto& AutoAssigned = ExpensiveTypeReference();
auto AutoCopyConstructed(ExpensiveTypeReference());
// CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'
// CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
ExpensiveToCopyType VarAssigned = ExpensiveTypeReference();
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
ExpensiveToCopyType VarCopyConstructed(ExpensiveTypeReference());
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
}
void positiveNonConstVarInCodeBlock(const ExpensiveToCopyType &Obj) {
{
auto Assigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'
// CHECK-FIXES: const auto& Assigned = Obj.reference();
Assigned.reference();
useAsConstReference(Assigned);
useByValue(Assigned);
}
}
void negativeNonConstVarWithNonConstUse(const ExpensiveToCopyType &Obj) {
{
auto NonConstInvoked = Obj.reference();
// CHECK-FIXES: auto NonConstInvoked = Obj.reference();
NonConstInvoked.nonConstMethod();
}
{
auto Reassigned = Obj.reference();
// CHECK-FIXES: auto Reassigned = Obj.reference();
Reassigned = ExpensiveToCopyType();
}
{
auto MutatedByReference = Obj.reference();
// CHECK-FIXES: auto MutatedByReference = Obj.reference();
mutate(MutatedByReference);
}
{
auto MutatedByPointer = Obj.reference();
// CHECK-FIXES: auto MutatedByPointer = Obj.reference();
mutate(&MutatedByPointer);
}
}
void PositiveMethodCallNonConstRefNotModified(ExpensiveToCopyType &Obj) {
const auto AutoAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
}
void NegativeMethodCallNonConstRefIsModified(ExpensiveToCopyType &Obj) {
const auto AutoAssigned = Obj.reference();
const auto AutoCopyConstructed(Obj.reference());
const ExpensiveToCopyType VarAssigned = Obj.reference();
const ExpensiveToCopyType VarCopyConstructed(Obj.reference());
mutate(&Obj);
}
void PositiveMethodCallNonConstNotModified(ExpensiveToCopyType Obj) {
const auto AutoAssigned = Obj.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
}
void NegativeMethodCallNonConstValueArgumentIsModified(ExpensiveToCopyType Obj) {
Obj.nonConstMethod();
const auto AutoAssigned = Obj.reference();
}
void PositiveMethodCallNonConstPointerNotModified(ExpensiveToCopyType *const Obj) {
const auto AutoAssigned = Obj->reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
Obj->constMethod();
}
void NegativeMethodCallNonConstPointerIsModified(ExpensiveToCopyType *const Obj) {
const auto AutoAssigned = Obj->reference();
const auto AutoCopyConstructed(Obj->reference());
const ExpensiveToCopyType VarAssigned = Obj->reference();
const ExpensiveToCopyType VarCopyConstructed(Obj->reference());
mutate(Obj);
}
void PositiveLocalVarIsNotModified() {
ExpensiveToCopyType LocalVar;
const auto AutoAssigned = LocalVar.reference();
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = LocalVar.reference();
}
void NegativeLocalVarIsModified() {
ExpensiveToCopyType Obj;
const auto AutoAssigned = Obj.reference();
Obj = AutoAssigned;
}
struct NegativeConstructor {
NegativeConstructor(const ExpensiveToCopyType &Obj) : Obj(Obj) {}
ExpensiveToCopyType Obj;
};
#define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE) \
void functionWith##TYPE(const TYPE &T) { \
auto AssignedInMacro = T.reference(); \
} \
// Ensure fix is not applied.
// CHECK-FIXES: auto AssignedInMacro = T.reference();
UNNECESSARY_COPY_INIT_IN_MACRO_BODY(ExpensiveToCopyType)
// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the variable 'AssignedInMacro' is copy-constructed
#define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT
void PositiveMacroArgument(const ExpensiveToCopyType &Obj) {
UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(auto CopyInMacroArg = Obj.reference());
// CHECK-MESSAGES: [[@LINE-1]]:48: warning: the variable 'CopyInMacroArg' is copy-constructed
// Ensure fix is not applied.
// CHECK-FIXES: auto CopyInMacroArg = Obj.reference()
}
void PositiveLocalCopyConstMethodInvoked() {
ExpensiveToCopyType orig;
ExpensiveToCopyType copy_1 = orig;
// 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]
// CHECK-FIXES: const ExpensiveToCopyType& copy_1 = orig;
copy_1.constMethod();
orig.constMethod();
}
void PositiveLocalCopyUsingExplicitCopyCtor() {
ExpensiveToCopyType orig;
ExpensiveToCopyType copy_2(orig);
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_2'
// CHECK-FIXES: const ExpensiveToCopyType& copy_2(orig);
copy_2.constMethod();
orig.constMethod();
}
void PositiveLocalCopyCopyIsArgument(const ExpensiveToCopyType &orig) {
ExpensiveToCopyType copy_3 = orig;
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_3'
// CHECK-FIXES: const ExpensiveToCopyType& copy_3 = orig;
copy_3.constMethod();
}
void PositiveLocalCopyUsedAsConstRef() {
ExpensiveToCopyType orig;
ExpensiveToCopyType copy_4 = orig;
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_4'
// CHECK-FIXES: const ExpensiveToCopyType& copy_4 = orig;
useAsConstReference(orig);
}
void PositiveLocalCopyTwice() {
ExpensiveToCopyType orig;
ExpensiveToCopyType copy_5 = orig;
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_5'
// CHECK-FIXES: const ExpensiveToCopyType& copy_5 = orig;
ExpensiveToCopyType copy_6 = copy_5;
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy_6'
// CHECK-FIXES: const ExpensiveToCopyType& copy_6 = copy_5;
copy_5.constMethod();
copy_6.constMethod();
orig.constMethod();
}
void PositiveLocalCopyWeirdCopy() {
WeirdCopyCtorType orig;
WeirdCopyCtorType weird_1(orig);
// CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_1'
// CHECK-FIXES: const WeirdCopyCtorType& weird_1(orig);
weird_1.constMethod();
WeirdCopyCtorType weird_2 = orig;
// CHECK-MESSAGES: [[@LINE-1]]:21: warning: local copy 'weird_2'
// CHECK-FIXES: const WeirdCopyCtorType& weird_2 = orig;
weird_2.constMethod();
}
void NegativeLocalCopySimpleTypes() {
int i1 = 0;
int i2 = i1;
}
void NegativeLocalCopyCopyIsModified() {
ExpensiveToCopyType orig;
ExpensiveToCopyType neg_copy_1 = orig;
neg_copy_1.nonConstMethod();
}
void NegativeLocalCopyOriginalIsModified() {
ExpensiveToCopyType orig;
ExpensiveToCopyType neg_copy_2 = orig;
orig.nonConstMethod();
}
void NegativeLocalCopyUsedAsRefArg() {
ExpensiveToCopyType orig;
ExpensiveToCopyType neg_copy_3 = orig;
mutate(neg_copy_3);
}
void NegativeLocalCopyUsedAsPointerArg() {
ExpensiveToCopyType orig;
ExpensiveToCopyType neg_copy_4 = orig;
mutate(&neg_copy_4);
}
void NegativeLocalCopyCopyFromGlobal() {
ExpensiveToCopyType neg_copy_5 = global_expensive_to_copy_type;
}
void NegativeLocalCopyCopyToStatic() {
ExpensiveToCopyType orig;
static ExpensiveToCopyType neg_copy_6 = orig;
}
void NegativeLocalCopyNonConstInForLoop() {
ExpensiveToCopyType orig;
for (ExpensiveToCopyType neg_copy_7 = orig; orig.constMethod();
orig.nonConstMethod()) {
orig.constMethod();
}
}
void NegativeLocalCopyWeirdNonCopy() {
WeirdCopyCtorType orig;
WeirdCopyCtorType neg_weird_1(orig, false);
WeirdCopyCtorType neg_weird_2(orig, true);
}
void WarningOnlyMultiDeclStmt() {
ExpensiveToCopyType orig;
ExpensiveToCopyType copy = orig, copy2;
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: local copy 'copy' of the variable 'orig' is never modified; consider avoiding the copy [performance-unnecessary-copy-initialization]
// CHECK-FIXES: ExpensiveToCopyType copy = orig, copy2;
}
class Element {};
class Container {
public:
class Iterator {
public:
void operator++();
Element operator*();
bool operator!=(const Iterator &);
WeirdCopyCtorType c;
};
const Iterator &begin() const;
const Iterator &end() const;
};
void implicitVarFalsePositive() {
for (const Element &E : Container()) {
}
}