1// RUN: %check_clang_tidy -std=c++14-or-later %s readability-container-size-empty %t -- \
2// RUN: -config="{CheckOptions: {readability-container-size-empty.ExcludedComparisonTypes: '::std::array;::IgnoredDummyType'}}" \
3// RUN: -- -fno-delayed-template-parsing -isystem %clang_tidy_headers
4#include <string>
5
6namespace std {
7template <typename T> struct vector {
8 vector();
9 bool operator==(const vector<T>& other) const;
10 bool operator!=(const vector<T>& other) const;
11 unsigned long size() const;
12 bool empty() const;
13};
14
15inline namespace __v2 {
16template <typename T> struct set {
17 set();
18 bool operator==(const set<T>& other) const;
19 bool operator!=(const set<T>& other) const;
20 unsigned long size() const;
21 bool empty() const;
22};
23}
24
25namespace string_literals{
26string operator""s(const char *, size_t);
27}
28
29}
30
31template <typename T>
32class TemplatedContainer {
33public:
34 bool operator==(const TemplatedContainer<T>& other) const;
35 bool operator!=(const TemplatedContainer<T>& other) const;
36 unsigned long size() const;
37 bool empty() const;
38};
39
40template <typename T>
41class PrivateEmpty {
42public:
43 bool operator==(const PrivateEmpty<T>& other) const;
44 bool operator!=(const PrivateEmpty<T>& other) const;
45 unsigned long size() const;
46private:
47 bool empty() const;
48};
49
50struct BoolSize {
51 bool size() const;
52 bool empty() const;
53};
54
55struct EnumSize {
56 enum E { one };
57 enum E size() const;
58 bool empty() const;
59};
60
61class Container {
62public:
63 bool operator==(const Container& other) const;
64 unsigned long size() const;
65 bool empty() const;
66};
67
68class Derived : public Container {
69};
70
71class Container2 {
72public:
73 unsigned long size() const;
74 bool empty() const { return size() == 0; }
75};
76
77class Container3 {
78public:
79 unsigned long size() const;
80 bool empty() const;
81};
82
83bool Container3::empty() const { return this->size() == 0; }
84
85class Container4 {
86public:
87 bool operator==(const Container4& rhs) const;
88 unsigned long size() const;
89 bool empty() const { return *this == Container4(); }
90};
91
92struct Lazy {
93 constexpr unsigned size() const { return 0; }
94 constexpr bool empty() const { return true; }
95};
96
97std::string s_func() {
98 return std::string();
99}
100
101void takesBool(bool)
102{
103
104}
105
106bool returnsBool() {
107 std::set<int> intSet;
108 std::string str;
109 std::string str2;
110 std::wstring wstr;
111 (void)(str.size() + 0);
112 (void)(str.length() + 0);
113 (void)(str.size() - 0);
114 (void)(str.length() - 0);
115 (void)(0 + str.size());
116 (void)(0 + str.length());
117 (void)(0 - str.size());
118 (void)(0 - str.length());
119 if (intSet.size() == 0)
120 ;
121 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
122 // CHECK-FIXES: {{^ }}if (intSet.empty()){{$}}
123 // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
124 if (intSet == std::set<int>())
125 ;
126 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness
127 // CHECK-FIXES: {{^ }}if (intSet.empty()){{$}}
128 // CHECK-MESSAGES: :21:8: note: method 'set'::empty() defined here
129 if (s_func() == "")
130 ;
131 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
132 // CHECK-FIXES: {{^ }}if (s_func().empty()){{$}}
133 if (str.size() == 0)
134 ;
135 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size'
136 // CHECK-FIXES: {{^ }}if (str.empty()){{$}}
137 if (str.length() == 0)
138 ;
139 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'length'
140 // CHECK-FIXES: {{^ }}if (str.empty()){{$}}
141 if ((str + str2).size() == 0)
142 ;
143 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size'
144 // CHECK-FIXES: {{^ }}if ((str + str2).empty()){{$}}
145 if ((str + str2).length() == 0)
146 ;
147 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'length'
148 // CHECK-FIXES: {{^ }}if ((str + str2).empty()){{$}}
149 if (str == "")
150 ;
151 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
152 // CHECK-FIXES: {{^ }}if (str.empty()){{$}}
153 if (str + str2 == "")
154 ;
155 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
156 // CHECK-FIXES: {{^ }}if ((str + str2).empty()){{$}}
157 if (wstr.size() == 0)
158 ;
159 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size'
160 // CHECK-FIXES: {{^ }}if (wstr.empty()){{$}}
161 if (wstr.length() == 0)
162 ;
163 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'length'
164 // CHECK-FIXES: {{^ }}if (wstr.empty()){{$}}
165 if (wstr == L"")
166 ;
167 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
168 // CHECK-FIXES: {{^ }}if (wstr.empty()){{$}}
169 std::vector<int> vect;
170 if (vect.size() == 0)
171 ;
172 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size'
173 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
174 if (vect == std::vector<int>())
175 ;
176 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
177 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
178 if (vect.size() != 0)
179 ;
180 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
181 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
182 if (vect != std::vector<int>())
183 ;
184 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
185 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
186 if (0 == vect.size())
187 ;
188 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
189 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
190 if (0 != vect.size())
191 ;
192 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
193 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
194 if (std::vector<int>() == vect)
195 ;
196 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
197 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
198 if (std::vector<int>() != vect)
199 ;
200 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
201 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
202 if (vect.size() > 0)
203 ;
204 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
205 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
206 if (0 < vect.size())
207 ;
208 // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
209 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
210 if (vect.size() < 1)
211 ;
212 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
213 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
214 if (1 > vect.size())
215 ;
216 // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
217 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
218 if (vect.size() >= 1)
219 ;
220 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
221 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
222 if (1 <= vect.size())
223 ;
224 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
225 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
226 if (vect.size() > 1) // no warning
227 ;
228 if (1 < vect.size()) // no warning
229 ;
230 if (vect.size() <= 1) // no warning
231 ;
232 if (1 >= vect.size()) // no warning
233 ;
234 if (!vect.size())
235 ;
236 // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
237 // CHECK-FIXES: {{^ }}if (vect.empty()){{$}}
238 if (vect.size())
239 ;
240 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
241 // CHECK-FIXES: {{^ }}if (!vect.empty()){{$}}
242
243 if (vect.empty())
244 ;
245
246 const std::vector<int> vect2;
247 if (vect2.size() != 0)
248 ;
249 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
250 // CHECK-FIXES: {{^ }}if (!vect2.empty()){{$}}
251
252 std::vector<int> *vect3 = new std::vector<int>();
253 if (vect3->size() == 0)
254 ;
255 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
256 // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
257 if ((*vect3).size() == 0)
258 ;
259 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
260 // CHECK-FIXES: {{^ }}if ((*vect3).empty()){{$}}
261 if ((*vect3) == std::vector<int>())
262 ;
263 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
264 // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
265 if (*vect3 == std::vector<int>())
266 ;
267 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
268 // CHECK-FIXES: {{^ }}if (vect3->empty()){{$}}
269
270 delete vect3;
271
272 const std::vector<int> &vect4 = vect2;
273 if (vect4.size() == 0)
274 ;
275 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
276 // CHECK-FIXES: {{^ }}if (vect4.empty()){{$}}
277 if (vect4 == std::vector<int>())
278 ;
279 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
280 // CHECK-FIXES: {{^ }}if (vect4.empty()){{$}}
281
282 TemplatedContainer<void> templated_container;
283 if (templated_container.size() == 0)
284 ;
285 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
286 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
287 if (templated_container == TemplatedContainer<void>())
288 ;
289 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
290 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
291 if (templated_container.size() != 0)
292 ;
293 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
294 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
295 if (templated_container != TemplatedContainer<void>())
296 ;
297 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
298 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
299 if (0 == templated_container.size())
300 ;
301 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
302 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
303 if (TemplatedContainer<void>() == templated_container)
304 ;
305 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
306 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
307 if (0 != templated_container.size())
308 ;
309 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
310 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
311 if (TemplatedContainer<void>() != templated_container)
312 ;
313 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
314 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
315 if (templated_container.size() > 0)
316 ;
317 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
318 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
319 if (0 < templated_container.size())
320 ;
321 // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
322 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
323 if (templated_container.size() < 1)
324 ;
325 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
326 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
327 if (1 > templated_container.size())
328 ;
329 // CHECK-MESSAGES: :[[@LINE-2]]:11: warning: the 'empty' method should be used
330 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
331 if (templated_container.size() >= 1)
332 ;
333 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
334 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
335 if (1 <= templated_container.size())
336 ;
337 // CHECK-MESSAGES: :[[@LINE-2]]:12: warning: the 'empty' method should be used
338 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
339 if (templated_container.size() > 1) // no warning
340 ;
341 if (1 < templated_container.size()) // no warning
342 ;
343 if (templated_container.size() <= 1) // no warning
344 ;
345 if (1 >= templated_container.size()) // no warning
346 ;
347 if (!templated_container.size())
348 ;
349 // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
350 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
351 if (templated_container.size())
352 ;
353 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
354 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
355
356 if (templated_container.empty())
357 ;
358
359 // No warnings expected.
360 PrivateEmpty<void> private_empty;
361 if (private_empty.size() == 0)
362 ;
363 if (private_empty == PrivateEmpty<void>())
364 ;
365 if (private_empty.size() != 0)
366 ;
367 if (private_empty != PrivateEmpty<void>())
368 ;
369 if (0 == private_empty.size())
370 ;
371 if (PrivateEmpty<void>() == private_empty)
372 ;
373 if (0 != private_empty.size())
374 ;
375 if (PrivateEmpty<void>() != private_empty)
376 ;
377 if (private_empty.size() > 0)
378 ;
379 if (0 < private_empty.size())
380 ;
381 if (private_empty.size() < 1)
382 ;
383 if (1 > private_empty.size())
384 ;
385 if (private_empty.size() >= 1)
386 ;
387 if (1 <= private_empty.size())
388 ;
389 if (private_empty.size() > 1)
390 ;
391 if (1 < private_empty.size())
392 ;
393 if (private_empty.size() <= 1)
394 ;
395 if (1 >= private_empty.size())
396 ;
397 if (!private_empty.size())
398 ;
399 if (private_empty.size())
400 ;
401
402 // Types with weird size() return type.
403 BoolSize bs;
404 if (bs.size() == 0)
405 ;
406 EnumSize es;
407 if (es.size() == 0)
408 ;
409
410 Derived derived;
411 if (derived.size() == 0)
412 ;
413 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
414 // CHECK-FIXES: {{^ }}if (derived.empty()){{$}}
415 if (derived == Derived())
416 ;
417 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
418 // CHECK-FIXES: {{^ }}if (derived.empty()){{$}}
419
420 takesBool(derived.size());
421 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
422 // CHECK-FIXES: {{^ }}takesBool(!derived.empty());
423
424 takesBool(derived.size() == 0);
425 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
426 // CHECK-FIXES: {{^ }}takesBool(derived.empty());
427
428 takesBool(derived.size() != 0);
429 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
430 // CHECK-FIXES: {{^ }}takesBool(!derived.empty());
431
432 bool b1 = derived.size();
433 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
434 // CHECK-FIXES: {{^ }}bool b1 = !derived.empty();
435
436 bool b2(derived.size());
437 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the 'empty' method should be used
438 // CHECK-FIXES: {{^ }}bool b2(!derived.empty());
439
440 auto b3 = static_cast<bool>(derived.size());
441 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: the 'empty' method should be used
442 // CHECK-FIXES: {{^ }}auto b3 = static_cast<bool>(!derived.empty());
443
444 auto b4 = (bool)derived.size();
445 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: the 'empty' method should be used
446 // CHECK-FIXES: {{^ }}auto b4 = (bool)!derived.empty();
447
448 auto b5 = bool(derived.size());
449 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: the 'empty' method should be used
450 // CHECK-FIXES: {{^ }}auto b5 = bool(!derived.empty());
451
452 return derived.size();
453 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
454 // CHECK-FIXES: {{^ }}return !derived.empty();
455}
456
457class ConstructWithBoolField {
458 bool B;
459public:
460 ConstructWithBoolField(const std::vector<int> &C) : B(C.size()) {}
461// CHECK-MESSAGES: :[[@LINE-1]]:57: warning: the 'empty' method should be used
462// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
463// CHECK-FIXES: {{^ }}ConstructWithBoolField(const std::vector<int> &C) : B(!C.empty()) {}
464};
465
466struct StructWithNSDMI {
467 std::vector<int> C;
468 bool B = C.size();
469// CHECK-MESSAGES: :[[@LINE-1]]:12: warning: the 'empty' method should be used
470// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
471// CHECK-FIXES: {{^ }}bool B = !C.empty();
472};
473
474int func(const std::vector<int> &C) {
475 return C.size() ? 0 : 1;
476// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
477// CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
478// CHECK-FIXES: {{^ }}return !C.empty() ? 0 : 1;
479}
480
481constexpr Lazy L;
482static_assert(!L.size(), "");
483// CHECK-MESSAGES: :[[@LINE-1]]:16: warning: the 'empty' method should be used
484// CHECK-MESSAGES: :94:18: note: method 'Lazy'::empty() defined here
485// CHECK-FIXES: {{^}}static_assert(L.empty(), "");
486
487struct StructWithLazyNoexcept {
488 void func() noexcept(L.size());
489};
490
491#define CHECKSIZE(x) if (x.size()) {}
492// CHECK-FIXES: #define CHECKSIZE(x) if (x.size()) {}
493
494template <typename T> void f() {
495 std::vector<T> v;
496 if (v.size())
497 ;
498 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
499 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
500 // CHECK-FIXES: {{^ }}if (!v.empty()){{$}}
501 if (v == std::vector<T>())
502 ;
503 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of comparing to an empty object [readability-container-size-empty]
504 // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
505 // CHECK-FIXES-NEXT: ;
506 CHECKSIZE(v);
507 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
508 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
509 // CHECK-FIXES: CHECKSIZE(v);
510
511 TemplatedContainer<T> templated_container;
512 if (templated_container.size())
513 ;
514 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
515 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
516 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
517 if (templated_container != TemplatedContainer<T>())
518 ;
519 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
520 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
521 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
522 // CHECK-FIXES-NEXT: ;
523 CHECKSIZE(templated_container);
524 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
525 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
526 // CHECK-FIXES: CHECKSIZE(templated_container);
527 std::basic_string<T> s;
528 if (s.size())
529 ;
530 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
531 // CHECK-MESSAGES: string:{{[0-9]+}}:8: note: method 'basic_string'::empty() defined here
532 // CHECK-FIXES: {{^ }}if (!s.empty()){{$}}
533 if (s.length())
534 ;
535 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'length' [readability-container-size-empty]
536 // CHECK-MESSAGES: string:{{[0-9]+}}:8: note: method 'basic_string'::empty() defined here
537 // CHECK-FIXES: {{^ }}if (!s.empty()){{$}}
538}
539
540void g() {
541 f<int>();
542 f<double>();
543 f<char *>();
544}
545
546template <typename T>
547bool neverInstantiatedTemplate() {
548 std::vector<T> v;
549 if (v.size())
550 ;
551 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
552 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
553 // CHECK-FIXES: {{^ }}if (!v.empty()){{$}}
554
555 if (v == std::vector<T>())
556 ;
557 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of comparing to an empty object [readability-container-size-empty]
558 // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
559 // CHECK-FIXES-NEXT: ;
560 if (v.size() == 0)
561 ;
562 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
563 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
564 // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
565 if (v.size() != 0)
566 ;
567 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
568 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
569 // CHECK-FIXES: {{^ }}if (!v.empty()){{$}}
570 if (v.size() < 1)
571 ;
572 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
573 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
574 // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
575 if (v.size() > 0)
576 ;
577 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
578 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
579 // CHECK-FIXES: {{^ }}if (!v.empty()){{$}}
580 if (v.size() == 1)
581 ;
582 if (v.size() != 1)
583 ;
584 if (v.size() == 2)
585 ;
586 if (v.size() != 2)
587 ;
588
589 if (static_cast<bool>(v.size()))
590 ;
591 // CHECK-MESSAGES: :[[@LINE-2]]:25: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
592 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
593 // CHECK-FIXES: {{^ }}if (static_cast<bool>(!v.empty())){{$}}
594 if (v.size() && false)
595 ;
596 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
597 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
598 // CHECK-FIXES: {{^ }}if (!v.empty() && false){{$}}
599 if (!v.size())
600 ;
601 // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
602 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
603 // CHECK-FIXES: {{^ }}if (v.empty()){{$}}
604
605 TemplatedContainer<T> templated_container;
606 if (templated_container.size())
607 ;
608 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
609 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
610 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
611 if (templated_container != TemplatedContainer<T>())
612 ;
613 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
614 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
615 // CHECK-FIXES: {{^ }}if (!templated_container.empty()){{$}}
616 // CHECK-FIXES-NEXT: ;
617 while (templated_container.size())
618 ;
619 // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: the 'empty' method should be used
620 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
621 // CHECK-FIXES: {{^ }}while (!templated_container.empty()){{$}}
622
623 do {
624 }
625 while (templated_container.size());
626 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
627 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
628 // CHECK-FIXES: {{^ }}while (!templated_container.empty());
629
630 for (; templated_container.size();)
631 ;
632 // CHECK-MESSAGES: :[[@LINE-2]]:10: warning: the 'empty' method should be used
633 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
634 // CHECK-FIXES: {{^ }}for (; !templated_container.empty();){{$}}
635
636 if (true && templated_container.size())
637 ;
638 // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: the 'empty' method should be used
639 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
640 // CHECK-FIXES: {{^ }}if (true && !templated_container.empty()){{$}}
641
642 if (true || templated_container.size())
643 ;
644 // CHECK-MESSAGES: :[[@LINE-2]]:15: warning: the 'empty' method should be used
645 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
646 // CHECK-FIXES: {{^ }}if (true || !templated_container.empty()){{$}}
647
648 if (!templated_container.size())
649 ;
650 // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used
651 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
652 // CHECK-FIXES: {{^ }}if (templated_container.empty()){{$}}
653
654 bool b1 = templated_container.size();
655 // CHECK-MESSAGES: :[[@LINE-1]]:13: warning: the 'empty' method should be used
656 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
657 // CHECK-FIXES: {{^ }}bool b1 = !templated_container.empty();
658
659 bool b2(templated_container.size());
660 // CHECK-MESSAGES: :[[@LINE-1]]:11: warning: the 'empty' method should be used
661 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
662 // CHECK-FIXES: {{^ }}bool b2(!templated_container.empty());
663
664 auto b3 = static_cast<bool>(templated_container.size());
665 // CHECK-MESSAGES: :[[@LINE-1]]:31: warning: the 'empty' method should be used
666 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
667 // CHECK-FIXES: {{^ }}auto b3 = static_cast<bool>(!templated_container.empty());
668
669 auto b4 = (bool)templated_container.size();
670 // CHECK-MESSAGES: :[[@LINE-1]]:19: warning: the 'empty' method should be used
671 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
672 // CHECK-FIXES: {{^ }}auto b4 = (bool)!templated_container.empty();
673
674 auto b5 = bool(templated_container.size());
675 // CHECK-MESSAGES: :[[@LINE-1]]:18: warning: the 'empty' method should be used
676 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
677 // CHECK-FIXES: {{^ }}auto b5 = bool(!templated_container.empty());
678
679 takesBool(templated_container.size());
680 // We don't detect this one because we don't know the parameter of takesBool
681 // until the type of templated_container.size() is known
682
683 return templated_container.size();
684 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
685 // CHECK-MESSAGES: :37:8: note: method 'TemplatedContainer'::empty() defined here
686 // CHECK-FIXES: {{^ }}return !templated_container.empty();
687}
688
689template <typename TypeRequiresSize>
690void instantiatedTemplateWithSizeCall() {
691 TypeRequiresSize t;
692 // The instantiation of the template with std::vector<int> should not
693 // result in changing the template, because we don't know that
694 // TypeRequiresSize generally has `.empty()`
695 if (t.size())
696 ;
697
698 if (t == TypeRequiresSize{})
699 ;
700
701 if (t != TypeRequiresSize{})
702 ;
703}
704
705class TypeWithSize {
706public:
707 TypeWithSize();
708 bool operator==(const TypeWithSize &other) const;
709 bool operator!=(const TypeWithSize &other) const;
710
711 unsigned size() const { return 0; }
712 // Does not have `.empty()`
713};
714
715void instantiator() {
716 instantiatedTemplateWithSizeCall<TypeWithSize>();
717 instantiatedTemplateWithSizeCall<std::vector<int>>();
718}
719
720namespace std {
721template <typename T>
722struct unique_ptr {
723 T *operator->() const;
724 T &operator*() const;
725};
726} // namespace std
727
728bool call_through_unique_ptr(const std::unique_ptr<std::vector<int>> &ptr) {
729 return ptr->size() > 0;
730 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
731 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
732 // CHECK-FIXES: {{^ }}return !ptr->empty();
733}
734
735bool call_through_unique_ptr_deref(const std::unique_ptr<std::vector<int>> &ptr) {
736 return (*ptr).size() > 0;
737 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
738 // CHECK-MESSAGES: :12:8: note: method 'vector'::empty() defined here
739 // CHECK-FIXES: {{^ }}return !(*ptr).empty();
740}
741
742struct TypedefSize {
743 typedef int size_type;
744 size_type size() const;
745 bool empty() const;
746};
747
748void testTypedefSize() {
749 TypedefSize ts;
750 if (ts.size() == 0)
751 ;
752 // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used
753 // CHECK-FIXES: {{^ }}if (ts.empty()){{$}}
754}
755
756namespace std {
757
758template <typename T, unsigned long N> struct array {
759 bool operator==(const array& other) const;
760 bool operator!=(const array& other) const;
761 unsigned long size() const { return N; }
762 bool empty() const { return N != 0U; }
763
764 T data[N];
765};
766
767}
768
769struct DummyType {
770 bool operator==(const DummyType&) const;
771 unsigned long size() const;
772 bool empty() const;
773};
774
775struct IgnoredDummyType {
776 bool operator==(const IgnoredDummyType&) const;
777 unsigned long size() const;
778 bool empty() const;
779};
780
781typedef std::array<int, 10U> Array;
782
783bool testArraySize(const Array& value) {
784 return value.size() == 0U;
785// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
786// CHECK-FIXES: {{^ }}return value.empty();{{$}}
787// CHECK-MESSAGES: :[[@LINE-25]]:8: note: method 'array'::empty() defined here
788}
789
790bool testArrayCompareToEmpty(const Array& value) {
791 return value == std::array<int, 10U>();
792}
793
794bool testDummyType(const DummyType& value) {
795 return value == DummyType();
796// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used to check for emptiness instead of comparing to an empty object [readability-container-size-empty]
797// CHECK-FIXES: {{^ }}return value.empty();{{$}}
798// CHECK-MESSAGES: :[[@LINE-26]]:8: note: method 'DummyType'::empty() defined here
799}
800
801bool testIgnoredDummyType(const IgnoredDummyType& value) {
802 return value == IgnoredDummyType();
803}
804
805bool testStringLiterals(const std::string& s)
806{
807 using namespace std::string_literals;
808 return s == ""s;
809 // CHECK-MESSAGES: :[[@LINE-1]]:10: warning: the 'empty' method should be used
810 // CHECK-FIXES: {{^ }}return s.empty()
811}
812
813bool testNotEmptyStringLiterals(const std::string& s)
814{
815 using namespace std::string_literals;
816 return s == "foo"s;
817}
818
819namespace PR72619 {
820 struct SS {
821 bool empty() const;
822 int size() const;
823 };
824
825 struct SU {
826 bool empty() const;
827 unsigned size() const;
828 };
829
830 void f(const SU& s) {
831 if (s.size() < 0) {}
832 if (0 > s.size()) {}
833 if (s.size() >= 0) {}
834 if (0 <= s.size()) {}
835 if (s.size() < 1)
836 ;
837 // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
838 // CHECK-FIXES: {{^ }}if (s.empty()){{$}}
839 if (1 > s.size())
840 ;
841 // CHECK-MESSAGES: :[[@LINE-2]]:13: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
842 // CHECK-FIXES: {{^ }}if (s.empty()){{$}}
843 if (s.size() <= 0)
844 ;
845 // CHECK-MESSAGES: :[[@LINE-2]]:9: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
846 // CHECK-FIXES: {{^ }}if (s.empty()){{$}}
847 if (0 >= s.size())
848 ;
849 // CHECK-MESSAGES: :[[@LINE-2]]:14: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
850 // CHECK-FIXES: {{^ }}if (s.empty()){{$}}
851 }
852
853 void f(const SS& s) {
854 if (s.size() < 0) {}
855 if (0 > s.size()) {}
856 if (s.size() >= 0) {}
857 if (0 <= s.size()) {}
858 if (s.size() < 1) {}
859 if (1 > s.size()) {}
860 if (s.size() <= 0) {}
861 if (0 >= s.size()) {}
862 }
863}
864

source code of clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp