1 // RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \
2 // RUN:   -config='{CheckOptions: [ \
3 // RUN:     {key: bugprone-easily-swappable-parameters.MinimumLength, value: 2}, \
4 // RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterNames, value: ""}, \
5 // RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes, value: ""}, \
6 // RUN:     {key: bugprone-easily-swappable-parameters.QualifiersMix, value: 0}, \
7 // RUN:     {key: bugprone-easily-swappable-parameters.ModelImplicitConversions, value: 0}, \
8 // RUN:     {key: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether, value: 1}, \
9 // RUN:     {key: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold, value: 0} \
10 // RUN:  ]}' --
11 
12 namespace std {
13 template <typename T>
14 T max(const T &A, const T &B);
15 } // namespace std
16 
17 bool coin();
18 void f(int);
19 void g(int);
20 void h(int, int);
21 void i(int, bool);
22 void i(int, char);
23 
24 struct Tmp {
25   int f(int);
26   int g(int, int);
27 };
28 
29 struct Int {
30   int I;
31 };
32 
compare(int Left,int Right)33 void compare(int Left, int Right) {}
34 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'compare' of similar type ('int')
35 // CHECK-MESSAGES: :[[@LINE-2]]:18: note: the first parameter in the range is 'Left'
36 // CHECK-MESSAGES: :[[@LINE-3]]:28: note: the last parameter in the range is 'Right'
37 
decideSequence(int A,int B)38 int decideSequence(int A, int B) {
39   if (A)
40     return 1;
41   if (B)
42     return 2;
43   return 3;
44 }
45 // CHECK-MESSAGES: :[[@LINE-7]]:20: warning: 2 adjacent parameters of 'decideSequence' of similar type ('int')
46 // CHECK-MESSAGES: :[[@LINE-8]]:24: note: the first parameter in the range is 'A'
47 // CHECK-MESSAGES: :[[@LINE-9]]:31: note: the last parameter in the range is 'B'
48 
myMax(int A,int B)49 int myMax(int A, int B) { // NO-WARN: Appears in same expression.
50   return A < B ? A : B;
51 }
52 
myMax2(int A,int B)53 int myMax2(int A, int B) { // NO-WARN: Appears in same expression.
54   if (A < B)
55     return A;
56   return B;
57 }
58 
myMax3(int A,int B)59 int myMax3(int A, int B) { // NO-WARN: Appears in same expression.
60   return std::max(A, B);
61 }
62 
binaryToUnary(int A,int)63 int binaryToUnary(int A, int) {
64   return A;
65 }
66 // CHECK-MESSAGES: :[[@LINE-3]]:19: warning: 2 adjacent parameters of 'binaryToUnary' of similar type ('int')
67 // CHECK-MESSAGES: :[[@LINE-4]]:23: note: the first parameter in the range is 'A'
68 // CHECK-MESSAGES: :[[@LINE-5]]:29: note: the last parameter in the range is '<unnamed>'
69 
randomReturn1(int A,int B)70 int randomReturn1(int A, int B) { // NO-WARN: Appears in same expression.
71   return coin() ? A : B;
72 }
73 
randomReturn2(int A,int B)74 int randomReturn2(int A, int B) { // NO-WARN: Both parameters returned.
75   if (coin())
76     return A;
77   return B;
78 }
79 
randomReturn3(int A,int B)80 int randomReturn3(int A, int B) { // NO-WARN: Both parameters returned.
81   bool Flip = coin();
82   if (Flip)
83     return A;
84   Flip = coin();
85   if (Flip)
86     return B;
87   Flip = coin();
88   if (!Flip)
89     return 0;
90   return -1;
91 }
92 
passthrough1(int A,int B)93 void passthrough1(int A, int B) { // WARN: Different functions, different params.
94   f(A);
95   g(B);
96 }
97 // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough1' of similar type ('int')
98 // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A'
99 // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B'
100 
passthrough2(int A,int B)101 void passthrough2(int A, int B) { // NO-WARN: Passed to same index of same function.
102   f(A);
103   f(B);
104 }
105 
passthrough3(int A,int B)106 void passthrough3(int A, int B) { // NO-WARN: Passed to same index of same funtion.
107   h(1, A);
108   h(1, B);
109 }
110 
passthrough4(int A,int B)111 void passthrough4(int A, int B) { // WARN: Different index used.
112   h(1, A);
113   h(B, 2);
114 }
115 // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough4' of similar type ('int')
116 // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A'
117 // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B'
118 
passthrough5(int A,int B)119 void passthrough5(int A, int B) { // WARN: Different function overload.
120   i(A, false);
121   i(A, '\0');
122 }
123 // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough5' of similar type ('int')
124 // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A'
125 // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B'
126 
passthrough6(int A,int B)127 void passthrough6(int A, int B) { // NO-WARN: Passed to same index of same function.
128   Tmp Temp;
129   Temp.f(A);
130   Temp.f(B);
131 }
132 
passthrough7(int A,int B)133 void passthrough7(int A, int B) { // NO-WARN: Passed to same index of same function.
134   // Clang-Tidy isn't path sensitive, the fact that the two objects we call the
135   // function on is different is not modelled.
136   Tmp Temp1, Temp2;
137   Temp1.f(A);
138   Temp2.f(B);
139 }
140 
passthrough8(int A,int B)141 void passthrough8(int A, int B) { // WARN: Different functions used.
142   f(A);
143   Tmp{}.f(B);
144 }
145 // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough8' of similar type ('int')
146 // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A'
147 // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B'
148 
149 // Test that the matching of "passed-to-function" is done to the proper node.
150 // Put simply, this test should not crash here.
151 void forwardDeclared(int X);
152 
passthrough9(int A,int B)153 void passthrough9(int A, int B) { // NO-WARN: Passed to same index of same function.
154   forwardDeclared(A);
155   forwardDeclared(B);
156 }
157 
forwardDeclared(int X)158 void forwardDeclared(int X) {}
159 
passthrough10(int A,int B)160 void passthrough10(int A, int B) { // NO-WARN: Passed to same index of same function.
161   forwardDeclared(A);
162   forwardDeclared(B);
163 }
164 
compare1(Int I,Int J)165 bool compare1(Int I, Int J) { // NO-WARN: Same member accessed.
166   int Val1 = I.I;
167   int Val2 = J.I;
168   return Val1 < Val2;
169 }
170 
compare2(Tmp T1,Tmp T2)171 bool compare2(Tmp T1, Tmp T2) { // NO-WARN: Same member accessed.
172   int Val1 = T1.g(0, 1);
173   int Val2 = T2.g(2, 3);
174   return Val1 < Val2;
175 }
176 
compare3(Tmp T1,Tmp T2)177 bool compare3(Tmp T1, Tmp T2) { // WARN: Different member accessed.
178   int Val1 = T1.f(0);
179   int Val2 = T2.g(1, 2);
180   return Val1 < Val2;
181 }
182 // CHECK-MESSAGES: :[[@LINE-5]]:15: warning: 2 adjacent parameters of 'compare3' of similar type ('Tmp')
183 // CHECK-MESSAGES: :[[@LINE-6]]:19: note: the first parameter in the range is 'T1'
184 // CHECK-MESSAGES: :[[@LINE-7]]:27: note: the last parameter in the range is 'T2'
185 
rangeBreaker(int I,int J,int K,int L,int M,int N)186 int rangeBreaker(int I, int J, int K, int L, int M, int N) {
187   // (I, J) swappable.
188 
189   if (J == K) // (J, K) related.
190     return -1;
191 
192   if (K + 2 > Tmp{}.f(K))
193     return M;
194 
195   // (K, L, M) swappable.
196 
197   return N; // (M, N) related.
198 }
199 // CHECK-MESSAGES: :[[@LINE-13]]:18: warning: 2 adjacent parameters of 'rangeBreaker' of similar type ('int')
200 // CHECK-MESSAGES: :[[@LINE-14]]:22: note: the first parameter in the range is 'I'
201 // CHECK-MESSAGES: :[[@LINE-15]]:29: note: the last parameter in the range is 'J'
202 // CHECK-MESSAGES: :[[@LINE-16]]:32: warning: 3 adjacent parameters of 'rangeBreaker' of similar type ('int')
203 // CHECK-MESSAGES: :[[@LINE-17]]:36: note: the first parameter in the range is 'K'
204 // CHECK-MESSAGES: :[[@LINE-18]]:50: note: the last parameter in the range is 'M'
205 
returnsNotOwnParameter(int I,int J,int K)206 int returnsNotOwnParameter(int I, int J, int K) {
207   const auto &Lambda = [&K](int L, int M, int N) {
208     if (K)
209       return L;
210     return M; // (L, M) related.
211   };
212 
213   if (Lambda(-1, 0, 1))
214     return I;
215   return J; // (I, J) related.
216 }
217 // CHECK-MESSAGES: :[[@LINE-11]]:35: warning: 2 adjacent parameters of 'returnsNotOwnParameter' of similar type ('int')
218 // CHECK-MESSAGES: :[[@LINE-12]]:39: note: the first parameter in the range is 'J'
219 // CHECK-MESSAGES: :[[@LINE-13]]:46: note: the last parameter in the range is 'K'
220 // CHECK-MESSAGES: :[[@LINE-13]]:36: warning: 2 adjacent parameters of 'operator()' of similar type ('int')
221 // CHECK-MESSAGES: :[[@LINE-14]]:40: note: the first parameter in the range is 'M'
222 // CHECK-MESSAGES: :[[@LINE-15]]:47: note: the last parameter in the range is 'N'
223 
usedTogetherInCapture(int I,int J,int K)224 int usedTogetherInCapture(int I, int J, int K) { // NO-WARN: Used together.
225   const auto &Lambda = [I, J, K]() {
226     int A = I + 1;
227     int B = J - 2;
228     int C = K * 3;
229     return A + B + C;
230   };
231   return Lambda();
232 }
233