1 | // RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \ |
2 | // RUN: -config='{CheckOptions: { \ |
3 | // RUN: bugprone-easily-swappable-parameters.MinimumLength: 2, \ |
4 | // RUN: bugprone-easily-swappable-parameters.IgnoredParameterNames: "", \ |
5 | // RUN: bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: "", \ |
6 | // RUN: bugprone-easily-swappable-parameters.QualifiersMix: 0, \ |
7 | // RUN: bugprone-easily-swappable-parameters.ModelImplicitConversions: 0, \ |
8 | // RUN: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 1, \ |
9 | // RUN: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: 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 | |
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 | |
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 | |
49 | int myMax(int A, int B) { // NO-WARN: Appears in same expression. |
50 | return A < B ? A : B; |
51 | } |
52 | |
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 | |
59 | int myMax3(int A, int B) { // NO-WARN: Appears in same expression. |
60 | return std::max(A, B); |
61 | } |
62 | |
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 | |
70 | int randomReturn1(int A, int B) { // NO-WARN: Appears in same expression. |
71 | return coin() ? A : B; |
72 | } |
73 | |
74 | int randomReturn2(int A, int B) { // NO-WARN: Both parameters returned. |
75 | if (coin()) |
76 | return A; |
77 | return B; |
78 | } |
79 | |
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 | |
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 | |
101 | void passthrough2(int A, int B) { // NO-WARN: Passed to same index of same function. |
102 | f(A); |
103 | f(B); |
104 | } |
105 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
153 | void passthrough9(int A, int B) { // NO-WARN: Passed to same index of same function. |
154 | forwardDeclared(X: A); |
155 | forwardDeclared(X: B); |
156 | } |
157 | |
158 | void forwardDeclared(int X) {} |
159 | |
160 | void passthrough10(int A, int B) { // NO-WARN: Passed to same index of same function. |
161 | forwardDeclared(X: A); |
162 | forwardDeclared(X: B); |
163 | } |
164 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |