xref: /llvm-project/clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp (revision 429e5be768c21d208ab688f8dfa1399c04ec5626)
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 
6 namespace std {
7 template <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 
15 inline namespace __v2 {
16 template <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 
25 namespace string_literals{
26 string operator""s(const char *, size_t);
27 }
28 
29 }
30 
31 template <typename T>
32 class TemplatedContainer {
33 public:
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 
40 template <typename T>
41 class PrivateEmpty {
42 public:
43   bool operator==(const PrivateEmpty<T>& other) const;
44   bool operator!=(const PrivateEmpty<T>& other) const;
45   unsigned long size() const;
46 private:
47   bool empty() const;
48 };
49 
50 struct BoolSize {
51   bool size() const;
52   bool empty() const;
53 };
54 
55 struct EnumSize {
56   enum E { one };
57   enum E size() const;
58   bool empty() const;
59 };
60 
61 class Container {
62 public:
63   bool operator==(const Container& other) const;
64   unsigned long size() const;
65   bool empty() const;
66 };
67 
68 class Derived : public Container {
69 };
70 
71 class Container2 {
72 public:
73   unsigned long size() const;
empty() const74   bool empty() const { return size() == 0; }
75 };
76 
77 class Container3 {
78 public:
79   unsigned long size() const;
80   bool empty() const;
81 };
82 
empty() const83 bool Container3::empty() const { return this->size() == 0; }
84 
85 class Container4 {
86 public:
87   bool operator==(const Container4& rhs) const;
88   unsigned long size() const;
empty() const89   bool empty() const { return *this == Container4(); }
90 };
91 
92 struct Lazy {
sizeLazy93   constexpr unsigned size() const { return 0; }
emptyLazy94   constexpr bool empty() const { return true; }
95 };
96 
s_func()97 std::string s_func() {
98   return std::string();
99 }
100 
takesBool(bool)101 void takesBool(bool)
102 {
103 
104 }
105 
returnsBool()106 bool 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 
457 class ConstructWithBoolField {
458   bool B;
459 public:
ConstructWithBoolField(const std::vector<int> & C)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 
466 struct 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 
func(const std::vector<int> & C)474 int 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 
481 constexpr Lazy L;
482 static_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 
487 struct 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 
f()494 template <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 
g()540 void g() {
541   f<int>();
542   f<double>();
543   f<char *>();
544 }
545 
546 template <typename T>
neverInstantiatedTemplate()547 bool 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 
689 template <typename TypeRequiresSize>
instantiatedTemplateWithSizeCall()690 void 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 
705 class TypeWithSize {
706 public:
707   TypeWithSize();
708   bool operator==(const TypeWithSize &other) const;
709   bool operator!=(const TypeWithSize &other) const;
710 
size() const711   unsigned size() const { return 0; }
712   // Does not have `.empty()`
713 };
714 
instantiator()715 void instantiator() {
716   instantiatedTemplateWithSizeCall<TypeWithSize>();
717   instantiatedTemplateWithSizeCall<std::vector<int>>();
718 }
719 
720 namespace std {
721 template <typename T>
722 struct unique_ptr {
723   T *operator->() const;
724   T &operator*() const;
725 };
726 } // namespace std
727 
call_through_unique_ptr(const std::unique_ptr<std::vector<int>> & ptr)728 bool 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 
call_through_unique_ptr_deref(const std::unique_ptr<std::vector<int>> & ptr)735 bool 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 
742 struct TypedefSize {
743   typedef int size_type;
744   size_type size() const;
745   bool empty() const;
746 };
747 
testTypedefSize()748 void 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 
756 namespace std {
757 
758 template <typename T, unsigned long N> struct array {
759   bool operator==(const array& other) const;
760   bool operator!=(const array& other) const;
sizestd::array761   unsigned long size() const { return N; }
emptystd::array762   bool empty() const { return N != 0U; }
763 
764   T data[N];
765 };
766 
767 }
768 
769 struct DummyType {
770   bool operator==(const DummyType&) const;
771   unsigned long size() const;
772   bool empty() const;
773 };
774 
775 struct IgnoredDummyType {
776   bool operator==(const IgnoredDummyType&) const;
777   unsigned long size() const;
778   bool empty() const;
779 };
780 
781 typedef std::array<int, 10U> Array;
782 
testArraySize(const Array & value)783 bool 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 
testArrayCompareToEmpty(const Array & value)790 bool testArrayCompareToEmpty(const Array& value) {
791   return value == std::array<int, 10U>();
792 }
793 
testDummyType(const DummyType & value)794 bool 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 
testIgnoredDummyType(const IgnoredDummyType & value)801 bool testIgnoredDummyType(const IgnoredDummyType& value) {
802   return value == IgnoredDummyType();
803 }
804 
testStringLiterals(const std::string & s)805 bool 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 
testNotEmptyStringLiterals(const std::string & s)813 bool testNotEmptyStringLiterals(const std::string& s)
814 {
815   using namespace std::string_literals;
816   return s == "foo"s;
817 }
818 
819 namespace 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 
f(const SU & s)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 
f(const SS & s)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 
865 namespace PR88203 {
866   struct SS {
867     bool empty() const;
868     int size() const;
869     int length(int) const;
870   };
871 
872   struct SU {
873     bool empty() const;
874     int size(int) const;
875     int length() const;
876   };
877 
f(const SS & s)878   void f(const SS& s) {
879     if (0 == s.length(1)) {}
880     if (0 == s.size()) {}
881     // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
882     // CHECK-FIXES: {{^    }}if (s.empty()) {}{{$}}
883   }
884 
f(const SU & s)885   void f(const SU& s) {
886     if (0 == s.size(1)) {}
887     if (0 == s.length()) {}
888     // CHECK-MESSAGES: :[[@LINE-1]]:14: warning: the 'empty' method should be used to check for emptiness instead of 'length' [readability-container-size-empty]
889     // CHECK-FIXES: {{^    }}if (s.empty()) {}{{$}}
890   }
891 }
892 
893 namespace PR94454 {
894   template <char...>
operator ""_ci()895   int operator""_ci() { return 0; }
896   auto eq = 0_ci == 0;
897 }
898