2019-12-18 01:00:08 +08:00
/ / RUN : % check_clang_tidy % s bugprone - easily - swappable - parameters % t \
/ / RUN : - config = ' { CheckOptions : [ \
/ / RUN : { key : bugprone - easily - swappable - parameters . MinimumLength , value : 2 } , \
/ / RUN : { key : bugprone - easily - swappable - parameters . IgnoredParameterNames , value : " " } , \
/ / RUN : { key : bugprone - easily - swappable - parameters . IgnoredParameterTypeSuffixes , value : " " } , \
/ / RUN : { key : bugprone - easily - swappable - parameters . QualifiersMix , value : 0 } , \
2020-04-08 22:33:15 +08:00
/ / RUN : { key : bugprone - easily - swappable - parameters . ModelImplicitConversions , value : 1 } , \
[clang-tidy] Suppress reports to patternedly named parameters in 'bugprone-easily-swappable-parameters'
While the original check's purpose is to identify potentially dangerous
functions based on the parameter types (as identifier names do not mean
anything when it comes to the language rules), unfortunately, such a plain
interface check rule can be incredibly noisy. While the previous
"filtering heuristic" is able to find many similar usages, there is an entire
class of parameters that should not be warned about very easily mixed by that
check: parameters that have a name and their name follows a pattern,
e.g. `text1, text2, text3, ...`.`
This patch implements a simple, but powerful rule, that allows us to detect
such cases and ensure that no warnings are emitted for parameter sequences that
follow a pattern, even if their types allow for them to be potentially mixed at a call site.
Given a threshold `k`, warnings about two parameters are filtered from the
result set if the names of the parameters are either prefixes or suffixes of
each other, with at most k letters difference on the non-common end.
(Assuming that the names themselves are at least `k` long.)
- The above `text1, text2` is an example of this. (Live finding from Xerces.)
- `LHS` and `RHS` are also fitting the bill here. (Live finding from... virtually any project.)
- So does `Qmat, Tmat, Rmat`. (Live finding from I think OpenCV.)
Reviewed By: aaron.ballman
Differential Revision: http://reviews.llvm.org/D97297
2021-01-13 00:03:42 +08:00
/ / RUN : { key : bugprone - easily - swappable - parameters . SuppressParametersUsedTogether , value : 0 } , \
/ / RUN : { key : bugprone - easily - swappable - parameters . NamePrefixSuffixSilenceDissimilarityTreshold , value : 0 } \
2019-12-18 01:00:08 +08:00
// RUN: ]}' --
void implicitDoesntBreakOtherStuff ( int A , int B ) { }
// CHECK-MESSAGES: :[[@LINE-1]]:36: warning: 2 adjacent parameters of 'implicitDoesntBreakOtherStuff' of similar type ('int') are easily swapped by mistake [bugprone-easily-swappable-parameters]
// CHECK-MESSAGES: :[[@LINE-2]]:40: note: the first parameter in the range is 'A'
// CHECK-MESSAGES: :[[@LINE-3]]:47: note: the last parameter in the range is 'B'
void arrayAndPtr1 ( int * IP , int IA [ ] ) { arrayAndPtr1 ( IA , IP ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'arrayAndPtr1' of similar type ('int *')
// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'IP'
// CHECK-MESSAGES: :[[@LINE-3]]:32: note: the last parameter in the range is 'IA'
void arrayAndPtr2 ( int * IP , int IA [ 8 ] ) { arrayAndPtr2 ( IA , IP ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'arrayAndPtr2' of similar type ('int *')
// CHECK-MESSAGES: :[[@LINE-2]]:24: note: the first parameter in the range is 'IP'
// CHECK-MESSAGES: :[[@LINE-3]]:32: note: the last parameter in the range is 'IA'
void arrayAndElement ( int I , int IA [ ] ) { } // NO-WARN.
void numericConversion1 ( int I , double D ) { numericConversion1 ( D , I ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion1' of convertible types are easily swapped by mistake [bugprone-easily-swappable-parameters]
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:39: note: the last parameter in the range is 'D'
// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'double' may be implicitly converted{{$}}
void numericConversion2 ( int I , short S ) { numericConversion2 ( S , I ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion2' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:38: note: the last parameter in the range is 'S'
// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'short' may be implicitly converted{{$}}
void numericConversion3 ( float F , unsigned long UL ) { numericConversion3 ( UL , F ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion3' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:31: note: the first parameter in the range is 'F'
// CHECK-MESSAGES: :[[@LINE-3]]:48: note: the last parameter in the range is 'UL'
// CHECK-MESSAGES: :[[@LINE-4]]:34: note: 'float' and 'unsigned long' may be implicitly converted{{$}}
enum Unscoped { U_A ,
U_B } ;
enum UnscopedFixed : char { UF_A ,
UF_B } ;
void numericConversion4 ( int I , enum Unscoped U ) { numericConversion4 ( U , I ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion4' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:46: note: the last parameter in the range is 'U'
// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'enum Unscoped' may be implicitly converted{{$}}
void numericConversion5 ( int I , enum UnscopedFixed UF ) { numericConversion5 ( UF , I ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion5' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:29: note: the first parameter in the range is 'I'
// CHECK-MESSAGES: :[[@LINE-3]]:51: note: the last parameter in the range is 'UF'
// CHECK-MESSAGES: :[[@LINE-4]]:32: note: 'int' and 'enum UnscopedFixed' may be implicitly converted{{$}}
void numericConversion7 ( double D , enum Unscoped U ) { numericConversion7 ( U , D ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion7' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'D'
// CHECK-MESSAGES: :[[@LINE-3]]:49: note: the last parameter in the range is 'U'
// CHECK-MESSAGES: :[[@LINE-4]]:35: note: 'double' and 'enum Unscoped' may be implicitly converted{{$}}
void numericConversion8 ( double D , enum UnscopedFixed UF ) { numericConversion8 ( UF , D ) ; }
// CHECK-MESSAGES: :[[@LINE-1]]:25: warning: 2 adjacent parameters of 'numericConversion8' of convertible types
// CHECK-MESSAGES: :[[@LINE-2]]:32: note: the first parameter in the range is 'D'
// CHECK-MESSAGES: :[[@LINE-3]]:54: note: the last parameter in the range is 'UF'
// CHECK-MESSAGES: :[[@LINE-4]]:35: note: 'double' and 'enum UnscopedFixed' may be implicitly converted{{$}}
void pointeeConverison ( int * IP , double * DP ) { pointeeConversion ( DP , IP ) ; }
// NO-WARN: Even though this is possible in C, a swap is diagnosed by the compiler.