xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/bugprone/easily-swappable-parameters.c (revision e8a3ddafe063c970df9c23e803812369abde4c82)
189a1d03eSRichard // RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \
2*e8a3ddafSNathan James // RUN:   -config='{CheckOptions: { \
3*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.MinimumLength: 2, \
4*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.IgnoredParameterNames: "", \
5*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes: "bool;MyBool;struct U;MAKE_LOGICAL_TYPE(int)", \
6*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.QualifiersMix: 0, \
7*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.ModelImplicitConversions: 0, \
8*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 0, \
9*e8a3ddafSNathan James // RUN:     bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: 0 \
10*e8a3ddafSNathan James // RUN:  }}' -- -Wno-strict-prototypes -x c
1189a1d03eSRichard 
1289a1d03eSRichard #define bool _Bool
1389a1d03eSRichard #define true 1
1489a1d03eSRichard #define false 0
1589a1d03eSRichard 
1689a1d03eSRichard typedef bool MyBool;
1789a1d03eSRichard 
1889a1d03eSRichard #define TheLogicalType bool
1989a1d03eSRichard 
2089a1d03eSRichard void declVoid(void);         // NO-WARN: Declaration only.
2189a1d03eSRichard void decl();                 // NO-WARN: Declaration only.
oneParam(int I)2289a1d03eSRichard void oneParam(int I) {}      // NO-WARN: 1 parameter.
variadic(int I,...)2389a1d03eSRichard void variadic(int I, ...) {} // NO-WARN: 1 visible parameter.
2489a1d03eSRichard 
trivial(int I,int J)2589a1d03eSRichard void trivial(int I, int J) {}
2689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'trivial' of similar type ('int') are easily swapped by mistake [bugprone-easily-swappable-parameters]
2789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:18: note: the first parameter in the range is 'I'
2889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:25: note: the last parameter in the range is 'J'
2989a1d03eSRichard 
qualifier(int I,const int CI)3089a1d03eSRichard void qualifier(int I, const int CI) {} // NO-WARN: Distinct types.
3189a1d03eSRichard 
restrictQualifier(char * restrict CPR1,char * restrict CPR2)3289a1d03eSRichard void restrictQualifier(char *restrict CPR1, char *restrict CPR2) {}
3389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 2 adjacent parameters of 'restrictQualifier' of similar type ('char *restrict')
3489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:39: note: the first parameter in the range is 'CPR1'
3589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:60: note: the last parameter in the range is 'CPR2'
3689a1d03eSRichard 
pointer1(int * IP1,int * IP2)3789a1d03eSRichard void pointer1(int *IP1, int *IP2) {}
3889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 2 adjacent parameters of 'pointer1' of similar type ('int *')
3989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:20: note: the first parameter in the range is 'IP1'
4089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:30: note: the last parameter in the range is 'IP2'
4189a1d03eSRichard 
pointerConversion(int * IP,long * LP)4289a1d03eSRichard void pointerConversion(int *IP, long *LP) {}
4389a1d03eSRichard // NO-WARN: Even though C can convert any T* to U* back and forth, compiler
4489a1d03eSRichard // warnings already exist for this.
4589a1d03eSRichard 
testVariadicsCall()4689a1d03eSRichard void testVariadicsCall() {
4789a1d03eSRichard   int IVal = 1;
4889a1d03eSRichard   decl(IVal); // NO-WARN: Particular calls to "variadics" are like template
4989a1d03eSRichard               // instantiations, and we do not model them.
5089a1d03eSRichard 
5189a1d03eSRichard   variadic(IVal);          // NO-WARN.
5289a1d03eSRichard   variadic(IVal, 2, 3, 4); // NO-WARN.
5389a1d03eSRichard }
5489a1d03eSRichard 
5589a1d03eSRichard struct S {};
5689a1d03eSRichard struct T {};
5789a1d03eSRichard 
taggedTypes1(struct S SVar,struct T TVar)5889a1d03eSRichard void taggedTypes1(struct S SVar, struct T TVar) {} // NO-WARN: Distinct types.
5989a1d03eSRichard 
taggedTypes2(struct S SVar1,struct S SVar2)6089a1d03eSRichard void taggedTypes2(struct S SVar1, struct S SVar2) {}
6189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'taggedTypes2' of similar type ('struct S')
6289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:28: note: the first parameter in the range is 'SVar1'
6389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:44: note: the last parameter in the range is 'SVar2'
6489a1d03eSRichard 
wrappers(struct{ int I; } I1,struct{ int I; } I2)6589a1d03eSRichard void wrappers(struct { int I; } I1, struct { int I; } I2) {} // NO-WARN: Distinct anonymous types.
6689a1d03eSRichard 
knr(I,J)6789a1d03eSRichard void knr(I, J)
6889a1d03eSRichard   int I;
6989a1d03eSRichard   int J;
7089a1d03eSRichard {}
7189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 2 adjacent parameters of 'knr' of similar type ('int')
7289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:7: note: the first parameter in the range is 'I'
7389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:7: note: the last parameter in the range is 'J'
7489a1d03eSRichard 
boolAsWritten(bool B1,bool B2)7589a1d03eSRichard void boolAsWritten(bool B1, bool B2) {} // NO-WARN: The type name is ignored.
7689a1d03eSRichard // Note that "bool" is a macro that expands to "_Bool" internally, but it is
7789a1d03eSRichard // only "bool" that is ignored from the two.
7889a1d03eSRichard 
underscoreBoolAsWritten(_Bool B1,_Bool B2)7989a1d03eSRichard void underscoreBoolAsWritten(_Bool B1, _Bool B2) {}
8089a1d03eSRichard // Even though it is "_Bool" that is written in the code, the diagnostic message
8189a1d03eSRichard // respects the printing policy as defined by the compilation commands. Clang's
8289a1d03eSRichard // default in C mode seems to say that the type itself is "bool", not "_Bool".
8389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:30: warning: 2 adjacent parameters of 'underscoreBoolAsWritten' of similar type ('bool')
8489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:36: note: the first parameter in the range is 'B1'
8589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:46: note: the last parameter in the range is 'B2'
8689a1d03eSRichard 
typedefdBoolAsWritten(MyBool MB1,MyBool MB2)8789a1d03eSRichard void typedefdBoolAsWritten(MyBool MB1, MyBool MB2) {} // NO-WARN: "MyBool" as written type name ignored.
8889a1d03eSRichard 
otherBoolMacroAsWritten(TheLogicalType TLT1,TheLogicalType TLT2)8989a1d03eSRichard void otherBoolMacroAsWritten(TheLogicalType TLT1, TheLogicalType TLT2) {}
9089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 2 adjacent parameters of 'otherBoolMacroAsWritten' of similar type ('bool')
9189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:45: note: the first parameter in the range is 'TLT1'
9289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:66: note: the last parameter in the range is 'TLT2'
9389a1d03eSRichard 
9489a1d03eSRichard struct U {};
9589a1d03eSRichard typedef struct U U;
9689a1d03eSRichard 
typedefStruct(U X,U Y)9789a1d03eSRichard void typedefStruct(U X, U Y) {}
9889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 2 adjacent parameters of 'typedefStruct' of similar type ('U')
9989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'X'
10089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:27: note: the last parameter in the range is 'Y'
10189a1d03eSRichard 
ignoredStructU(struct U X,struct U Y)10289a1d03eSRichard void ignoredStructU(struct U X, struct U Y) {} // NO-WARN: "struct U" ignored.
10389a1d03eSRichard 
10489a1d03eSRichard #define TYPE_TAG_TO_USE struct // We are in C!
10589a1d03eSRichard #define MAKE_TYPE_NAME(T) TYPE_TAG_TO_USE T
10689a1d03eSRichard 
macroMagic1(TYPE_TAG_TO_USE T X,TYPE_TAG_TO_USE T Y)10789a1d03eSRichard void macroMagic1(TYPE_TAG_TO_USE T X, TYPE_TAG_TO_USE T Y) {}
10889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 2 adjacent parameters of 'macroMagic1' of similar type ('struct T')
10989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
11089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-3]]:36: note: the first parameter in the range is 'X'
11189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:57: note: the last parameter in the range is 'Y'
11289a1d03eSRichard 
macroMagic2(TYPE_TAG_TO_USE U X,TYPE_TAG_TO_USE U Y)11389a1d03eSRichard void macroMagic2(TYPE_TAG_TO_USE U X, TYPE_TAG_TO_USE U Y) {}
11489a1d03eSRichard // "struct U" is ignored, but that is not what is written here!
11589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: 2 adjacent parameters of 'macroMagic2' of similar type ('struct U')
11689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-12]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
11789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:36: note: the first parameter in the range is 'X'
11889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:57: note: the last parameter in the range is 'Y'
11989a1d03eSRichard 
evenMoreMacroMagic1(MAKE_TYPE_NAME (T)X,MAKE_TYPE_NAME (T)Y)12089a1d03eSRichard void evenMoreMacroMagic1(MAKE_TYPE_NAME(T) X, MAKE_TYPE_NAME(T) Y) {}
12189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 2 adjacent parameters of 'evenMoreMacroMagic1' of similar type ('struct T')
12289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-17]]:27: note: expanded from macro 'MAKE_TYPE_NAME'
12389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-19]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
12489a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:44: note: the first parameter in the range is 'X'
12589a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:65: note: the last parameter in the range is 'Y'
12689a1d03eSRichard 
evenMoreMacroMagic2(MAKE_TYPE_NAME (U)X,MAKE_TYPE_NAME (U)Y)12789a1d03eSRichard void evenMoreMacroMagic2(MAKE_TYPE_NAME(U) X, MAKE_TYPE_NAME(U) Y) {}
12889a1d03eSRichard // "struct U" is ignored, but that is not what is written here!
12989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 2 adjacent parameters of 'evenMoreMacroMagic2' of similar type ('struct U')
13089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-25]]:27: note: expanded from macro 'MAKE_TYPE_NAME'
13189a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-27]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
13289a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:44: note: the first parameter in the range is 'X'
13389a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-6]]:65: note: the last parameter in the range is 'Y'
13489a1d03eSRichard 
13589a1d03eSRichard #define MAKE_PRIMITIVE_WRAPPER(WRAPPED_TYPE) \
13689a1d03eSRichard   MAKE_TYPE_NAME() {                         \
13789a1d03eSRichard     WRAPPED_TYPE Member;                     \
13889a1d03eSRichard   }
13989a1d03eSRichard 
thisIsGettingRidiculous(MAKE_PRIMITIVE_WRAPPER (int)I1,MAKE_PRIMITIVE_WRAPPER (int)I2)14089a1d03eSRichard void thisIsGettingRidiculous(MAKE_PRIMITIVE_WRAPPER(int) I1,
14189a1d03eSRichard                              MAKE_PRIMITIVE_WRAPPER(int) I2) {} // NO-WARN: Distinct anonymous types.
14289a1d03eSRichard 
14389a1d03eSRichard #define MAKE_LOGICAL_TYPE(X) bool
14489a1d03eSRichard 
macroMagic3(MAKE_LOGICAL_TYPE (char)B1,MAKE_LOGICAL_TYPE (long)B2)14589a1d03eSRichard void macroMagic3(MAKE_LOGICAL_TYPE(char) B1, MAKE_LOGICAL_TYPE(long) B2) {}
14689a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 2 adjacent parameters of 'macroMagic3' of similar type ('bool')
14789a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:30: note: expanded from macro 'MAKE_LOGICAL_TYPE'
14889a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-136]]:14: note: expanded from macro 'bool'
14989a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-4]]:42: note: the first parameter in the range is 'B1'
15089a1d03eSRichard // CHECK-MESSAGES: :[[@LINE-5]]:70: note: the last parameter in the range is 'B2'
15189a1d03eSRichard 
macroMagic4(MAKE_LOGICAL_TYPE (int)B1,MAKE_LOGICAL_TYPE (int)B2)15289a1d03eSRichard void macroMagic4(MAKE_LOGICAL_TYPE(int) B1, MAKE_LOGICAL_TYPE(int) B2) {} // NO-WARN: "Type name" ignored.
153