390 lines · cpp
1// RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fno-delayed-template-parsing2 3// CHECK-FIXES: #include <utility>4 5namespace std {6template <typename>7struct remove_reference;8 9template <typename _Tp>10struct remove_reference {11 typedef _Tp type;12};13 14template <typename _Tp>15struct remove_reference<_Tp &> {16 typedef _Tp type;17};18 19template <typename _Tp>20struct remove_reference<_Tp &&> {21 typedef _Tp type;22};23 24template <typename _Tp>25constexpr typename std::remove_reference<_Tp>::type &&move(_Tp &&__t) {26 return static_cast<typename std::remove_reference<_Tp>::type &&>(__t);27}28} // namespace std29 30struct ExpensiveToCopyType {31 const ExpensiveToCopyType & constReference() const {32 return *this;33 }34 void nonConstMethod();35 virtual ~ExpensiveToCopyType();36};37 38void mutate(ExpensiveToCopyType &);39void mutate(ExpensiveToCopyType *);40void useAsConstReference(const ExpensiveToCopyType &);41void useByValue(ExpensiveToCopyType);42 43template <class T> class Vector {44 public:45 using iterator = T*;46 using const_iterator = const T*;47 48 Vector(const Vector&);49 Vector& operator=(const Vector&);50 51 iterator begin();52 iterator end();53 const_iterator begin() const;54 const_iterator end() const;55};56 57// This class simulates std::pair<>. It is trivially copy constructible58// and trivially destructible, but not trivially copy assignable.59class SomewhatTrivial {60 public:61 SomewhatTrivial();62 SomewhatTrivial(const SomewhatTrivial&) = default;63 ~SomewhatTrivial() = default;64 SomewhatTrivial& operator=(const SomewhatTrivial&);65};66 67struct MoveOnlyType {68 MoveOnlyType(const MoveOnlyType &) = delete;69 MoveOnlyType(MoveOnlyType &&) = default;70 ~MoveOnlyType();71 void constMethod() const;72};73 74struct ExpensiveMovableType {75 ExpensiveMovableType();76 ExpensiveMovableType(ExpensiveMovableType &&);77 ExpensiveMovableType(const ExpensiveMovableType &) = default;78 ExpensiveMovableType &operator=(const ExpensiveMovableType &) = default;79 ExpensiveMovableType &operator=(ExpensiveMovableType &&);80 ~ExpensiveMovableType();81};82 83void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);84// CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);85void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {86 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'Obj' of type 'const ExpensiveToCopyType' is copied for each invocation; consider making it a reference [performance-unnecessary-value-param]87 // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {88}89 90void positiveExpensiveValue(ExpensiveToCopyType Obj);91// CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);92void positiveExpensiveValue(ExpensiveToCopyType Obj) {93 // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'Obj' of type 'ExpensiveToCopyType' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]94 // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {95 Obj.constReference();96 useAsConstReference(Obj);97 auto Copy = Obj;98 useByValue(Obj);99}100 101void positiveVector(Vector<ExpensiveToCopyType> V) {102 // CHECK-MESSAGES: [[@LINE-1]]:49: warning: the parameter 'V' of type 'Vector<ExpensiveToCopyType>' is copied for each invocation but only used as a const reference; consider making it a const reference [performance-unnecessary-value-param]103 // CHECK-FIXES: void positiveVector(const Vector<ExpensiveToCopyType>& V) {104 for (const auto& Obj : V) {105 useByValue(Obj);106 }107}108 109void positiveWithComment(const ExpensiveToCopyType /* important */ S);110// CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);111void positiveWithComment(const ExpensiveToCopyType /* important */ S) {112 // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified113 // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {114}115 116void positiveUnnamedParam(const ExpensiveToCopyType) {117 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1118 // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {119}120 121void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);122// CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);123void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {124 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'125 // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'126 // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {127}128 129struct PositiveConstValueConstructor {130 PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}131 // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'132 // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}133};134 135void negativeArray(const ExpensiveToCopyType[]) {136}137 138void negativePointer(ExpensiveToCopyType* Obj) {139}140 141void negativeConstPointer(const ExpensiveToCopyType* Obj) {142}143 144void negativeConstReference(const ExpensiveToCopyType& Obj) {145}146 147void negativeReference(ExpensiveToCopyType& Obj) {148}149 150void negativeUniversalReference(ExpensiveToCopyType&& Obj) {151}152 153void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {154}155 156void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {157}158 159void negativeConstBuiltIn(const int I) {160}161 162void negativeValueBuiltIn(int I) {163}164 165void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {166 mutate(Obj);167}168 169void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {170 mutate(&Obj);171}172 173void negativeValueIsReassigned(ExpensiveToCopyType Obj) {174 Obj = ExpensiveToCopyType();175}176 177void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {178 Obj.nonConstMethod();179}180 181struct PositiveValueUnusedConstructor {182 PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}183 // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'184 // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}185};186 187struct PositiveValueCopiedConstructor {188 PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}189 // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'190 // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}191 ExpensiveToCopyType Field;192};193 194struct PositiveValueMovableConstructor {195 PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(Copy) {}196 // CHECK-MESSAGES: [[@LINE-1]]:70: warning: parameter 'Copy'197 // CHECK-FIXES: PositiveValueMovableConstructor(ExpensiveMovableType Copy) : Field(std::move(Copy)) {}198 ExpensiveMovableType Field;199};200 201struct NegativeValueMovedConstructor {202 NegativeValueMovedConstructor(ExpensiveMovableType Copy) : Field(static_cast<ExpensiveMovableType &&>(Copy)) {}203 ExpensiveMovableType Field;204};205 206template <typename T>207struct Container {208 typedef const T & const_reference;209};210 211void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {212}213 214#define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY() \215 void inMacro(const ExpensiveToCopyType T) { \216 } \217// Ensure fix is not applied.218// CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) { {{\\}}219 220UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()221// CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'222 223#define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT) \224 ARGUMENT225 226UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})227// CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'228// CHECK-FIXES: UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})229 230struct VirtualMethod {231 virtual ~VirtualMethod() {}232 virtual void handle(ExpensiveToCopyType T) const = 0;233};234 235struct NegativeOverriddenMethod : public VirtualMethod {236 void handle(ExpensiveToCopyType Overridden) const {237 // CHECK-FIXES: void handle(ExpensiveToCopyType Overridden) const {238 }239};240 241struct VirtualMethodWarningOnly {242 virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}243 // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'T' of type 'ExpensiveToCopyType' is copied244 // CHECK-FIXES: virtual void methodWithExpensiveValueParam(ExpensiveToCopyType T) {}245 virtual ~VirtualMethodWarningOnly() {}246};247 248struct PositiveNonVirualMethod {249 void method(const ExpensiveToCopyType T) {}250 // CHECK-MESSAGES: [[@LINE-1]]:41: warning: the const qualified parameter 'T' of type 'const ExpensiveToCopyType' is copied251 // CHECK-FIXES: void method(const ExpensiveToCopyType& T) {}252};253 254struct NegativeDeletedMethod {255 ~NegativeDeletedMethod() {}256 NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;257 // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;258};259 260void NegativeMoveOnlyTypePassedByValue(MoveOnlyType M) {261 M.constMethod();262}263 264void PositiveMoveOnCopyConstruction(ExpensiveMovableType E) {265 auto F = E;266 // CHECK-MESSAGES: [[@LINE-1]]:12: warning: parameter 'E' of type 'ExpensiveMovableType' is passed by value and only copied once; consider moving it to avoid unnecessary copies [performance-unnecessary-value-param]267 // CHECK-FIXES: auto F = std::move(E);268}269 270void PositiveConstRefNotMoveSinceReferencedMultipleTimes(ExpensiveMovableType E) {271 // CHECK-MESSAGES: [[@LINE-1]]:79: warning: the parameter 'E' of type 'ExpensiveMovableType' is copied272 // CHECK-FIXES: void PositiveConstRefNotMoveSinceReferencedMultipleTimes(const ExpensiveMovableType& E) {273 auto F = E;274 auto G = E;275}276 277void PositiveMoveOnCopyAssignment(ExpensiveMovableType E) {278 ExpensiveMovableType F;279 F = E;280 // CHECK-MESSAGES: [[@LINE-1]]:7: warning: parameter 'E' of type 'ExpensiveMovableType' is passed by value281 // CHECK-FIXES: F = std::move(E);282}283 284struct NotCopyAssigned {285 NotCopyAssigned &operator=(const ExpensiveMovableType &);286};287 288void PositiveNoMoveForNonCopyAssignmentOperator(ExpensiveMovableType E) {289 // CHECK-MESSAGES: [[@LINE-1]]:70: warning: the parameter 'E' of type 'ExpensiveMovableType' is copied290 // CHECK-FIXES: void PositiveNoMoveForNonCopyAssignmentOperator(const ExpensiveMovableType& E) {291 NotCopyAssigned N;292 N = E;293}294 295// The argument could be moved but is not since copy statement is inside a loop.296void PositiveNoMoveInsideLoop(ExpensiveMovableType E) {297 // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the parameter 'E' of type 'ExpensiveMovableType' is copied298 // CHECK-FIXES: void PositiveNoMoveInsideLoop(const ExpensiveMovableType& E) {299 for (;;) {300 auto F = E;301 }302}303 304void PositiveConstRefNotMoveConstructible(ExpensiveToCopyType T) {305 // CHECK-MESSAGES: [[@LINE-1]]:63: warning: the parameter 'T' of type 'ExpensiveToCopyType' is copied306 // CHECK-FIXES: void PositiveConstRefNotMoveConstructible(const ExpensiveToCopyType& T) {307 auto U = T;308}309 310void PositiveConstRefNotMoveAssignable(ExpensiveToCopyType A) {311 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the parameter 'A' of type 'ExpensiveToCopyType' is copied312 // CHECK-FIXES: void PositiveConstRefNotMoveAssignable(const ExpensiveToCopyType& A) {313 ExpensiveToCopyType B;314 B = A;315}316 317// Case where parameter in declaration is already const-qualified but not in318// implementation. Make sure a second 'const' is not added to the declaration.319void PositiveConstDeclaration(const ExpensiveToCopyType A);320// CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A);321void PositiveConstDeclaration(ExpensiveToCopyType A) {322 // CHECK-MESSAGES: [[@LINE-1]]:51: warning: the parameter 'A' of type 'ExpensiveToCopyType' is copied323 // CHECK-FIXES: void PositiveConstDeclaration(const ExpensiveToCopyType& A) {324}325 326void PositiveNonConstDeclaration(ExpensiveToCopyType A);327// CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A);328void PositiveNonConstDeclaration(const ExpensiveToCopyType A) {329 // CHECK-MESSAGES: [[@LINE-1]]:60: warning: the const qualified parameter 'A' of type 'const ExpensiveToCopyType'330 // CHECK-FIXES: void PositiveNonConstDeclaration(const ExpensiveToCopyType& A) {331}332 333void PositiveOnlyMessageAsReferencedInCompilationUnit(ExpensiveToCopyType A) {334 // CHECK-MESSAGES: [[@LINE-1]]:75: warning: the parameter 'A' of type 'ExpensiveToCopyType' is copied335 // CHECK-FIXES: void PositiveOnlyMessageAsReferencedInCompilationUnit(const ExpensiveToCopyType& A) {336}337 338void PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType A) {339 // CHECK-MESSAGES: [[@LINE-1]]:66: warning: the parameter 'A' of type 'ExpensiveToCopyType' is copied340 // CHECK-FIXES: void PositiveMessageAndFixAsFunctionIsCalled(const ExpensiveToCopyType& A) {341}342 343void ReferenceFunctionByCallingIt() {344 PositiveMessageAndFixAsFunctionIsCalled(ExpensiveToCopyType());345}346 347// Virtual method overrides of dependent types cannot be recognized unless they348// are marked as override or final. Test that check is not triggered on methods349// marked with override or final.350template <typename T>351struct NegativeDependentTypeInterface {352 virtual void Method(ExpensiveToCopyType E) = 0;353};354 355template <typename T>356struct NegativeOverrideImpl : public NegativeDependentTypeInterface<T> {357 void Method(ExpensiveToCopyType E) override {}358};359 360template <typename T>361struct NegativeFinalImpl : public NegativeDependentTypeInterface<T> {362 void Method(ExpensiveToCopyType E) final {}363};364 365struct PositiveConstructor {366 PositiveConstructor(ExpensiveToCopyType E) : E(E) {}367 // CHECK-MESSAGES: [[@LINE-1]]:43: warning: the parameter 'E' of type 'ExpensiveToCopyType' is copied368 // CHECK-FIXES: PositiveConstructor(const ExpensiveToCopyType& E) : E(E) {}369 370 ExpensiveToCopyType E;371};372 373struct NegativeUsingConstructor : public PositiveConstructor {374 using PositiveConstructor::PositiveConstructor;375};376 377void fun() {378 ExpensiveToCopyType E;379 NegativeUsingConstructor S(E);380}381 382struct B {383 static void bar(ExpensiveMovableType a, ExpensiveMovableType b);384};385 386template <typename T>387void NegativeCallWithDependentAndNondependentArgs(ExpensiveMovableType a, T b) {388 B::bar(std::move(a), b);389}390