[clang] [RawPtrRefMemberChecker] Member varible checker should allow T* in smart pointer classes (PR #136503)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Sun Apr 20 18:00:50 PDT 2025
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/136503
>From 01a0a5544010a605e828a28c04ba56d37658c6b0 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Sun, 20 Apr 2025 11:58:11 -0700
Subject: [PATCH] [RawPtrRefMemberChecker] Member variable checker should allow
T* in smart pointer classes
This PR fixes member variable checker to allow the usage of T* in smart pointer classes.
e.g. alpha.webkit.NoUncheckedPtrMemberChecker should allow T* to appear within RefPtr.
---
.../Checkers/WebKit/PtrTypesSemantics.cpp | 7 +++++++
.../Checkers/WebKit/PtrTypesSemantics.h | 4 ++++
.../Checkers/WebKit/RawPtrRefMemberChecker.cpp | 17 ++---------------
.../Checkers/WebKit/unchecked-members.cpp | 9 +++++++++
.../Checkers/WebKit/uncounted-members.cpp | 15 ++++++++++++---
5 files changed, 34 insertions(+), 18 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 811888e119449..ba0c7fd77b410 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -436,6 +436,13 @@ bool isRetainPtr(const CXXRecordDecl *R) {
return false;
}
+bool isSmartPtr(const CXXRecordDecl *R) {
+ assert(R);
+ if (auto *TmplR = R->getTemplateInstantiationPattern())
+ return isSmartPtrClass(safeGetName(TmplR));
+ return false;
+}
+
bool isPtrConversion(const FunctionDecl *F) {
assert(F);
if (isCtorOfRefCounted(F))
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 97c9d0510e67d..f9fcfe9878d54 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -58,6 +58,10 @@ bool isCheckedPtr(const clang::CXXRecordDecl *Class);
/// \returns true if \p Class is a RetainPtr, false if not.
bool isRetainPtr(const clang::CXXRecordDecl *Class);
+/// \returns true if \p Class is a smart pointer (RefPtr, WeakPtr, etc...),
+/// false if not.
+bool isSmartPtr(const clang::CXXRecordDecl *Class);
+
/// \returns true if \p Class is ref-countable AND not ref-counted, false if
/// not, std::nullopt if inconclusive.
std::optional<bool> isUncounted(const clang::QualType T);
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index a003fc200727c..10b9749319a57 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -41,7 +41,6 @@ class RawPtrRefMemberChecker
virtual std::optional<bool>
isPtrCompatible(const clang::QualType,
const clang::CXXRecordDecl *R) const = 0;
- virtual bool isPtrCls(const clang::CXXRecordDecl *) const = 0;
virtual const char *typeName() const = 0;
virtual const char *invariant() const = 0;
@@ -205,8 +204,8 @@ class RawPtrRefMemberChecker
// Ref-counted smartpointers actually have raw-pointer to uncounted type as
// a member but we trust them to handle it correctly.
auto CXXRD = llvm::dyn_cast_or_null<CXXRecordDecl>(RD);
- if (CXXRD)
- return isPtrCls(CXXRD);
+ if (CXXRD && isSmartPtr(CXXRD))
+ return true;
return false;
}
@@ -270,10 +269,6 @@ class NoUncountedMemberChecker final : public RawPtrRefMemberChecker {
return R ? isRefCountable(R) : std::nullopt;
}
- bool isPtrCls(const clang::CXXRecordDecl *R) const final {
- return isRefCounted(R);
- }
-
const char *typeName() const final { return "ref-countable type"; }
const char *invariant() const final {
@@ -293,10 +288,6 @@ class NoUncheckedPtrMemberChecker final : public RawPtrRefMemberChecker {
return R ? isCheckedPtrCapable(R) : std::nullopt;
}
- bool isPtrCls(const clang::CXXRecordDecl *R) const final {
- return isCheckedPtr(R);
- }
-
const char *typeName() const final { return "CheckedPtr capable type"; }
const char *invariant() const final {
@@ -319,10 +310,6 @@ class NoUnretainedMemberChecker final : public RawPtrRefMemberChecker {
return RTC->isUnretained(QT);
}
- bool isPtrCls(const clang::CXXRecordDecl *R) const final {
- return isRetainPtr(R);
- }
-
const char *typeName() const final { return "retainable type"; }
const char *invariant() const final {
diff --git a/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp b/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
index 0189b0cd50fcc..048ffbffcdefb 100644
--- a/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/unchecked-members.cpp
@@ -50,3 +50,12 @@ namespace ignore_unions {
void forceTmplToInstantiate(FooTmpl<CheckedObj>) { }
} // namespace ignore_unions
+
+namespace checked_ptr_ref_ptr_capable {
+
+ RefCountableAndCheckable* provide();
+ void foo() {
+ RefPtr<RefCountableAndCheckable> foo = provide();
+ }
+
+} // checked_ptr_ref_ptr_capable
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp b/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
index 1bdbaedefbfeb..130777a9a5fee 100644
--- a/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-members.cpp
@@ -34,7 +34,7 @@ namespace members {
private:
RefCountable* a = nullptr;
};
-}
+} // members
namespace ignore_unions {
union Foo {
@@ -49,7 +49,7 @@ namespace ignore_unions {
};
void forceTmplToInstantiate(RefPtr<RefCountable>) {}
-}
+} // ignore_unions
namespace ignore_system_header {
@@ -67,4 +67,13 @@ namespace ignore_non_ref_countable {
struct Bar {
Foo* foo;
};
-}
\ No newline at end of file
+} // ignore_non_ref_countable
+
+namespace checked_ptr_ref_ptr_capable {
+
+ RefCountableAndCheckable* provide();
+ void foo() {
+ CheckedPtr<RefCountableAndCheckable> foo = provide();
+ }
+
+} // checked_ptr_ref_ptr_capable
More information about the cfe-commits
mailing list