[clang-tools-extra] [clang-tidy] Fix `readability-container-data-pointer` check (PR #165636)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 31 10:45:35 PDT 2025
https://github.com/zeyi2 updated https://github.com/llvm/llvm-project/pull/165636
>From f29accd639928c3560309a15bf42e81b65e5b20f Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Thu, 30 Oct 2025 02:56:11 +0800
Subject: [PATCH 1/4] [clang-tidy] Fix `readability-container-data-pointer`
check
---
.../readability/ContainerDataPointerCheck.cpp | 7 +++++--
.../checkers/readability/container-data-pointer.cpp | 12 ++++++++++++
2 files changed, 17 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
index 11756d10a8221..d9338888cc40e 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
@@ -107,8 +107,11 @@ void ContainerDataPointerCheck::check(const MatchFinder::MatchResult &Result) {
Lexer::getSourceText(CharSourceRange::getTokenRange(SrcRange),
*Result.SourceManager, getLangOpts())};
- if (!isa<DeclRefExpr, ArraySubscriptExpr, CXXOperatorCallExpr, CallExpr,
- MemberExpr>(CE))
+ const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(CE);
+ bool NeedsParens =
+ OpCall ? (OpCall->getOperator() != OO_Subscript)
+ : !isa<DeclRefExpr, MemberExpr, ArraySubscriptExpr, CallExpr>(CE);
+ if (NeedsParens)
ReplacementText = "(" + ReplacementText + ")";
if (CE->getType()->isPointerType())
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
index a8e0eb6d262e6..26f9d9f16ac8c 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -35,6 +35,12 @@ template <typename T>
struct enable_if<true, T> {
typedef T type;
};
+
+template <typename T>
+struct unique_ptr {
+ T &operator*() const;
+ T *operator->() const;
+};
}
template <typename T>
@@ -144,3 +150,9 @@ int *r() {
// CHECK-MESSAGES: :[[@LINE-1]]:10: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
// CHECK-FIXES: return holder.v.data();
}
+
+void s(std::unique_ptr<std::vector<unsigned char>> p) {
+ f(&(*p)[0]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
+ // CHECK-FIXES: f((*p).data());
+}
>From b7dcb77b75d080d9003a96c669c40ca09c11fedc Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Thu, 30 Oct 2025 23:54:29 +0800
Subject: [PATCH 2/4] add release notes and fix minor issue
---
.../clang-tidy/readability/ContainerDataPointerCheck.cpp | 2 +-
clang-tools-extra/docs/ReleaseNotes.rst | 6 +++++-
2 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
index d9338888cc40e..dba4aa8d5fc6e 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
@@ -108,7 +108,7 @@ void ContainerDataPointerCheck::check(const MatchFinder::MatchResult &Result) {
*Result.SourceManager, getLangOpts())};
const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(CE);
- bool NeedsParens =
+ const bool NeedsParens =
OpCall ? (OpCall->getOperator() != OO_Subscript)
: !isa<DeclRefExpr, MemberExpr, ArraySubscriptExpr, CallExpr>(CE);
if (NeedsParens)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 8f4be0d1cb259..40c00c8206aff 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -362,7 +362,7 @@ Changes in existing checks
- Improved :doc:`misc-const-correctness
<clang-tidy/checks/misc/const-correctness>` check to avoid false
- positives when pointers is transferred to non-const references
+ positives when pointers is transferred to non-const references
and avoid false positives of function pointer and fix false
positives on return of non-const pointer.
@@ -429,6 +429,10 @@ Changes in existing checks
comparisons to ``npos``. Internal changes may cause new rare false positives
in non-standard containers.
+- Improved :doc:`readability-container-data-pointer
+ <clang-tidy/checks/readability/container-data-pointer>`check by correctly
+ adding parentheses when the container expression is a dereference.
+
- Improved :doc:`readability-container-size-empty
<clang-tidy/checks/readability/container-size-empty>` check by correctly
generating fix-it hints when size method is called from implicit ``this``,
>From 76bc6cfdcb8faa6ff24016baa9fb40051c28f9fd Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Fri, 31 Oct 2025 00:19:10 +0800
Subject: [PATCH 3/4] fix docs
---
clang-tools-extra/docs/ReleaseNotes.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 40c00c8206aff..11337aa3d628e 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -430,7 +430,7 @@ Changes in existing checks
in non-standard containers.
- Improved :doc:`readability-container-data-pointer
- <clang-tidy/checks/readability/container-data-pointer>`check by correctly
+ <clang-tidy/checks/readability/container-data-pointer>` check by correctly
adding parentheses when the container expression is a dereference.
- Improved :doc:`readability-container-size-empty
>From f63a789bac9970206a38e41cd386dc012fbee704 Mon Sep 17 00:00:00 2001
From: mtx <mitchell.xu2 at gmail.com>
Date: Sat, 1 Nov 2025 01:41:26 +0800
Subject: [PATCH 4/4] Add more tests
---
.../readability/ContainerDataPointerCheck.cpp | 33 ++++++++++---------
.../readability/ContainerDataPointerCheck.h | 2 +-
.../readability/container-data-pointer.cpp | 9 +++++
3 files changed, 28 insertions(+), 16 deletions(-)
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
index dba4aa8d5fc6e..b9b8c9a829bfe 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.cpp
@@ -71,20 +71,20 @@ void ContainerDataPointerCheck::registerMatchers(MatchFinder *Finder) {
const auto Zero = integerLiteral(equals(0));
- const auto SubscriptOperator = callee(cxxMethodDecl(hasName("operator[]")));
-
- Finder->addMatcher(
+ const auto AddressOfMatcher =
unaryOperator(
unless(isExpansionInSystemHeader()), hasOperatorName("&"),
- hasUnaryOperand(expr(
- anyOf(cxxOperatorCallExpr(SubscriptOperator, argumentCountIs(2),
- hasArgument(0, ContainerExpr),
- hasArgument(1, Zero)),
- cxxMemberCallExpr(SubscriptOperator, on(ContainerExpr),
- argumentCountIs(1), hasArgument(0, Zero)),
- arraySubscriptExpr(hasLHS(ContainerExpr), hasRHS(Zero))))))
- .bind(AddressOfName),
- this);
+ hasUnaryOperand(ignoringParenImpCasts(expr(anyOf(
+ cxxOperatorCallExpr(
+ hasOverloadedOperatorName("[]"), argumentCountIs(2),
+ hasArgument(0, ContainerExpr), hasArgument(1, Zero)),
+ cxxMemberCallExpr(callee(cxxMethodDecl(hasName("operator[]"))),
+ on(ContainerExpr), argumentCountIs(1),
+ hasArgument(0, Zero)),
+ arraySubscriptExpr(hasLHS(ContainerExpr), hasRHS(Zero)))))))
+ .bind(AddressOfName);
+
+ Finder->addMatcher(AddressOfMatcher, this);
}
void ContainerDataPointerCheck::check(const MatchFinder::MatchResult &Result) {
@@ -101,16 +101,19 @@ void ContainerDataPointerCheck::check(const MatchFinder::MatchResult &Result) {
else if (ACE)
CE = ACE;
- SourceRange SrcRange = CE->getSourceRange();
+ const Expr *PrintedCE = CE->IgnoreParenImpCasts();
+
+ SourceRange SrcRange = PrintedCE->getSourceRange();
std::string ReplacementText{
Lexer::getSourceText(CharSourceRange::getTokenRange(SrcRange),
*Result.SourceManager, getLangOpts())};
- const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(CE);
+ const auto *OpCall = dyn_cast<CXXOperatorCallExpr>(PrintedCE);
const bool NeedsParens =
OpCall ? (OpCall->getOperator() != OO_Subscript)
- : !isa<DeclRefExpr, MemberExpr, ArraySubscriptExpr, CallExpr>(CE);
+ : !isa<DeclRefExpr, MemberExpr, ArraySubscriptExpr, CallExpr>(
+ PrintedCE);
if (NeedsParens)
ReplacementText = "(" + ReplacementText + ")";
diff --git a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h
index 71fde87fbb093..d71cb7ff21904 100644
--- a/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h
+++ b/clang-tools-extra/clang-tidy/readability/ContainerDataPointerCheck.h
@@ -34,7 +34,7 @@ class ContainerDataPointerCheck : public ClangTidyCheck {
void check(const ast_matchers::MatchFinder::MatchResult &Result) override;
std::optional<TraversalKind> getCheckTraversalKind() const override {
- return TK_IgnoreUnlessSpelledInSource;
+ return TK_AsIs;
}
private:
diff --git a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
index 26f9d9f16ac8c..12fa030fc0af2 100644
--- a/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
+++ b/clang-tools-extra/test/clang-tidy/checkers/readability/container-data-pointer.cpp
@@ -156,3 +156,12 @@ void s(std::unique_ptr<std::vector<unsigned char>> p) {
// CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
// CHECK-FIXES: f((*p).data());
}
+
+template <typename Cont>
+void u(std::unique_ptr<Cont> p) {
+ f(&(*p)[0]);
+ // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: 'data' should be used for accessing the data pointer instead of taking the address of the 0-th element [readability-container-data-pointer]
+ // CHECK-FIXES: f((*p).data());
+}
+
+template void u<std::vector<int>>(std::unique_ptr<std::vector<int>>);
More information about the cfe-commits
mailing list