| 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 | |