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: "bool;MyBool;struct U;MAKE_LOGICAL_TYPE(int)", \ |
6 | // RUN: bugprone-easily-swappable-parameters.QualifiersMix: 0, \ |
7 | // RUN: bugprone-easily-swappable-parameters.ModelImplicitConversions: 0, \ |
8 | // RUN: bugprone-easily-swappable-parameters.SuppressParametersUsedTogether: 0, \ |
9 | // RUN: bugprone-easily-swappable-parameters.NamePrefixSuffixSilenceDissimilarityTreshold: 0 \ |
10 | // RUN: }}' -- -Wno-strict-prototypes -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. |
22 | void oneParam(int I) {} // NO-WARN: 1 parameter. |
23 | void variadic(int I, ...) {} // NO-WARN: 1 visible parameter. |
24 | |
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 | |
30 | void qualifier(int I, const int CI) {} // NO-WARN: Distinct types. |
31 | |
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 | |
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 | |
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 | |
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(I: IVal); // NO-WARN. |
52 | variadic(I: IVal, 2, 3, 4); // NO-WARN. |
53 | } |
54 | |
55 | struct S {}; |
56 | struct T {}; |
57 | |
58 | void taggedTypes1(struct S SVar, struct T TVar) {} // NO-WARN: Distinct types. |
59 | |
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 | |
65 | void wrappers(struct { int I; } I1, struct { int I; } I2) {} // NO-WARN: Distinct anonymous types. |
66 | |
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 | |
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 | |
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 | |
87 | void typedefdBoolAsWritten(MyBool MB1, MyBool MB2) {} // NO-WARN: "MyBool" as written type name ignored. |
88 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
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 | |
152 | void macroMagic4(MAKE_LOGICAL_TYPE(int) B1, MAKE_LOGICAL_TYPE(int) B2) {} // NO-WARN: "Type name" ignored. |
153 | |