1 // RUN: %check_clang_tidy %s bugprone-easily-swappable-parameters %t \
2 // RUN:   -config='{CheckOptions: [ \
3 // RUN:     {key: bugprone-easily-swappable-parameters.MinimumLength, value: 2}, \
4 // RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterNames, value: ""}, \
5 // RUN:     {key: bugprone-easily-swappable-parameters.IgnoredParameterTypeSuffixes, value: "bool;MyBool;struct U;MAKE_LOGICAL_TYPE(int)"}, \
6 // RUN:     {key: bugprone-easily-swappable-parameters.QualifiersMix, value: 0}, \
7 // RUN:     {key: bugprone-easily-swappable-parameters.ModelImplicitConversions, value: 0}, \
8 // RUN:     {key: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether, value: 0}, \
9 // RUN:     {key: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold, value: 0} \
10 // RUN:  ]}' -- -x c
11 
12 #define bool _Bool
13 #define true 1
14 #define false 0
15 
16 typedef bool MyBool;
17 
18 #define TheLogicalType bool
19 
20 void declVoid(void);         // NO-WARN: Declaration only.
21 void decl();                 // NO-WARN: Declaration only.
oneParam(int I)22 void oneParam(int I) {}      // NO-WARN: 1 parameter.
variadic(int I,...)23 void variadic(int I, ...) {} // NO-WARN: 1 visible parameter.
24 
trivial(int I,int J)25 void trivial(int I, int J) {}
26 // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: 2 adjacent parameters of 'trivial' of similar type ('int') are easily swapped by mistake [bugprone-easily-swappable-parameters]
27 // CHECK-MESSAGES: :[[@LINE-2]]:18: note: the first parameter in the range is 'I'
28 // CHECK-MESSAGES: :[[@LINE-3]]:25: note: the last parameter in the range is 'J'
29 
qualifier(int I,const int CI)30 void qualifier(int I, const int CI) {} // NO-WARN: Distinct types.
31 
restrictQualifier(char * restrict CPR1,char * restrict CPR2)32 void restrictQualifier(char *restrict CPR1, char *restrict CPR2) {}
33 // CHECK-MESSAGES: :[[@LINE-1]]:24: warning: 2 adjacent parameters of 'restrictQualifier' of similar type ('char *restrict')
34 // CHECK-MESSAGES: :[[@LINE-2]]:39: note: the first parameter in the range is 'CPR1'
35 // CHECK-MESSAGES: :[[@LINE-3]]:60: note: the last parameter in the range is 'CPR2'
36 
pointer1(int * IP1,int * IP2)37 void pointer1(int *IP1, int *IP2) {}
38 // CHECK-MESSAGES: :[[@LINE-1]]:15: warning: 2 adjacent parameters of 'pointer1' of similar type ('int *')
39 // CHECK-MESSAGES: :[[@LINE-2]]:20: note: the first parameter in the range is 'IP1'
40 // CHECK-MESSAGES: :[[@LINE-3]]:30: note: the last parameter in the range is 'IP2'
41 
pointerConversion(int * IP,long * LP)42 void pointerConversion(int *IP, long *LP) {}
43 // NO-WARN: Even though C can convert any T* to U* back and forth, compiler
44 // warnings already exist for this.
45 
testVariadicsCall()46 void testVariadicsCall() {
47   int IVal = 1;
48   decl(IVal); // NO-WARN: Particular calls to "variadics" are like template
49               // instantiations, and we do not model them.
50 
51   variadic(IVal);          // NO-WARN.
52   variadic(IVal, 2, 3, 4); // NO-WARN.
53 }
54 
55 struct S {};
56 struct T {};
57 
taggedTypes1(struct S SVar,struct T TVar)58 void taggedTypes1(struct S SVar, struct T TVar) {} // NO-WARN: Distinct types.
59 
taggedTypes2(struct S SVar1,struct S SVar2)60 void taggedTypes2(struct S SVar1, struct S SVar2) {}
61 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: 2 adjacent parameters of 'taggedTypes2' of similar type ('struct S')
62 // CHECK-MESSAGES: :[[@LINE-2]]:28: note: the first parameter in the range is 'SVar1'
63 // CHECK-MESSAGES: :[[@LINE-3]]:44: note: the last parameter in the range is 'SVar2'
64 
wrappers(struct{ int I; } I1,struct{ int I; } I2)65 void wrappers(struct { int I; } I1, struct { int I; } I2) {} // NO-WARN: Distinct anonymous types.
66 
knr(I,J)67 void knr(I, J)
68   int I;
69   int J;
70 {}
71 // CHECK-MESSAGES: :[[@LINE-3]]:3: warning: 2 adjacent parameters of 'knr' of similar type ('int')
72 // CHECK-MESSAGES: :[[@LINE-4]]:7: note: the first parameter in the range is 'I'
73 // CHECK-MESSAGES: :[[@LINE-4]]:7: note: the last parameter in the range is 'J'
74 
boolAsWritten(bool B1,bool B2)75 void boolAsWritten(bool B1, bool B2) {} // NO-WARN: The type name is ignored.
76 // Note that "bool" is a macro that expands to "_Bool" internally, but it is
77 // only "bool" that is ignored from the two.
78 
underscoreBoolAsWritten(_Bool B1,_Bool B2)79 void underscoreBoolAsWritten(_Bool B1, _Bool B2) {}
80 // Even though it is "_Bool" that is written in the code, the diagnostic message
81 // respects the printing policy as defined by the compilation commands. Clang's
82 // default in C mode seems to say that the type itself is "bool", not "_Bool".
83 // CHECK-MESSAGES: :[[@LINE-4]]:30: warning: 2 adjacent parameters of 'underscoreBoolAsWritten' of similar type ('bool')
84 // CHECK-MESSAGES: :[[@LINE-5]]:36: note: the first parameter in the range is 'B1'
85 // CHECK-MESSAGES: :[[@LINE-6]]:46: note: the last parameter in the range is 'B2'
86 
typedefdBoolAsWritten(MyBool MB1,MyBool MB2)87 void typedefdBoolAsWritten(MyBool MB1, MyBool MB2) {} // NO-WARN: "MyBool" as written type name ignored.
88 
otherBoolMacroAsWritten(TheLogicalType TLT1,TheLogicalType TLT2)89 void otherBoolMacroAsWritten(TheLogicalType TLT1, TheLogicalType TLT2) {}
90 // CHECK-MESSAGES: :[[@LINE-1]]:30: warning: 2 adjacent parameters of 'otherBoolMacroAsWritten' of similar type ('bool')
91 // CHECK-MESSAGES: :[[@LINE-2]]:45: note: the first parameter in the range is 'TLT1'
92 // CHECK-MESSAGES: :[[@LINE-3]]:66: note: the last parameter in the range is 'TLT2'
93 
94 struct U {};
95 typedef struct U U;
96 
typedefStruct(U X,U Y)97 void typedefStruct(U X, U Y) {}
98 // CHECK-MESSAGES: :[[@LINE-1]]:20: warning: 2 adjacent parameters of 'typedefStruct' of similar type ('U')
99 // CHECK-MESSAGES: :[[@LINE-2]]:22: note: the first parameter in the range is 'X'
100 // CHECK-MESSAGES: :[[@LINE-3]]:27: note: the last parameter in the range is 'Y'
101 
ignoredStructU(struct U X,struct U Y)102 void ignoredStructU(struct U X, struct U Y) {} // NO-WARN: "struct U" ignored.
103 
104 #define TYPE_TAG_TO_USE struct // We are in C!
105 #define MAKE_TYPE_NAME(T) TYPE_TAG_TO_USE T
106 
macroMagic1(TYPE_TAG_TO_USE T X,TYPE_TAG_TO_USE T Y)107 void macroMagic1(TYPE_TAG_TO_USE T X, TYPE_TAG_TO_USE T Y) {}
108 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 2 adjacent parameters of 'macroMagic1' of similar type ('struct T')
109 // CHECK-MESSAGES: :[[@LINE-5]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
110 // CHECK-MESSAGES: :[[@LINE-3]]:36: note: the first parameter in the range is 'X'
111 // CHECK-MESSAGES: :[[@LINE-4]]:57: note: the last parameter in the range is 'Y'
112 
macroMagic2(TYPE_TAG_TO_USE U X,TYPE_TAG_TO_USE U Y)113 void macroMagic2(TYPE_TAG_TO_USE U X, TYPE_TAG_TO_USE U Y) {}
114 // "struct U" is ignored, but that is not what is written here!
115 // CHECK-MESSAGES: :[[@LINE-2]]:18: warning: 2 adjacent parameters of 'macroMagic2' of similar type ('struct U')
116 // CHECK-MESSAGES: :[[@LINE-12]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
117 // CHECK-MESSAGES: :[[@LINE-4]]:36: note: the first parameter in the range is 'X'
118 // CHECK-MESSAGES: :[[@LINE-5]]:57: note: the last parameter in the range is 'Y'
119 
evenMoreMacroMagic1(MAKE_TYPE_NAME (T)X,MAKE_TYPE_NAME (T)Y)120 void evenMoreMacroMagic1(MAKE_TYPE_NAME(T) X, MAKE_TYPE_NAME(T) Y) {}
121 // CHECK-MESSAGES: :[[@LINE-1]]:26: warning: 2 adjacent parameters of 'evenMoreMacroMagic1' of similar type ('struct T')
122 // CHECK-MESSAGES: :[[@LINE-17]]:27: note: expanded from macro 'MAKE_TYPE_NAME'
123 // CHECK-MESSAGES: :[[@LINE-19]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
124 // CHECK-MESSAGES: :[[@LINE-4]]:44: note: the first parameter in the range is 'X'
125 // CHECK-MESSAGES: :[[@LINE-5]]:65: note: the last parameter in the range is 'Y'
126 
evenMoreMacroMagic2(MAKE_TYPE_NAME (U)X,MAKE_TYPE_NAME (U)Y)127 void evenMoreMacroMagic2(MAKE_TYPE_NAME(U) X, MAKE_TYPE_NAME(U) Y) {}
128 // "struct U" is ignored, but that is not what is written here!
129 // CHECK-MESSAGES: :[[@LINE-2]]:26: warning: 2 adjacent parameters of 'evenMoreMacroMagic2' of similar type ('struct U')
130 // CHECK-MESSAGES: :[[@LINE-25]]:27: note: expanded from macro 'MAKE_TYPE_NAME'
131 // CHECK-MESSAGES: :[[@LINE-27]]:25: note: expanded from macro 'TYPE_TAG_TO_USE'
132 // CHECK-MESSAGES: :[[@LINE-5]]:44: note: the first parameter in the range is 'X'
133 // CHECK-MESSAGES: :[[@LINE-6]]:65: note: the last parameter in the range is 'Y'
134 
135 #define MAKE_PRIMITIVE_WRAPPER(WRAPPED_TYPE) \
136   MAKE_TYPE_NAME() {                         \
137     WRAPPED_TYPE Member;                     \
138   }
139 
thisIsGettingRidiculous(MAKE_PRIMITIVE_WRAPPER (int)I1,MAKE_PRIMITIVE_WRAPPER (int)I2)140 void thisIsGettingRidiculous(MAKE_PRIMITIVE_WRAPPER(int) I1,
141                              MAKE_PRIMITIVE_WRAPPER(int) I2) {} // NO-WARN: Distinct anonymous types.
142 
143 #define MAKE_LOGICAL_TYPE(X) bool
144 
macroMagic3(MAKE_LOGICAL_TYPE (char)B1,MAKE_LOGICAL_TYPE (long)B2)145 void macroMagic3(MAKE_LOGICAL_TYPE(char) B1, MAKE_LOGICAL_TYPE(long) B2) {}
146 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: 2 adjacent parameters of 'macroMagic3' of similar type ('bool')
147 // CHECK-MESSAGES: :[[@LINE-4]]:30: note: expanded from macro 'MAKE_LOGICAL_TYPE'
148 // CHECK-MESSAGES: :[[@LINE-136]]:14: note: expanded from macro 'bool'
149 // CHECK-MESSAGES: :[[@LINE-4]]:42: note: the first parameter in the range is 'B1'
150 // CHECK-MESSAGES: :[[@LINE-5]]:70: note: the last parameter in the range is 'B2'
151 
macroMagic4(MAKE_LOGICAL_TYPE (int)B1,MAKE_LOGICAL_TYPE (int)B2)152 void macroMagic4(MAKE_LOGICAL_TYPE(int) B1, MAKE_LOGICAL_TYPE(int) B2) {} // NO-WARN: "Type name" ignored.
153