[clang-tools-extra] [clang-tidy] Extend readability-container-size-empty to std::size() (PR #201231)
Aayush Shrivastava via cfe-commits
cfe-commits at lists.llvm.org
Tue Jun 2 16:49:17 PDT 2026
https://github.com/iamaayushrivastava updated https://github.com/llvm/llvm-project/pull/201231
>From 200bac8dba96dc076560c4887ca3d12917818915 Mon Sep 17 00:00:00 2001
From: Aayush Shrivastava <iamaayushrivastava at gmail.com>
Date: Wed, 3 Jun 2026 04:40:53 +0530
Subject: [PATCH 1/2] [clang-tidy] Extend readability-container-size-empty to
std::size()
---
.../readability/ContainerSizeEmptyCheck.cpp | 13 +++++
.../readability/container-size-empty.rst | 14 +++---
.../readability/container-size-empty.cpp | 50 +++++++++++++++++++
3 files changed, 70 insertions(+), 7 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
index cbad3d244d841..92ebd038610b6 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -208,6 +208,19 @@ void ContainerSizeEmptyCheck::registerMatchers(MatchFinder *Finder) {
.bind("SizeCallExpr"),
this);
+ // Match non-member std::size(container) used in boolean context or compared
+ // with 0/1.
+ Finder->addMatcher(
+ callExpr(argumentCountIs(1),
+ callee(functionDecl(hasName("::std::size")).bind("SizeMethod")),
+ hasArgument(0, expr(anyOf(hasType(ValidContainer),
+ hasType(pointsTo(ValidContainer)),
+ hasType(references(ValidContainer))))
+ .bind("MemberCallObject")),
+ WrongUse, NotInEmptyMethodOfContainer)
+ .bind("SizeCallExpr"),
+ this);
+
// Comparison to empty string or empty constructor.
const auto WrongComparend =
anyOf(stringLiteral(hasSize(0)),
diff --git a/clang-tools-extra/docs/clang-tidy/checks/readability/container-size-empty.rst b/clang-tools-extra/docs/clang-tidy/checks/readability/container-size-empty.rst
index cc012fdcd7649..70b05f498d804 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/readability/container-size-empty.rst
+++ b/clang-tools-extra/docs/clang-tidy/checks/readability/container-size-empty.rst
@@ -4,15 +4,15 @@ readability-container-size-empty
================================
-Checks whether a call to the ``size()``/``length()`` method can be replaced
-with a call to ``empty()``.
+Checks whether a call to the ``size()``/``length()`` method or the
+``std::size()`` free function can be replaced with a call to ``empty()``.
The emptiness of a container should be checked using the ``empty()`` method
-instead of the ``size()``/``length()`` method. It shows clearer intent to use
-``empty()``. Furthermore some containers (for example, a ``std::forward_list``)
-may implement the ``empty()`` method but not implement the ``size()`` or
-``length()`` method. Using ``empty()`` whenever possible makes it easier to
-switch to another container in the future.
+instead of the ``size()``/``length()`` method or ``std::size()``. It shows
+clearer intent to use ``empty()``. Furthermore some containers (for example, a
+``std::forward_list``) may implement the ``empty()`` method but not implement
+the ``size()`` or ``length()`` method. Using ``empty()`` whenever possible
+makes it easier to switch to another container in the future.
The check issues warning if a container has ``empty()`` and ``size()`` or
``length()`` methods matching following signatures:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
index cd2eebb16138b..9edca775a73d9 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/container-size-empty.cpp
@@ -27,6 +27,12 @@ namespace string_literals{
string operator""s(const char *, size_t);
}
+template <class C>
+auto size(const C& c) -> decltype(c.size());
+
+template <class C>
+auto empty(const C& c) -> decltype(c.empty());
+
}
template <typename T>
@@ -924,6 +930,50 @@ class ReportInTemplateContainerNonEmptyMethod {
}
};
+namespace GH198494 {
+
+void testStdSize(const std::string &str, std::vector<int> vect) {
+ if (std::size(vect))
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (!vect.empty())
+
+ if (!std::size(vect))
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:8: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (vect.empty())
+
+ if (std::size(vect) == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (vect.empty())
+
+ if (std::size(vect) != 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (!vect.empty())
+
+ if (std::size(vect) > 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (!vect.empty())
+
+ if (std::size(str))
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (!str.empty())
+
+ if (std::size(str) == 0)
+ ;
+ // CHECK-MESSAGES: :[[@LINE-2]]:7: warning: the 'empty' method should be used to check for emptiness instead of 'size' [readability-container-size-empty]
+ // CHECK-FIXES: if (str.empty())
+
+ // No warning when std::empty is already used.
+ if (std::empty(vect)) {}
+}
+
+} // namespace GH198494
+
class ReportInContainerNonEmptyMethodCompare {
>From 95e6cf68a0359280254e48248967c03d181e3578 Mon Sep 17 00:00:00 2001
From: Aayush Shrivastava <iamaayushrivastava at gmail.com>
Date: Wed, 3 Jun 2026 05:18:53 +0530
Subject: [PATCH 2/2] [clang-tidy] Fix diagnostic message for std::size()
template specialization
---
.../clang-tidy/readability/ContainerSizeEmptyCheck.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
index 92ebd038610b6..08deaf40f62c7 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerSizeEmptyCheck.cpp
@@ -419,7 +419,7 @@ void ContainerSizeEmptyCheck::check(const MatchFinder::MatchResult &Result) {
"for emptiness instead of %0");
if (const auto *SizeMethod =
Result.Nodes.getNodeAs<NamedDecl>("SizeMethod"))
- Diag << SizeMethod;
+ Diag << SizeMethod->getDeclName();
else if (const auto *DependentExpr =
Result.Nodes.getNodeAs<CXXDependentScopeMemberExpr>(
"MemberExpr"))
More information about the cfe-commits
mailing list