https://github.com/rniwa created 
https://github.com/llvm/llvm-project/pull/136503

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.

>From 441e1d80180549ff17eb74e3749bc6e5663c5c0f Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rn...@webkit.org>
Date: Sun, 20 Apr 2025 11:58:11 -0700
Subject: [PATCH] [RawPtrRefMemberChecker] Member varible 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

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to