189a1d03eSRichard // RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fno-delayed-template-parsing 289a1d03eSRichard 389a1d03eSRichard // CHECK-FIXES: #include <utility> 489a1d03eSRichard 5*1ce89899SDmitry Polukhin namespace std { 6*1ce89899SDmitry Polukhin template <typename> 7*1ce89899SDmitry Polukhin struct remove_reference; 8*1ce89899SDmitry Polukhin 9*1ce89899SDmitry Polukhin template <typename _Tp> 10*1ce89899SDmitry Polukhin struct remove_reference { 11*1ce89899SDmitry Polukhin typedef _Tp type; 12*1ce89899SDmitry Polukhin }; 13*1ce89899SDmitry Polukhin 14*1ce89899SDmitry Polukhin template <typename _Tp> 15*1ce89899SDmitry Polukhin struct remove_reference<_Tp &> { 16*1ce89899SDmitry Polukhin typedef _Tp type; 17*1ce89899SDmitry Polukhin }; 18*1ce89899SDmitry Polukhin 19*1ce89899SDmitry Polukhin template <typename _Tp> 20*1ce89899SDmitry Polukhin struct remove_reference<_Tp &&> { 21*1ce89899SDmitry Polukhin typedef _Tp type; 22*1ce89899SDmitry Polukhin }; 23*1ce89899SDmitry Polukhin 24*1ce89899SDmitry Polukhin template <typename _Tp> 25*1ce89899SDmitry Polukhin constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) { 26*1ce89899SDmitry Polukhin return static_cast<typename std::remove_reference<_Tp>::type &&>(__t); 27*1ce89899SDmitry Polukhin } 28*1ce89899SDmitry Polukhin } // namespace std 29*1ce89899SDmitry Polukhin 3089a1d03eSRichard struct ExpensiveToCopyType { 3189a1d03eSRichard const ExpensiveToCopyType & constReference() const { 3289a1d03eSRichard return *this; 3389a1d03eSRichard } 3489a1d03eSRichard void nonConstMethod(); 3589a1d03eSRichard virtual ~ExpensiveToCopyType(); 3689a1d03eSRichard }; 3789a1d03eSRichard 3889a1d03eSRichard void mutate(ExpensiveToCopyType &); 3989a1d03eSRichard void mutate(ExpensiveToCopyType *); 4089a1d03eSRichard void useAsConstReference(const ExpensiveToCopyType &); 4189a1d03eSRichard void useByValue(ExpensiveToCopyType); 4289a1d03eSRichard 4389a1d03eSRichard template <class T> class Vector { 4489a1d03eSRichard public: 4589a1d03eSRichard using iterator = T*; 4689a1d03eSRichard using const_iterator = const T*; 4789a1d03eSRichard 4889a1d03eSRichard Vector(const Vector&); 4989a1d03eSRichard Vector& operator=(const Vector&); 5089a1d03eSRichard 5189a1d03eSRichard iterator begin(); 5289a1d03eSRichard iterator end(); 5389a1d03eSRichard const_iterator begin() const; 5489a1d03eSRichard const_iterator end() const; 5589a1d03eSRichard }; 5689a1d03eSRichard 5789a1d03eSRichard // This class simulates std::pair<>. It is trivially copy constructible 5889a1d03eSRichard // and trivially destructible, but not trivially copy assignable. 5989a1d03eSRichard class SomewhatTrivial { 6089a1d03eSRichard public: 6189a1d03eSRichard SomewhatTrivial(); 6289a1d03eSRichard SomewhatTrivial(const SomewhatTrivial&) = default; 6389a1d03eSRichard ~SomewhatTrivial() = default; 6489a1d03eSRichard SomewhatTrivial& operator=(const SomewhatTrivial&); 6589a1d03eSRichard }; 6689a1d03eSRichard 6789a1d03eSRichard struct MoveOnlyType { 6889a1d03eSRichard MoveOnlyType(const MoveOnlyType &) = delete; 6989a1d03eSRichard MoveOnlyType(MoveOnlyType &&) = default; 7089a1d03eSRichard ~MoveOnlyType(); 7189a1d03eSRichard void constMethod() const; 7289a1d03eSRichard }; 7389a1d03eSRichard 7489a1d03eSRichard struct ExpensiveMovableType { 7589a1d03eSRichard ExpensiveMovableType(); 7689a1d03eSRichard ExpensiveMovableType(ExpensiveMovableType &&); 7789a1d03eSRichard ExpensiveMovableType(const ExpensiveMovableType &) = default; 7889a1d03eSRichard ExpensiveMovableType &operator=(const ExpensiveMovableType &) = default; 7989a1d03eSRichard ExpensiveMovableType &operator=(ExpensiveMovableType &&); 8089a1d03eSRichard ~ExpensiveMovableType(); 8189a1d03eSRichard }; 8289a1d03eSRichard 8389a1d03eSRichard void positiveExpensiveConstValue(const ExpensiveToCopyType Obj); 8489a1d03eSRichard // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj); 8589a1d03eSRichard void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) { 8689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param] 8789a1d03eSRichard // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) { 8889a1d03eSRichard } 8989a1d03eSRichard 9089a1d03eSRichard void positiveExpensiveValue(ExpensiveToCopyType Obj); 9189a1d03eSRichard // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj); 9289a1d03eSRichard void positiveExpensiveValue(ExpensiveToCopyType Obj) { 9389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param] 9489a1d03eSRichard // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) { 9589a1d03eSRichard Obj.constReference(); 9689a1d03eSRichard useAsConstReference(Obj); 9789a1d03eSRichard auto Copy = Obj; 9889a1d03eSRichard useByValue(Obj); 9989a1d03eSRichard } 10089a1d03eSRichard 10189a1d03eSRichard void positiveVector(Vector<ExpensiveToCopyType> V) { 10289a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'V' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param] 10389a1d03eSRichard // CHECK-FIXES: void positiveVector(const Vector<ExpensiveToCopyType>& V) { 10489a1d03eSRichard for (const auto& Obj : V) { 10589a1d03eSRichard useByValue(Obj); 10689a1d03eSRichard } 10789a1d03eSRichard } 10889a1d03eSRichard 10989a1d03eSRichard void positiveWithComment(const ExpensiveToCopyType /* important */ S); 11089a1d03eSRichard // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S); 11189a1d03eSRichard void positiveWithComment(const ExpensiveToCopyType /* important */ S) { 11289a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified 11389a1d03eSRichard // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) { 11489a1d03eSRichard } 11589a1d03eSRichard 11689a1d03eSRichard void positiveUnnamedParam(const ExpensiveToCopyType) { 11789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1 11889a1d03eSRichard // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) { 11989a1d03eSRichard } 12089a1d03eSRichard 12189a1d03eSRichard void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy); 12289a1d03eSRichard // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy); 12389a1d03eSRichard void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) { 12489a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy' 12589a1d03eSRichard // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy' 12689a1d03eSRichard // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) { 12789a1d03eSRichard } 12889a1d03eSRichard 12989a1d03eSRichard struct PositiveConstValueConstructor { 13089a1d03eSRichard PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {} 13189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy' 13289a1d03eSRichard // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {} 13389a1d03eSRichard }; 13489a1d03eSRichard 13589a1d03eSRichard void negativeArray(const ExpensiveToCopyType[]) { 13689a1d03eSRichard } 13789a1d03eSRichard 13889a1d03eSRichard void negativePointer(ExpensiveToCopyType* Obj) { 13989a1d03eSRichard } 14089a1d03eSRichard 14189a1d03eSRichard void negativeConstPointer(const ExpensiveToCopyType* Obj) { 14289a1d03eSRichard } 14389a1d03eSRichard 14489a1d03eSRichard void negativeConstReference(const ExpensiveToCopyType& Obj) { 14589a1d03eSRichard } 14689a1d03eSRichard 14789a1d03eSRichard void negativeReference(ExpensiveToCopyType& Obj) { 14889a1d03eSRichard } 14989a1d03eSRichard 15089a1d03eSRichard void negativeUniversalReference(ExpensiveToCopyType&& Obj) { 15189a1d03eSRichard } 15289a1d03eSRichard 15389a1d03eSRichard void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) { 15489a1d03eSRichard } 15589a1d03eSRichard 15689a1d03eSRichard void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) { 15789a1d03eSRichard } 15889a1d03eSRichard 15989a1d03eSRichard void negativeConstBuiltIn(const int I) { 16089a1d03eSRichard } 16189a1d03eSRichard 16289a1d03eSRichard void negativeValueBuiltIn(int I) { 16389a1d03eSRichard } 16489a1d03eSRichard 16589a1d03eSRichard void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) { 16689a1d03eSRichard mutate(Obj); 16789a1d03eSRichard } 16889a1d03eSRichard 16989a1d03eSRichard void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) { 17089a1d03eSRichard mutate(&Obj); 17189a1d03eSRichard } 17289a1d03eSRichard 17389a1d03eSRichard void negativeValueIsReassigned(ExpensiveToCopyType Obj) { 17489a1d03eSRichard Obj = ExpensiveToCopyType(); 17589a1d03eSRichard } 17689a1d03eSRichard 17789a1d03eSRichard void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) { 17889a1d03eSRichard Obj.nonConstMethod(); 17989a1d03eSRichard } 18089a1d03eSRichard 18189a1d03eSRichard struct PositiveValueUnusedConstructor { 18289a1d03eSRichard PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {} 18389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy' 18489a1d03eSRichard // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {} 18589a1d03eSRichard }; 18689a1d03eSRichard 18789a1d03eSRichard struct PositiveValueCopiedConstructor { 18889a1d03eSRichard PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {} 18989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy' 19089a1d03eSRichard // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {} 19189a1d03eSRichard ExpensiveToCopyType Field; 19289a1d03eSRichard }; 19389a1d03eSRichard 19489a1d03eSRichard struct PositiveValueMovableConstructor { 19589a1d03eSRichard PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {} 19689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy' 19789a1d03eSRichard // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {} 19889a1d03eSRichard ExpensiveMovableType Field; 19989a1d03eSRichard }; 20089a1d03eSRichard 20189a1d03eSRichard struct NegativeValueMovedConstructor { 20289a1d03eSRichard NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast<ExpensiveMovableType &&>(Copy)) {} 20389a1d03eSRichard ExpensiveMovableType Field; 20489a1d03eSRichard }; 20589a1d03eSRichard 20689a1d03eSRichard template <typename T> 20789a1d03eSRichard struct Container { 20889a1d03eSRichard typedef const T & const_reference; 20989a1d03eSRichard }; 21089a1d03eSRichard 21189a1d03eSRichard void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) { 21289a1d03eSRichard } 21389a1d03eSRichard 21489a1d03eSRichard #define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() \ 21589a1d03eSRichard void inMacro(const ExpensiveToCopyType T) { \ 21689a1d03eSRichard } \ 21789a1d03eSRichard // Ensure fix is not applied. 21889a1d03eSRichard // CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) { 21989a1d03eSRichard 22089a1d03eSRichard UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() 22189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T' 22289a1d03eSRichard 22389a1d03eSRichard #define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT) \ 22489a1d03eSRichard ARGUMENT 22589a1d03eSRichard 22689a1d03eSRichard UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}) 22789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg' 22889a1d03eSRichard // CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {} 22989a1d03eSRichard 23089a1d03eSRichard struct VirtualMethod { 23189a1d03eSRichard virtual ~VirtualMethod() {} 23289a1d03eSRichard virtual void handle(ExpensiveToCopyType T) const = 0; 23389a1d03eSRichard }; 23489a1d03eSRichard 23589a1d03eSRichard struct NegativeOverriddenMethod : public VirtualMethod { 23689a1d03eSRichard void handle(ExpensiveToCopyType Overridden) const { 23789a1d03eSRichard // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const { 23889a1d03eSRichard } 23989a1d03eSRichard }; 24089a1d03eSRichard 24189a1d03eSRichard struct VirtualMethodWarningOnly { 24289a1d03eSRichard virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {} 24389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'T' is copied 24489a1d03eSRichard // CHECK-FIXES: virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {} 24589a1d03eSRichard virtual ~VirtualMethodWarningOnly() {} 24689a1d03eSRichard }; 24789a1d03eSRichard 24889a1d03eSRichard struct PositiveNonVirualMethod { 24989a1d03eSRichard void method(const ExpensiveToCopyType T) {} 25089a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:41: warning: the const qualified parameter 'T' is copied 25189a1d03eSRichard // CHECK-FIXES: void method(const ExpensiveToCopyType& T) {} 25289a1d03eSRichard }; 25389a1d03eSRichard 25489a1d03eSRichard struct NegativeDeletedMethod { 25589a1d03eSRichard ~NegativeDeletedMethod() {} 25689a1d03eSRichard NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete; 25789a1d03eSRichard // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete; 25889a1d03eSRichard }; 25989a1d03eSRichard 26089a1d03eSRichard void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) { 26189a1d03eSRichard M.constMethod(); 26289a1d03eSRichard } 26389a1d03eSRichard 26489a1d03eSRichard void PositiveMoveOnCopyConstruction(ExpensiveMovableType E) { 26589a1d03eSRichard auto F = E; 26689a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:12: warning: parameter 'E' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param] 26789a1d03eSRichard // CHECK-FIXES: auto F = std::move(E); 26889a1d03eSRichard } 26989a1d03eSRichard 27089a1d03eSRichard void PositiveConstRefNotMoveSinceReferencedMultipleTimes(ExpensiveMovableType E) { 27189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:79: warning: the parameter 'E' is copied 27289a1d03eSRichard // CHECK-FIXES: void PositiveConstRefNotMoveSinceReferencedMultipleTimes(const ExpensiveMovableType& E) { 27389a1d03eSRichard auto F = E; 27489a1d03eSRichard auto G = E; 27589a1d03eSRichard } 27689a1d03eSRichard 27789a1d03eSRichard void PositiveMoveOnCopyAssignment(ExpensiveMovableType E) { 27889a1d03eSRichard ExpensiveMovableType F; 27989a1d03eSRichard F = E; 28089a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:7: warning: parameter 'E' is passed by value 28189a1d03eSRichard // CHECK-FIXES: F = std::move(E); 28289a1d03eSRichard } 28389a1d03eSRichard 28489a1d03eSRichard struct NotCopyAssigned { 28589a1d03eSRichard NotCopyAssigned &operator=(const ExpensiveMovableType &); 28689a1d03eSRichard }; 28789a1d03eSRichard 28889a1d03eSRichard void PositiveNoMoveForNonCopyAssigmentOperator(ExpensiveMovableType E) { 28989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:69: warning: the parameter 'E' is copied 29089a1d03eSRichard // CHECK-FIXES: void PositiveNoMoveForNonCopyAssigmentOperator(const ExpensiveMovableType& E) { 29189a1d03eSRichard NotCopyAssigned N; 29289a1d03eSRichard N = E; 29389a1d03eSRichard } 29489a1d03eSRichard 29589a1d03eSRichard // The argument could be moved but is not since copy statement is inside a loop. 29689a1d03eSRichard void PositiveNoMoveInsideLoop(ExpensiveMovableType E) { 29789a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' is copied 29889a1d03eSRichard // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) { 29989a1d03eSRichard for (;;) { 30089a1d03eSRichard auto F = E; 30189a1d03eSRichard } 30289a1d03eSRichard } 30389a1d03eSRichard 30489a1d03eSRichard void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) { 30589a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' is copied 30689a1d03eSRichard // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const ExpensiveToCopyType& T) { 30789a1d03eSRichard auto U = T; 30889a1d03eSRichard } 30989a1d03eSRichard 31089a1d03eSRichard void PositiveConstRefNotMoveAssignable(ExpensiveToCopyType A) { 31189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the parameter 'A' is copied 31289a1d03eSRichard // CHECK-FIXES: void PositiveConstRefNotMoveAssignable(const ExpensiveToCopyType& A) { 31389a1d03eSRichard ExpensiveToCopyType B; 31489a1d03eSRichard B = A; 31589a1d03eSRichard } 31689a1d03eSRichard 31789a1d03eSRichard // Case where parameter in declaration is already const-qualified but not in 31889a1d03eSRichard // implementation. Make sure a second 'const' is not added to the declaration. 31989a1d03eSRichard void PositiveConstDeclaration(const ExpensiveToCopyType A); 32089a1d03eSRichard // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A); 32189a1d03eSRichard void PositiveConstDeclaration(ExpensiveToCopyType A) { 32289a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' is copied 32389a1d03eSRichard // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) { 32489a1d03eSRichard } 32589a1d03eSRichard 32689a1d03eSRichard void PositiveNonConstDeclaration(ExpensiveToCopyType A); 32789a1d03eSRichard // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A); 32889a1d03eSRichard void PositiveNonConstDeclaration(const ExpensiveToCopyType A) { 32989a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A' 33089a1d03eSRichard // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) { 33189a1d03eSRichard } 33289a1d03eSRichard 33389a1d03eSRichard void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) { 33489a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' is copied 33589a1d03eSRichard // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) { 33689a1d03eSRichard } 33789a1d03eSRichard 33889a1d03eSRichard void ReferenceFunctionOutsideOfCallExpr() { 33989a1d03eSRichard void (*ptr)(ExpensiveToCopyType) = &PositiveOnlyMessageAsReferencedInCompilationUnit; 34089a1d03eSRichard } 34189a1d03eSRichard 34289a1d03eSRichard void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) { 34389a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' is copied 34489a1d03eSRichard // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) { 34589a1d03eSRichard } 34689a1d03eSRichard 34789a1d03eSRichard void ReferenceFunctionByCallingIt() { 34889a1d03eSRichard PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType()); 34989a1d03eSRichard } 35089a1d03eSRichard 35189a1d03eSRichard // Virtual method overrides of dependent types cannot be recognized unless they 35289a1d03eSRichard // are marked as override or final. Test that check is not triggered on methods 35389a1d03eSRichard // marked with override or final. 35489a1d03eSRichard template <typename T> 35589a1d03eSRichard struct NegativeDependentTypeInterface { 35689a1d03eSRichard virtual void Method(ExpensiveToCopyType E) = 0; 35789a1d03eSRichard }; 35889a1d03eSRichard 35989a1d03eSRichard template <typename T> 36089a1d03eSRichard struct NegativeOverrideImpl : public NegativeDependentTypeInterface<T> { 36189a1d03eSRichard void Method(ExpensiveToCopyType E) override {} 36289a1d03eSRichard }; 36389a1d03eSRichard 36489a1d03eSRichard template <typename T> 36589a1d03eSRichard struct NegativeFinalImpl : public NegativeDependentTypeInterface<T> { 36689a1d03eSRichard void Method(ExpensiveToCopyType E) final {} 36789a1d03eSRichard }; 36889a1d03eSRichard 36989a1d03eSRichard struct PositiveConstructor { 37089a1d03eSRichard PositiveConstructor(ExpensiveToCopyType E) : E(E) {} 37189a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:43: warning: the parameter 'E' is copied 37289a1d03eSRichard // CHECK-FIXES: PositiveConstructor(const ExpensiveToCopyType& E) : E(E) {} 37389a1d03eSRichard 37489a1d03eSRichard ExpensiveToCopyType E; 37589a1d03eSRichard }; 37689a1d03eSRichard 37789a1d03eSRichard struct NegativeUsingConstructor : public PositiveConstructor { 37889a1d03eSRichard using PositiveConstructor::PositiveConstructor; 37989a1d03eSRichard }; 38089a1d03eSRichard 38189a1d03eSRichard void fun() { 38289a1d03eSRichard ExpensiveToCopyType E; 38389a1d03eSRichard NegativeUsingConstructor S(E); 38489a1d03eSRichard } 385*1ce89899SDmitry Polukhin 386*1ce89899SDmitry Polukhin struct B { 387*1ce89899SDmitry Polukhin static void bar(ExpensiveMovableType a, ExpensiveMovableType b); 388*1ce89899SDmitry Polukhin }; 389*1ce89899SDmitry Polukhin 390*1ce89899SDmitry Polukhin template <typename T> 391*1ce89899SDmitry Polukhin void NegativeCallWithDependentAndNondependentArgs(ExpensiveMovableType a, T b) { 392*1ce89899SDmitry Polukhin B::bar(std::move(a), b); 393*1ce89899SDmitry Polukhin } 394