189a1d03eSRichard // RUN: %check_clang_tidy %s performance-unnecessary-value-param %t -- -- -fdelayed-template-parsing
289a1d03eSRichard 
389a1d03eSRichard struct ExpensiveToCopyType {
489a1d03eSRichard   const ExpensiveToCopyType & constReference() const {
589a1d03eSRichard     return *this;
689a1d03eSRichard   }
789a1d03eSRichard   void nonConstMethod();
889a1d03eSRichard   virtual ~ExpensiveToCopyType();
989a1d03eSRichard };
1089a1d03eSRichard 
1189a1d03eSRichard void mutate(ExpensiveToCopyType &);
1289a1d03eSRichard void mutate(ExpensiveToCopyType *);
1389a1d03eSRichard void useAsConstReference(const ExpensiveToCopyType &);
1489a1d03eSRichard void useByValue(ExpensiveToCopyType);
1589a1d03eSRichard 
1689a1d03eSRichard // This class simulates std::pair<>. It is trivially copy constructible
1789a1d03eSRichard // and trivially destructible, but not trivially copy assignable.
1889a1d03eSRichard class SomewhatTrivial {
1989a1d03eSRichard  public:
2089a1d03eSRichard   SomewhatTrivial();
2189a1d03eSRichard   SomewhatTrivial(const SomewhatTrivial&) = default;
2289a1d03eSRichard   ~SomewhatTrivial() = default;
2389a1d03eSRichard   SomewhatTrivial& operator=(const SomewhatTrivial&);
2489a1d03eSRichard };
2589a1d03eSRichard 
2689a1d03eSRichard void positiveExpensiveConstValue(const ExpensiveToCopyType Obj);
2789a1d03eSRichard // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj);
2889a1d03eSRichard void positiveExpensiveConstValue(const ExpensiveToCopyType Obj) {
2989a1d03eSRichard   // 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]
3089a1d03eSRichard   // CHECK-FIXES: void positiveExpensiveConstValue(const ExpensiveToCopyType& Obj) {
3189a1d03eSRichard }
3289a1d03eSRichard 
3389a1d03eSRichard void positiveExpensiveValue(ExpensiveToCopyType Obj);
3489a1d03eSRichard // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj);
3589a1d03eSRichard void positiveExpensiveValue(ExpensiveToCopyType Obj) {
3689a1d03eSRichard   // 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]
3789a1d03eSRichard   // CHECK-FIXES: void positiveExpensiveValue(const ExpensiveToCopyType& Obj) {
3889a1d03eSRichard   Obj.constReference();
3989a1d03eSRichard   useAsConstReference(Obj);
4089a1d03eSRichard   auto Copy = Obj;
4189a1d03eSRichard   useByValue(Obj);
4289a1d03eSRichard }
4389a1d03eSRichard 
4489a1d03eSRichard void positiveWithComment(const ExpensiveToCopyType /* important */ S);
4589a1d03eSRichard // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S);
4689a1d03eSRichard void positiveWithComment(const ExpensiveToCopyType /* important */ S) {
4789a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:68: warning: the const qualified
4889a1d03eSRichard   // CHECK-FIXES: void positiveWithComment(const ExpensiveToCopyType& /* important */ S) {
4989a1d03eSRichard }
5089a1d03eSRichard 
5189a1d03eSRichard void positiveUnnamedParam(const ExpensiveToCopyType) {
5289a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter #1
5389a1d03eSRichard   // CHECK-FIXES: void positiveUnnamedParam(const ExpensiveToCopyType&) {
5489a1d03eSRichard }
5589a1d03eSRichard 
5689a1d03eSRichard void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy);
5789a1d03eSRichard // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy);
5889a1d03eSRichard void positiveAndNegative(const ExpensiveToCopyType ConstCopy, const ExpensiveToCopyType& ConstRef, ExpensiveToCopyType Copy) {
5989a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:52: warning: the const qualified parameter 'ConstCopy'
6089a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-2]]:120: warning: the parameter 'Copy'
6189a1d03eSRichard   // CHECK-FIXES: void positiveAndNegative(const ExpensiveToCopyType& ConstCopy, const ExpensiveToCopyType& ConstRef, const ExpensiveToCopyType& Copy) {
6289a1d03eSRichard }
6389a1d03eSRichard 
6489a1d03eSRichard struct PositiveConstValueConstructor {
6589a1d03eSRichard   PositiveConstValueConstructor(const ExpensiveToCopyType ConstCopy) {}
6689a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:59: warning: the const qualified parameter 'ConstCopy'
6789a1d03eSRichard   // CHECK-FIXES: PositiveConstValueConstructor(const ExpensiveToCopyType& ConstCopy) {}
6889a1d03eSRichard };
6989a1d03eSRichard 
7089a1d03eSRichard template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType S, T V) {
7189a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'S'
72*8e42e0d2SVitaly Goldshteyn   // CHECK-MESSAGES: [[@LINE-2]]:95: warning: the parameter 'V'
73*8e42e0d2SVitaly Goldshteyn   // CHECK-FIXES: template <typename T> void templateWithNonTemplatizedParameter(const ExpensiveToCopyType& S, const T& V) {
7489a1d03eSRichard }
7589a1d03eSRichard 
7689a1d03eSRichard void instantiated() {
7789a1d03eSRichard   templateWithNonTemplatizedParameter(ExpensiveToCopyType(), ExpensiveToCopyType());
7889a1d03eSRichard   templateWithNonTemplatizedParameter(ExpensiveToCopyType(), 5);
7989a1d03eSRichard }
8089a1d03eSRichard 
8189a1d03eSRichard template <typename T> void negativeTemplateType(const T V) {
8289a1d03eSRichard }
8389a1d03eSRichard 
8489a1d03eSRichard void negativeArray(const ExpensiveToCopyType[]) {
8589a1d03eSRichard }
8689a1d03eSRichard 
8789a1d03eSRichard void negativePointer(ExpensiveToCopyType* Obj) {
8889a1d03eSRichard }
8989a1d03eSRichard 
9089a1d03eSRichard void negativeConstPointer(const ExpensiveToCopyType* Obj) {
9189a1d03eSRichard }
9289a1d03eSRichard 
9389a1d03eSRichard void negativeConstReference(const ExpensiveToCopyType& Obj) {
9489a1d03eSRichard }
9589a1d03eSRichard 
9689a1d03eSRichard void negativeReference(ExpensiveToCopyType& Obj) {
9789a1d03eSRichard }
9889a1d03eSRichard 
9989a1d03eSRichard void negativeUniversalReference(ExpensiveToCopyType&& Obj) {
10089a1d03eSRichard }
10189a1d03eSRichard 
10289a1d03eSRichard void negativeSomewhatTrivialConstValue(const SomewhatTrivial Somewhat) {
10389a1d03eSRichard }
10489a1d03eSRichard 
10589a1d03eSRichard void negativeSomewhatTrivialValue(SomewhatTrivial Somewhat) {
10689a1d03eSRichard }
10789a1d03eSRichard 
10889a1d03eSRichard void negativeConstBuiltIn(const int I) {
10989a1d03eSRichard }
11089a1d03eSRichard 
11189a1d03eSRichard void negativeValueBuiltIn(int I) {
11289a1d03eSRichard }
11389a1d03eSRichard 
11489a1d03eSRichard void negativeValueIsMutatedByReference(ExpensiveToCopyType Obj) {
11589a1d03eSRichard   mutate(Obj);
11689a1d03eSRichard }
11789a1d03eSRichard 
11889a1d03eSRichard void negativeValueIsMutatatedByPointer(ExpensiveToCopyType Obj) {
11989a1d03eSRichard   mutate(&Obj);
12089a1d03eSRichard }
12189a1d03eSRichard 
12289a1d03eSRichard void negativeValueIsReassigned(ExpensiveToCopyType Obj) {
12389a1d03eSRichard   Obj = ExpensiveToCopyType();
12489a1d03eSRichard }
12589a1d03eSRichard 
12689a1d03eSRichard void negativeValueNonConstMethodIsCalled(ExpensiveToCopyType Obj) {
12789a1d03eSRichard   Obj.nonConstMethod();
12889a1d03eSRichard }
12989a1d03eSRichard 
13089a1d03eSRichard struct PositiveValueUnusedConstructor {
13189a1d03eSRichard   PositiveValueUnusedConstructor(ExpensiveToCopyType Copy) {}
13289a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
13389a1d03eSRichard   // CHECK-FIXES: PositiveValueUnusedConstructor(const ExpensiveToCopyType& Copy) {}
13489a1d03eSRichard };
13589a1d03eSRichard 
13689a1d03eSRichard struct PositiveValueCopiedConstructor {
13789a1d03eSRichard   PositiveValueCopiedConstructor(ExpensiveToCopyType Copy) : Field(Copy) {}
13889a1d03eSRichard   // CHECK-MESSAGES: [[@LINE-1]]:54: warning: the parameter 'Copy'
13989a1d03eSRichard   // CHECK-FIXES: PositiveValueCopiedConstructor(const ExpensiveToCopyType& Copy) : Field(Copy) {}
14089a1d03eSRichard   ExpensiveToCopyType Field;
14189a1d03eSRichard };
14289a1d03eSRichard 
14389a1d03eSRichard template <typename T>
14489a1d03eSRichard struct Container {
14589a1d03eSRichard   typedef const T & const_reference;
14689a1d03eSRichard };
14789a1d03eSRichard 
14889a1d03eSRichard void NegativeTypedefParam(const Container<ExpensiveToCopyType>::const_reference Param) {
14989a1d03eSRichard }
15089a1d03eSRichard 
15189a1d03eSRichard #define UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()         \
15289a1d03eSRichard   void inMacro(const ExpensiveToCopyType T) {           \
15389a1d03eSRichard   }                                                     \
15489a1d03eSRichard // Ensure fix is not applied.
15589a1d03eSRichard // CHECK-FIXES: void inMacro(const ExpensiveToCopyType T) {
15689a1d03eSRichard 
15789a1d03eSRichard UNNECESSARY_VALUE_PARAM_IN_MACRO_BODY()
15889a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:1: warning: the const qualified parameter 'T'
15989a1d03eSRichard 
16089a1d03eSRichard #define UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(ARGUMENT)     \
16189a1d03eSRichard   ARGUMENT
16289a1d03eSRichard 
16389a1d03eSRichard UNNECESSARY_VALUE_PARAM_IN_MACRO_ARGUMENT(void inMacroArgument(const ExpensiveToCopyType InMacroArg) {})
16489a1d03eSRichard // CHECK-MESSAGES: [[@LINE-1]]:90: warning: the const qualified parameter 'InMacroArg'
16589a1d03eSRichard // CHECK-FIXES: void inMacroArgument(const ExpensiveToCopyType InMacroArg) {}
16689a1d03eSRichard 
16789a1d03eSRichard struct VirtualMethod {
16889a1d03eSRichard   virtual ~VirtualMethod() {}
16989a1d03eSRichard   virtual void handle(ExpensiveToCopyType T) const = 0;
17089a1d03eSRichard };
17189a1d03eSRichard 
17289a1d03eSRichard struct NegativeOverriddenMethod : public VirtualMethod {
17389a1d03eSRichard   void handle(ExpensiveToCopyType Overridden) const {
17489a1d03eSRichard     // CHECK-FIXES: handle(ExpensiveToCopyType Overridden) const {
17589a1d03eSRichard   }
17689a1d03eSRichard };
17789a1d03eSRichard 
17889a1d03eSRichard struct NegativeDeletedMethod {
17989a1d03eSRichard   ~NegativeDeletedMethod() {}
18089a1d03eSRichard   NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
18189a1d03eSRichard   // CHECK-FIXES: NegativeDeletedMethod& operator=(NegativeDeletedMethod N) = delete;
18289a1d03eSRichard };
183