1 | // RUN: %check_clang_tidy --match-partial-fixes %s bugprone-suspicious-string-compare %t -- \ |
2 | // RUN: -config='{CheckOptions: \ |
3 | // RUN: {bugprone-suspicious-string-compare.WarnOnImplicitComparison: true, \ |
4 | // RUN: bugprone-suspicious-string-compare.WarnOnLogicalNotComparison: true}}' \ |
5 | // RUN: -- |
6 | |
7 | typedef __SIZE_TYPE__ size; |
8 | |
9 | struct locale_t { |
10 | void* dummy; |
11 | } locale; |
12 | |
13 | static const char A[] = "abc" ; |
14 | static const unsigned char U[] = "abc" ; |
15 | static const unsigned char V[] = "xyz" ; |
16 | static const wchar_t W[] = L"abc" ; |
17 | |
18 | int strlen(const char *); |
19 | |
20 | int memcmp(const void *, const void *, size); |
21 | int wmemcmp(const wchar_t *, const wchar_t *, size); |
22 | int memicmp(const void *, const void *, size); |
23 | int _memicmp(const void *, const void *, size); |
24 | int _memicmp_l(const void *, const void *, size, locale_t); |
25 | |
26 | int strcmp(const char *, const char *); |
27 | int strncmp(const char *, const char *, size); |
28 | int strcasecmp(const char *, const char *); |
29 | int strncasecmp(const char *, const char *, size); |
30 | int stricmp(const char *, const char *); |
31 | int strcmpi(const char *, const char *); |
32 | int strnicmp(const char *, const char *, size); |
33 | int _stricmp(const char *, const char * ); |
34 | int _strnicmp(const char *, const char *, size); |
35 | int _stricmp_l(const char *, const char *, locale_t); |
36 | int _strnicmp_l(const char *, const char *, size, locale_t); |
37 | |
38 | int wcscmp(const wchar_t *, const wchar_t *); |
39 | int wcsncmp(const wchar_t *, const wchar_t *, size); |
40 | int wcscasecmp(const wchar_t *, const wchar_t *); |
41 | int wcsicmp(const wchar_t *, const wchar_t *); |
42 | int wcsnicmp(const wchar_t *, const wchar_t *, size); |
43 | int _wcsicmp(const wchar_t *, const wchar_t *); |
44 | int _wcsnicmp(const wchar_t *, const wchar_t *, size); |
45 | int _wcsicmp_l(const wchar_t *, const wchar_t *, locale_t); |
46 | int _wcsnicmp_l(const wchar_t *, const wchar_t *, size, locale_t); |
47 | |
48 | int _mbscmp(const unsigned char *, const unsigned char *); |
49 | int _mbsncmp(const unsigned char *, const unsigned char *, size); |
50 | int _mbsnbcmp(const unsigned char *, const unsigned char *, size); |
51 | int _mbsnbicmp(const unsigned char *, const unsigned char *, size); |
52 | int _mbsicmp(const unsigned char *, const unsigned char *); |
53 | int _mbsnicmp(const unsigned char *, const unsigned char *, size); |
54 | int _mbscmp_l(const unsigned char *, const unsigned char *, locale_t); |
55 | int _mbsncmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
56 | int _mbsicmp_l(const unsigned char *, const unsigned char *, locale_t); |
57 | int _mbsnicmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
58 | int _mbsnbcmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
59 | int _mbsnbicmp_l(const unsigned char *, const unsigned char *, size, locale_t); |
60 | |
61 | int test_warning_patterns() { |
62 | if (strcmp(A, "a" )) |
63 | return 0; |
64 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result [bugprone-suspicious-string-compare] |
65 | // CHECK-FIXES: if (strcmp(A, "a") != 0) |
66 | |
67 | if (strcmp(A, "a" ) == 0 || |
68 | strcmp(A, "b" )) |
69 | return 0; |
70 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
71 | // CHECK-FIXES: strcmp(A, "b") != 0) |
72 | |
73 | if (strcmp(A, "a" ) == 1) |
74 | return 0; |
75 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
76 | |
77 | if (strcmp(A, "a" ) == -1) |
78 | return 0; |
79 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
80 | |
81 | if (strcmp(A, "a" ) == true) |
82 | return 0; |
83 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
84 | |
85 | if (strcmp(A, "a" ) < '0') |
86 | return 0; |
87 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
88 | |
89 | if (strcmp(A, "a" ) < 0.) |
90 | return 0; |
91 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast |
92 | |
93 | return 1; |
94 | } |
95 | |
96 | int test_valid_patterns() { |
97 | // The following cases are valid. |
98 | if (strcmp(A, "a" ) < 0) |
99 | return 0; |
100 | if (strcmp(A, "a" ) == 0) |
101 | return 0; |
102 | if (strcmp(A, "a" ) <= 0) |
103 | return 0; |
104 | |
105 | if (wcscmp(W, L"a" ) < 0) |
106 | return 0; |
107 | if (wcscmp(W, L"a" ) == 0) |
108 | return 0; |
109 | if (wcscmp(W, L"a" ) <= 0) |
110 | return 0; |
111 | |
112 | return 1; |
113 | } |
114 | |
115 | int test_implicit_compare_with_functions() { |
116 | |
117 | if (memcmp(A, "a" , 1)) |
118 | return 0; |
119 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memcmp' is called without explicitly comparing result |
120 | // CHECK-FIXES: memcmp(A, "a", 1) != 0) |
121 | |
122 | if (wmemcmp(W, L"a" , 1)) |
123 | return 0; |
124 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wmemcmp' is called without explicitly comparing result |
125 | // CHECK-FIXES: wmemcmp(W, L"a", 1) != 0) |
126 | |
127 | if (memicmp(A, "a" , 1)) |
128 | return 0; |
129 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'memicmp' is called without explicitly comparing result |
130 | // CHECK-FIXES: memicmp(A, "a", 1) != 0) |
131 | |
132 | if (_memicmp(A, "a" , 1)) |
133 | return 0; |
134 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp' is called without explicitly comparing result |
135 | // CHECK-FIXES: _memicmp(A, "a", 1) != 0) |
136 | |
137 | if (_memicmp_l(A, "a" , 1, locale)) |
138 | return 0; |
139 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_memicmp_l' is called without explicitly comparing result |
140 | // CHECK-FIXES: _memicmp_l(A, "a", 1, locale) != 0) |
141 | |
142 | if (strcmp(A, "a" )) |
143 | return 0; |
144 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
145 | // CHECK-FIXES: strcmp(A, "a") != 0) |
146 | |
147 | if (strncmp(A, "a" , 1)) |
148 | return 0; |
149 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncmp' is called without explicitly comparing result |
150 | // CHECK-FIXES: strncmp(A, "a", 1) != 0) |
151 | |
152 | if (strcasecmp(A, "a" )) |
153 | return 0; |
154 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcasecmp' is called without explicitly comparing result |
155 | // CHECK-FIXES: strcasecmp(A, "a") != 0) |
156 | |
157 | if (strncasecmp(A, "a" , 1)) |
158 | return 0; |
159 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strncasecmp' is called without explicitly comparing result |
160 | // CHECK-FIXES: strncasecmp(A, "a", 1) != 0) |
161 | |
162 | if (stricmp(A, "a" )) |
163 | return 0; |
164 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'stricmp' is called without explicitly comparing result |
165 | // CHECK-FIXES: stricmp(A, "a") != 0) |
166 | |
167 | if (strcmpi(A, "a" )) |
168 | return 0; |
169 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmpi' is called without explicitly comparing result |
170 | // CHECK-FIXES: strcmpi(A, "a") != 0) |
171 | |
172 | if (_stricmp(A, "a" )) |
173 | return 0; |
174 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp' is called without explicitly comparing result |
175 | // CHECK-FIXES: _stricmp(A, "a") != 0) |
176 | |
177 | if (strnicmp(A, "a" , 1)) |
178 | return 0; |
179 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strnicmp' is called without explicitly comparing result |
180 | // CHECK-FIXES: strnicmp(A, "a", 1) != 0) |
181 | |
182 | if (_strnicmp(A, "a" , 1)) |
183 | return 0; |
184 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp' is called without explicitly comparing result |
185 | // CHECK-FIXES: _strnicmp(A, "a", 1) != 0) |
186 | |
187 | if (_stricmp_l(A, "a" , locale)) |
188 | return 0; |
189 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_stricmp_l' is called without explicitly comparing result |
190 | // CHECK-FIXES: _stricmp_l(A, "a", locale) != 0) |
191 | |
192 | if (_strnicmp_l(A, "a" , 1, locale)) |
193 | return 0; |
194 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_strnicmp_l' is called without explicitly comparing result |
195 | // CHECK-FIXES: _strnicmp_l(A, "a", 1, locale) != 0) |
196 | |
197 | if (wcscmp(W, L"a" )) |
198 | return 0; |
199 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscmp' is called without explicitly comparing result |
200 | // CHECK-FIXES: wcscmp(W, L"a") != 0) |
201 | |
202 | if (wcsncmp(W, L"a" , 1)) |
203 | return 0; |
204 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsncmp' is called without explicitly comparing result |
205 | // CHECK-FIXES: wcsncmp(W, L"a", 1) != 0) |
206 | |
207 | if (wcscasecmp(W, L"a" )) |
208 | return 0; |
209 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcscasecmp' is called without explicitly comparing result |
210 | // CHECK-FIXES: wcscasecmp(W, L"a") != 0) |
211 | |
212 | if (wcsicmp(W, L"a" )) |
213 | return 0; |
214 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsicmp' is called without explicitly comparing result |
215 | // CHECK-FIXES: wcsicmp(W, L"a") != 0) |
216 | |
217 | if (_wcsicmp(W, L"a" )) |
218 | return 0; |
219 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp' is called without explicitly comparing result |
220 | // CHECK-FIXES: _wcsicmp(W, L"a") != 0) |
221 | |
222 | if (_wcsicmp_l(W, L"a" , locale)) |
223 | return 0; |
224 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsicmp_l' is called without explicitly comparing result |
225 | // CHECK-FIXES: _wcsicmp_l(W, L"a", locale) != 0) |
226 | |
227 | if (wcsnicmp(W, L"a" , 1)) |
228 | return 0; |
229 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'wcsnicmp' is called without explicitly comparing result |
230 | // CHECK-FIXES: wcsnicmp(W, L"a", 1) != 0) |
231 | |
232 | if (_wcsnicmp(W, L"a" , 1)) |
233 | return 0; |
234 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp' is called without explicitly comparing result |
235 | // CHECK-FIXES: _wcsnicmp(W, L"a", 1) != 0) |
236 | |
237 | if (_wcsnicmp_l(W, L"a" , 1, locale)) |
238 | return 0; |
239 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_wcsnicmp_l' is called without explicitly comparing result |
240 | // CHECK-FIXES: _wcsnicmp_l(W, L"a", 1, locale) != 0) |
241 | |
242 | if (_mbscmp(U, V)) |
243 | return 0; |
244 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp' is called without explicitly comparing result |
245 | // CHECK-FIXES: _mbscmp(U, V) != 0) |
246 | |
247 | if (_mbsncmp(U, V, 1)) |
248 | return 0; |
249 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp' is called without explicitly comparing result |
250 | // CHECK-FIXES: _mbsncmp(U, V, 1) != 0) |
251 | |
252 | if (_mbsnbcmp(U, V, 1)) |
253 | return 0; |
254 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp' is called without explicitly comparing result |
255 | // CHECK-FIXES: _mbsnbcmp(U, V, 1) != 0) |
256 | |
257 | if (_mbsnbicmp(U, V, 1)) |
258 | return 0; |
259 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp' is called without explicitly comparing result |
260 | // CHECK-FIXES: _mbsnbicmp(U, V, 1) != 0) |
261 | |
262 | if (_mbsicmp(U, V)) |
263 | return 0; |
264 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp' is called without explicitly comparing result |
265 | // CHECK-FIXES: _mbsicmp(U, V) != 0) |
266 | |
267 | if (_mbsnicmp(U, V, 1)) |
268 | return 0; |
269 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp' is called without explicitly comparing result |
270 | // CHECK-FIXES: _mbsnicmp(U, V, 1) != 0) |
271 | |
272 | if (_mbscmp_l(U, V, locale)) |
273 | return 0; |
274 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbscmp_l' is called without explicitly comparing result |
275 | // CHECK-FIXES: _mbscmp_l(U, V, locale) != 0) |
276 | |
277 | if (_mbsncmp_l(U, V, 1, locale)) |
278 | return 0; |
279 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsncmp_l' is called without explicitly comparing result |
280 | // CHECK-FIXES: _mbsncmp_l(U, V, 1, locale) != 0) |
281 | |
282 | if (_mbsicmp_l(U, V, locale)) |
283 | return 0; |
284 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsicmp_l' is called without explicitly comparing result |
285 | // CHECK-FIXES: _mbsicmp_l(U, V, locale) != 0) |
286 | |
287 | if (_mbsnicmp_l(U, V, 1, locale)) |
288 | return 0; |
289 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnicmp_l' is called without explicitly comparing result |
290 | // CHECK-FIXES: _mbsnicmp_l(U, V, 1, locale) != 0) |
291 | |
292 | if (_mbsnbcmp_l(U, V, 1, locale)) |
293 | return 0; |
294 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbcmp_l' is called without explicitly comparing result |
295 | // CHECK-FIXES: _mbsnbcmp_l(U, V, 1, locale) != 0) |
296 | |
297 | if (_mbsnbicmp_l(U, V, 1, locale)) |
298 | return 0; |
299 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function '_mbsnbicmp_l' is called without explicitly comparing result |
300 | // CHECK-FIXES: _mbsnbicmp_l(U, V, 1, locale) != 0) |
301 | |
302 | return 1; |
303 | } |
304 | |
305 | int strcmp_wrapper1(const char* a, const char* b) { |
306 | return strcmp(a, b); |
307 | } |
308 | |
309 | int strcmp_wrapper2(const char* a, const char* b) { |
310 | return (a && b) ? strcmp(a, b) : 0; |
311 | } |
312 | |
313 | #define macro_strncmp(s1, s2, n) \ |
314 | (__extension__ (__builtin_constant_p (n) \ |
315 | && ((__builtin_constant_p (s1) \ |
316 | && strlen (s1) < ((size) (n))) \ |
317 | || (__builtin_constant_p (s2) \ |
318 | && strlen (s2) < ((size) (n)))) \ |
319 | ? strcmp (s1, s2) : strncmp (s1, s2, n))) |
320 | |
321 | int strncmp_macro(const char* a, const char* b) { |
322 | if (macro_strncmp(a, b, 4)) |
323 | return 0; |
324 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is called without explicitly comparing result |
325 | |
326 | if (macro_strncmp(a, b, 4) == 2) |
327 | return 0; |
328 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' is compared to a suspicious constant |
329 | |
330 | if (macro_strncmp(a, b, 4) <= .0) |
331 | return 0; |
332 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: function 'strcmp' has suspicious implicit cast |
333 | |
334 | if (macro_strncmp(a, b, 4) + 0) |
335 | return 0; |
336 | // CHECK-MESSAGES: [[@LINE-2]]:7: warning: results of function 'strcmp' used by operator '+' |
337 | |
338 | return 1; |
339 | } |
340 | |