// RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \ // RUN: -config='{CheckOptions: { \ // RUN: bugprone-easily-swappable-parameters.MinimumLength: 2, \ // RUN: bugprone-easily-swappable-parameters.IgnoredParameterNames: "", \ // RUN: bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: "", \ // RUN: bugprone-easily-swappable-parameters.QualifiersMix: 0, \ // RUN: bugprone-easily-swappable-parameters.ModelImplicitConversions: 0, \ // RUN: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 1, \ // RUN: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: 0 \ // RUN: }}' -- namespace std { template T max(const T &A, const T &B); } // namespace std bool coin(); void f(int); void g(int); void h(int, int); void i(int, bool); void i(int, char); struct Tmp { int f(int); int g(int, int); }; struct Int { int I; }; void compare(int Left, int Right) {} // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'compare' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-2]]:18: note: the first parameter in the range is 'Left' // CHECK-MESSAGES: :[[@LINE-3]]:28: note: the last parameter in the range is 'Right' int decideSequence(int A, int B) { if (A) return 1; if (B) return 2; return 3; } // CHECK-MESSAGES: :[[@LINE-7]]:20: warning: 2 adjacent parameters of 'decideSequence' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-8]]:24: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-9]]:31: note: the last parameter in the range is 'B' int myMax(int A, int B) { // NO-WARN: Appears in same expression. return A < B ? A : B; } int myMax2(int A, int B) { // NO-WARN: Appears in same expression. if (A < B) return A; return B; } int myMax3(int A, int B) { // NO-WARN: Appears in same expression. return std::max(A, B); } int binaryToUnary(int A, int) { return A; } // CHECK-MESSAGES: :[[@LINE-3]]:19: warning: 2 adjacent parameters of 'binaryToUnary' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-4]]:23: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-5]]:29: note: the last parameter in the range is '' int randomReturn1(int A, int B) { // NO-WARN: Appears in same expression. return coin() ? A : B; } int randomReturn2(int A, int B) { // NO-WARN: Both parameters returned. if (coin()) return A; return B; } int randomReturn3(int A, int B) { // NO-WARN: Both parameters returned. bool Flip = coin(); if (Flip) return A; Flip = coin(); if (Flip) return B; Flip = coin(); if (!Flip) return 0; return -1; } void passthrough1(int A, int B) { // WARN: Different functions, different params. f(A); g(B); } // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough1' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B' void passthrough2(int A, int B) { // NO-WARN: Passed to same index of same function. f(A); f(B); } void passthrough3(int A, int B) { // NO-WARN: Passed to same index of same funtion. h(1, A); h(1, B); } void passthrough4(int A, int B) { // WARN: Different index used. h(1, A); h(B, 2); } // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough4' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B' void passthrough5(int A, int B) { // WARN: Different function overload. i(A, false); i(A, '\0'); } // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough5' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B' void passthrough6(int A, int B) { // NO-WARN: Passed to same index of same function. Tmp Temp; Temp.f(A); Temp.f(B); } void passthrough7(int A, int B) { // NO-WARN: Passed to same index of same function. // Clang-Tidy isn't path sensitive, the fact that the two objects we call the // function on is different is not modelled. Tmp Temp1, Temp2; Temp1.f(A); Temp2.f(B); } void passthrough8(int A, int B) { // WARN: Different functions used. f(A); Tmp{}.f(B); } // CHECK-MESSAGES: :[[@LINE-4]]:19: warning: 2 adjacent parameters of 'passthrough8' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-5]]:23: note: the first parameter in the range is 'A' // CHECK-MESSAGES: :[[@LINE-6]]:30: note: the last parameter in the range is 'B' // Test that the matching of "passed-to-function" is done to the proper node. // Put simply, this test should not crash here. void forwardDeclared(int X); void passthrough9(int A, int B) { // NO-WARN: Passed to same index of same function. forwardDeclared(A); forwardDeclared(B); } void forwardDeclared(int X) {} void passthrough10(int A, int B) { // NO-WARN: Passed to same index of same function. forwardDeclared(A); forwardDeclared(B); } bool compare1(Int I, Int J) { // NO-WARN: Same member accessed. int Val1 = I.I; int Val2 = J.I; return Val1 < Val2; } bool compare2(Tmp T1, Tmp T2) { // NO-WARN: Same member accessed. int Val1 = T1.g(0, 1); int Val2 = T2.g(2, 3); return Val1 < Val2; } bool compare3(Tmp T1, Tmp T2) { // WARN: Different member accessed. int Val1 = T1.f(0); int Val2 = T2.g(1, 2); return Val1 < Val2; } // CHECK-MESSAGES: :[[@LINE-5]]:15: warning: 2 adjacent parameters of 'compare3' of similar type ('Tmp') // CHECK-MESSAGES: :[[@LINE-6]]:19: note: the first parameter in the range is 'T1' // CHECK-MESSAGES: :[[@LINE-7]]:27: note: the last parameter in the range is 'T2' int rangeBreaker(int I, int J, int K, int L, int M, int N) { // (I, J) swappable. if (J == K) // (J, K) related. return -1; if (K + 2 > Tmp{}.f(K)) return M; // (K, L, M) swappable. return N; // (M, N) related. } // CHECK-MESSAGES: :[[@LINE-13]]:18: warning: 2 adjacent parameters of 'rangeBreaker' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-14]]:22: note: the first parameter in the range is 'I' // CHECK-MESSAGES: :[[@LINE-15]]:29: note: the last parameter in the range is 'J' // CHECK-MESSAGES: :[[@LINE-16]]:32: warning: 3 adjacent parameters of 'rangeBreaker' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-17]]:36: note: the first parameter in the range is 'K' // CHECK-MESSAGES: :[[@LINE-18]]:50: note: the last parameter in the range is 'M' int returnsNotOwnParameter(int I, int J, int K) { const auto &Lambda = [&K](int L, int M, int N) { if (K) return L; return M; // (L, M) related. }; if (Lambda(-1, 0, 1)) return I; return J; // (I, J) related. } // CHECK-MESSAGES: :[[@LINE-11]]:35: warning: 2 adjacent parameters of 'returnsNotOwnParameter' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-12]]:39: note: the first parameter in the range is 'J' // CHECK-MESSAGES: :[[@LINE-13]]:46: note: the last parameter in the range is 'K' // CHECK-MESSAGES: :[[@LINE-13]]:36: warning: 2 adjacent parameters of 'operator()' of similar type ('int') // CHECK-MESSAGES: :[[@LINE-14]]:40: note: the first parameter in the range is 'M' // CHECK-MESSAGES: :[[@LINE-15]]:47: note: the last parameter in the range is 'N' int usedTogetherInCapture(int I, int J, int K) { // NO-WARN: Used together. const auto &Lambda = [I, J, K]() { int A = I + 1; int B = J - 2; int C = K * 3; return A + B + C; }; return Lambda(); }