2015-12-30 18:24:40 +08:00
// RUN: %check_clang_tidy %s performance-unnecessary-copy-initialization %t
struct ExpensiveToCopyType {
2016-03-23 17:33:07 +08:00
ExpensiveToCopyType ( ) ;
virtual ~ ExpensiveToCopyType ( ) ;
const ExpensiveToCopyType & reference ( ) const ;
void nonConstMethod ( ) ;
bool constMethod ( ) const ;
2015-12-30 18:24:40 +08:00
} ;
struct TrivialToCopyType {
2016-03-23 17:33:07 +08:00
const TrivialToCopyType & reference ( ) const ;
2015-12-30 18:24:40 +08:00
} ;
2016-03-23 17:33:07 +08:00
struct WeirdCopyCtorType {
WeirdCopyCtorType ( ) ;
WeirdCopyCtorType ( const WeirdCopyCtorType & w , bool oh_yes = true ) ;
2015-12-30 18:24:40 +08:00
2016-03-23 17:33:07 +08:00
void nonConstMethod ( ) ;
bool constMethod ( ) const ;
} ;
ExpensiveToCopyType global_expensive_to_copy_type ;
const ExpensiveToCopyType & ExpensiveTypeReference ( ) ;
const TrivialToCopyType & TrivialTypeReference ( ) ;
2015-12-30 18:24:40 +08:00
2016-03-06 05:17:58 +08:00
void mutate ( ExpensiveToCopyType & ) ;
void mutate ( ExpensiveToCopyType * ) ;
2016-03-23 17:33:07 +08:00
void useAsConstPointer ( const ExpensiveToCopyType * ) ;
2016-03-06 05:17:58 +08:00
void useAsConstReference ( const ExpensiveToCopyType & ) ;
void useByValue ( ExpensiveToCopyType ) ;
2015-12-30 18:24:40 +08:00
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 ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
const ExpensiveToCopyType VarAssigned = ExpensiveTypeReference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
const ExpensiveToCopyType VarCopyConstructed ( ExpensiveTypeReference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
}
void PositiveMethodCallConstReferenceParam ( const ExpensiveToCopyType & Obj ) {
const auto AutoAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
const auto AutoCopyConstructed ( Obj . reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
const ExpensiveToCopyType VarAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
const ExpensiveToCopyType VarCopyConstructed ( Obj . reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
}
void PositiveMethodCallConstParam ( const ExpensiveToCopyType Obj ) {
const auto AutoAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
const auto AutoCopyConstructed ( Obj . reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj.reference());
const ExpensiveToCopyType VarAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj.reference();
const ExpensiveToCopyType VarCopyConstructed ( Obj . reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj.reference());
}
void PositiveMethodCallConstPointerParam ( const ExpensiveToCopyType * const Obj ) {
const auto AutoAssigned = Obj - > reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoAssigned = Obj->reference();
const auto AutoCopyConstructed ( Obj - > reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& AutoCopyConstructed(Obj->reference());
const ExpensiveToCopyType VarAssigned = Obj - > reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarAssigned'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = Obj->reference();
const ExpensiveToCopyType VarCopyConstructed ( Obj - > reference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:29: warning: the const qualified variable 'VarCopyConstructed'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(Obj->reference());
}
void PositiveLocalConstValue ( ) {
const ExpensiveToCopyType Obj ;
const auto UnnecessaryCopy = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& UnnecessaryCopy = Obj.reference();
}
void PositiveLocalConstRef ( ) {
const ExpensiveToCopyType Obj ;
const ExpensiveToCopyType & ConstReference = Obj . reference ( ) ;
const auto UnnecessaryCopy = ConstReference . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
2015-12-30 18:24:40 +08:00
// CHECK-FIXES: const auto& UnnecessaryCopy = ConstReference.reference();
}
void PositiveLocalConstPointer ( ) {
const ExpensiveToCopyType Obj ;
const ExpensiveToCopyType * const ConstPointer = & Obj ;
const auto UnnecessaryCopy = ConstPointer - > reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'UnnecessaryCopy'
2015-12-30 18:24:40 +08:00
// 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 ( ) ) ;
}
2015-12-30 19:35:50 +08:00
void NegativeStaticLocalVar ( const ExpensiveToCopyType & Obj ) {
static const auto StaticVar = Obj . reference ( ) ;
}
2016-03-06 05:17:58 +08:00
void PositiveFunctionCallExpensiveTypeNonConstVariable ( ) {
2015-12-30 18:24:40 +08:00
auto AutoAssigned = ExpensiveTypeReference ( ) ;
2016-03-06 05:17:58 +08:00
// 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();
2015-12-30 18:24:40 +08:00
auto AutoCopyConstructed ( ExpensiveTypeReference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:8: warning: the variable 'AutoCopyConstructed'
2016-03-06 05:17:58 +08:00
// CHECK-FIXES: const auto& AutoCopyConstructed(ExpensiveTypeReference());
2015-12-30 18:24:40 +08:00
ExpensiveToCopyType VarAssigned = ExpensiveTypeReference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarAssigned'
2016-03-06 05:17:58 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarAssigned = ExpensiveTypeReference();
2015-12-30 18:24:40 +08:00
ExpensiveToCopyType VarCopyConstructed ( ExpensiveTypeReference ( ) ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:23: warning: the variable 'VarCopyConstructed'
2016-03-06 05:17:58 +08:00
// CHECK-FIXES: const ExpensiveToCopyType& VarCopyConstructed(ExpensiveTypeReference());
}
void positiveNonConstVarInCodeBlock ( const ExpensiveToCopyType & Obj ) {
{
auto Assigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:10: warning: the variable 'Assigned'
2016-03-06 05:17:58 +08:00
// 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 ) ;
}
2015-12-30 18:24:40 +08:00
}
2016-05-31 08:25:57 +08:00
void PositiveMethodCallNonConstRefNotModified ( ExpensiveToCopyType & Obj ) {
2015-12-30 18:24:40 +08:00
const auto AutoAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
// CHECK-MESSAGES: [[@LINE-1]]:14: warning: the const qualified variable 'AutoAssigned'
// CHECK-FIXES: const auto& AutoAssigned = Obj.reference();
2015-12-30 18:24:40 +08:00
}
2016-05-31 08:25:57 +08:00
void NegativeMethodCallNonConstRefIsModified ( ExpensiveToCopyType & Obj ) {
2015-12-30 18:24:40 +08:00
const auto AutoAssigned = Obj . reference ( ) ;
const auto AutoCopyConstructed ( Obj . reference ( ) ) ;
const ExpensiveToCopyType VarAssigned = Obj . reference ( ) ;
const ExpensiveToCopyType VarCopyConstructed ( Obj . reference ( ) ) ;
2016-05-31 08:25:57 +08:00
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();
2015-12-30 18:24:40 +08:00
}
2016-05-31 08:25:57 +08:00
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 ) {
2015-12-30 18:24:40 +08:00
const auto AutoAssigned = Obj - > reference ( ) ;
const auto AutoCopyConstructed ( Obj - > reference ( ) ) ;
const ExpensiveToCopyType VarAssigned = Obj - > reference ( ) ;
const ExpensiveToCopyType VarCopyConstructed ( Obj - > reference ( ) ) ;
2016-05-31 08:25:57 +08:00
mutate ( Obj ) ;
2015-12-30 18:24:40 +08:00
}
2016-05-31 08:25:57 +08:00
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 ( ) {
2015-12-30 18:24:40 +08:00
ExpensiveToCopyType Obj ;
const auto AutoAssigned = Obj . reference ( ) ;
2016-05-31 08:25:57 +08:00
Obj = AutoAssigned ;
2015-12-30 18:24:40 +08:00
}
struct NegativeConstructor {
NegativeConstructor ( const ExpensiveToCopyType & Obj ) : Obj ( Obj ) { }
ExpensiveToCopyType Obj ;
} ;
2016-03-06 05:17:58 +08:00
2016-03-23 17:33:07 +08:00
# define UNNECESSARY_COPY_INIT_IN_MACRO_BODY(TYPE) \
void functionWith # # TYPE ( const TYPE & T ) { \
auto AssignedInMacro = T . reference ( ) ; \
} \
2016-03-06 05:17:58 +08:00
// 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
2016-03-23 17:33:07 +08:00
# define UNNECESSARY_COPY_INIT_IN_MACRO_ARGUMENT(ARGUMENT) ARGUMENT
2016-03-06 05:17:58 +08:00
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()
}
2016-03-23 17:33:07 +08:00
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 ) ;
}
2016-05-13 10:47:56 +08:00
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;
}
2016-11-08 08:45:34 +08:00
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 ( ) ) {
}
}