[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-10 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ closed https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Ryosuke Niwa via cfe-commits

rniwa wrote:

Yes, it would be great if you can merge the change now that I've addressed your 
nits.

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Ryosuke Niwa via cfe-commits


@@ -77,14 +77,53 @@ class RefCntblBaseVirtualDtorChecker
   (AccSpec == AS_none && RD->isClass()))
 return false;
 
-  std::optional RefCntblBaseRD = 
isRefCountable(Base);
-  if (!RefCntblBaseRD || !(*RefCntblBaseRD))
+  auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");
+  auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+
+  bool hasRef = hasRefInBase && *hasRefInBase != nullptr;
+  bool hasDeref = hasDerefInBase && *hasDerefInBase != nullptr;
+
+  const Type *T = Base->getType().getTypePtrOrNull();
+  if (!T)
+return false;
+
+  const CXXRecordDecl *C = T->getAsCXXRecordDecl();

rniwa wrote:

Fixed.

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/69985

>From bf169f3d79f8a5b0658d9e060ddd6c3e773b979a Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Mon, 23 Oct 2023 16:38:10 -0700
Subject: [PATCH] Fix WebKit static analyzers to support ref and deref methods
 to be defined on different classes.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 62 ++-
 .../Checkers/WebKit/PtrTypesSemantics.h   |  8 +--
 .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 47 --
 ...virtual-dtor-ref-deref-on-diff-classes.cpp | 22 +++
 ...nted-members-ref-deref-on-diff-classes.cpp | 23 +++
 5 files changed, 126 insertions(+), 36 deletions(-)
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/ref-cntbl-base-virtual-dtor-ref-deref-on-diff-classes.cpp
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/uncounted-members-ref-deref-on-diff-classes.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index c1f180f31338cb3..d2b663410580008 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -18,24 +18,15 @@ using namespace clang;
 
 namespace {
 
-bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
+bool hasPublicMethodInBaseClass(const CXXRecordDecl *R,
+const char *NameToMatch) {
   assert(R);
   assert(R->hasDefinition());
 
-  bool hasRef = false;
-  bool hasDeref = false;
   for (const CXXMethodDecl *MD : R->methods()) {
 const auto MethodName = safeGetName(MD);
-
-if (MethodName == "ref" && MD->getAccess() == AS_public) {
-  if (hasDeref)
-return true;
-  hasRef = true;
-} else if (MethodName == "deref" && MD->getAccess() == AS_public) {
-  if (hasRef)
-return true;
-  hasDeref = true;
-}
+if (MethodName == NameToMatch && MD->getAccess() == AS_public)
+  return true;
   }
   return false;
 }
@@ -44,9 +35,8 @@ bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
 
 namespace clang {
 
-std::optional
-isRefCountable(const CXXBaseSpecifier* Base)
-{
+std::optional
+hasPublicMethodInBase(const CXXBaseSpecifier *Base, const char *NameToMatch) {
   assert(Base);
 
   const Type *T = Base->getType().getTypePtrOrNull();
@@ -59,7 +49,7 @@ isRefCountable(const CXXBaseSpecifier* Base)
   if (!R->hasDefinition())
 return std::nullopt;
 
-  return hasPublicRefAndDeref(R) ? R : nullptr;
+  return hasPublicMethodInBaseClass(R, NameToMatch) ? R : nullptr;
 }
 
 std::optional isRefCountable(const CXXRecordDecl* R)
@@ -70,29 +60,45 @@ std::optional isRefCountable(const CXXRecordDecl* R)
   if (!R)
 return std::nullopt;
 
-  if (hasPublicRefAndDeref(R))
+  bool hasRef = hasPublicMethodInBaseClass(R, "ref");
+  bool hasDeref = hasPublicMethodInBaseClass(R, "deref");
+  if (hasRef && hasDeref)
 return true;
 
   CXXBasePaths Paths;
   Paths.setOrigin(const_cast(R));
 
   bool AnyInconclusiveBase = false;
-  const auto isRefCountableBase =
-  [](const CXXBaseSpecifier* Base, CXXBasePath&) {
-  std::optional IsRefCountable = 
clang::isRefCountable(Base);
-  if (!IsRefCountable) {
-  AnyInconclusiveBase = true;
-  return false;
-  }
-  return (*IsRefCountable) != nullptr;
+  const auto hasPublicRefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");
+if (!hasRefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasRefInBase) != nullptr;
   };
 
-  bool BasesResult = R->lookupInBases(isRefCountableBase, Paths,
+  hasRef = hasRef || R->lookupInBases(hasPublicRefInBase, Paths,
   /*LookupInDependent =*/true);
   if (AnyInconclusiveBase)
 return std::nullopt;
 
-  return BasesResult;
+  const auto hasPublicDerefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+if (!hasDerefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasDerefInBase) != nullptr;
+  };
+  hasDeref = hasDeref || R->lookupInBases(hasPublicDerefInBase, Paths,
+  /*LookupInDependent =*/true);
+  if (AnyInconclusiveBase)
+return std::nullopt;
+
+  return hasRef && hasDeref;
 }
 
 bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 91e3ccf2ec3047e..45b21cc0918443b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -26,10 +26,10 @@ class Type;
 // 

[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits

haoNoQ wrote:

(You still need me to merge right? You can ask me to merge, or you can address 
nitpicks and then ask me to merge, or you can go through 
https://llvm.org/docs/DeveloperPolicy.html#obtaining-commit-access and merge 
yourself!)

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits


@@ -77,14 +77,53 @@ class RefCntblBaseVirtualDtorChecker
   (AccSpec == AS_none && RD->isClass()))
 return false;
 
-  std::optional RefCntblBaseRD = 
isRefCountable(Base);
-  if (!RefCntblBaseRD || !(*RefCntblBaseRD))
+  auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");
+  auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+
+  bool hasRef = hasRefInBase && *hasRefInBase != nullptr;
+  bool hasDeref = hasDerefInBase && *hasDerefInBase != nullptr;
+
+  const Type *T = Base->getType().getTypePtrOrNull();
+  if (!T)
+return false;
+
+  const CXXRecordDecl *C = T->getAsCXXRecordDecl();

haoNoQ wrote:

`.getTypePtrOrNull()` is typically unnecessary, most of the code can use the 
overloaded `QualType::operator->()` to access the underlying `Type`:

QualType T = Base->getType();
if (T.isNull())
  return false;

const CXXRecordDecl *C = T->getAsCXXRecordDecl();

etc.

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits


@@ -77,14 +77,53 @@ class RefCntblBaseVirtualDtorChecker
   (AccSpec == AS_none && RD->isClass()))
 return false;
 
-  std::optional RefCntblBaseRD = 
isRefCountable(Base);
-  if (!RefCntblBaseRD || !(*RefCntblBaseRD))
+  auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");

haoNoQ wrote:

I wonder if this entire new section can be deduplicated with `isRefCountable()` 
in the other file. They look so similar!

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ approved this pull request.


https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits

https://github.com/haoNoQ edited https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-11-09 Thread Artem Dergachev via cfe-commits

haoNoQ wrote:

LGTM, thanks!! I have a couple nitpicks but I don't think they should block 
your progress.

https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-10-23 Thread Ryosuke Niwa via cfe-commits

https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/69985

>From 1832737f3e198386d1ebdeccd7d0ca55ef6094c0 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Mon, 23 Oct 2023 16:38:10 -0700
Subject: [PATCH] Fix WebKit static analyzers to support ref and deref methods
 to be defined on different classes.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 62 ++-
 .../Checkers/WebKit/PtrTypesSemantics.h   |  8 +--
 .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 47 --
 ...virtual-dtor-ref-deref-on-diff-classes.cpp | 22 +++
 ...nted-members-ref-deref-on-diff-classes.cpp | 23 +++
 5 files changed, 126 insertions(+), 36 deletions(-)
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/ref-cntbl-base-virtual-dtor-ref-deref-on-diff-classes.cpp
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/uncounted-members-ref-deref-on-diff-classes.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index c1f180f31338cb3..d2b663410580008 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -18,24 +18,15 @@ using namespace clang;
 
 namespace {
 
-bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
+bool hasPublicMethodInBaseClass(const CXXRecordDecl *R,
+const char *NameToMatch) {
   assert(R);
   assert(R->hasDefinition());
 
-  bool hasRef = false;
-  bool hasDeref = false;
   for (const CXXMethodDecl *MD : R->methods()) {
 const auto MethodName = safeGetName(MD);
-
-if (MethodName == "ref" && MD->getAccess() == AS_public) {
-  if (hasDeref)
-return true;
-  hasRef = true;
-} else if (MethodName == "deref" && MD->getAccess() == AS_public) {
-  if (hasRef)
-return true;
-  hasDeref = true;
-}
+if (MethodName == NameToMatch && MD->getAccess() == AS_public)
+  return true;
   }
   return false;
 }
@@ -44,9 +35,8 @@ bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
 
 namespace clang {
 
-std::optional
-isRefCountable(const CXXBaseSpecifier* Base)
-{
+std::optional
+hasPublicMethodInBase(const CXXBaseSpecifier *Base, const char *NameToMatch) {
   assert(Base);
 
   const Type *T = Base->getType().getTypePtrOrNull();
@@ -59,7 +49,7 @@ isRefCountable(const CXXBaseSpecifier* Base)
   if (!R->hasDefinition())
 return std::nullopt;
 
-  return hasPublicRefAndDeref(R) ? R : nullptr;
+  return hasPublicMethodInBaseClass(R, NameToMatch) ? R : nullptr;
 }
 
 std::optional isRefCountable(const CXXRecordDecl* R)
@@ -70,29 +60,45 @@ std::optional isRefCountable(const CXXRecordDecl* R)
   if (!R)
 return std::nullopt;
 
-  if (hasPublicRefAndDeref(R))
+  bool hasRef = hasPublicMethodInBaseClass(R, "ref");
+  bool hasDeref = hasPublicMethodInBaseClass(R, "deref");
+  if (hasRef && hasDeref)
 return true;
 
   CXXBasePaths Paths;
   Paths.setOrigin(const_cast(R));
 
   bool AnyInconclusiveBase = false;
-  const auto isRefCountableBase =
-  [](const CXXBaseSpecifier* Base, CXXBasePath&) {
-  std::optional IsRefCountable = 
clang::isRefCountable(Base);
-  if (!IsRefCountable) {
-  AnyInconclusiveBase = true;
-  return false;
-  }
-  return (*IsRefCountable) != nullptr;
+  const auto hasPublicRefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");
+if (!hasRefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasRefInBase) != nullptr;
   };
 
-  bool BasesResult = R->lookupInBases(isRefCountableBase, Paths,
+  hasRef = hasRef || R->lookupInBases(hasPublicRefInBase, Paths,
   /*LookupInDependent =*/true);
   if (AnyInconclusiveBase)
 return std::nullopt;
 
-  return BasesResult;
+  const auto hasPublicDerefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+if (!hasDerefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasDerefInBase) != nullptr;
+  };
+  hasDeref = hasDeref || R->lookupInBases(hasPublicDerefInBase, Paths,
+  /*LookupInDependent =*/true);
+  if (AnyInconclusiveBase)
+return std::nullopt;
+
+  return hasRef && hasDeref;
 }
 
 bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 91e3ccf2ec3047e..45b21cc0918443b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -26,10 +26,10 @@ class Type;
 // 

[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-10-23 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff e45356910f826194003e9bd62a2406971b2fe3f3 
d8236358e137967dbbd63606b7d43983709597e8 -- 
clang/test/Analysis/Checkers/WebKit/ref-cntbl-base-virtual-dtor-ref-deref-on-diff-classes.cpp
 
clang/test/Analysis/Checkers/WebKit/uncounted-members-ref-deref-on-diff-classes.cpp
 clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h 
clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 8c7eaa3b9a53..d2b663410580 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -18,7 +18,8 @@ using namespace clang;
 
 namespace {
 
-bool hasPublicMethodInBaseClass(const CXXRecordDecl *R, const char* 
NameToMatch) {
+bool hasPublicMethodInBaseClass(const CXXRecordDecl *R,
+const char *NameToMatch) {
   assert(R);
   assert(R->hasDefinition());
 
diff --git 
a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
index bf54bb40c23c..c32e20f9a03b 100644
--- 
a/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
+++ 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/RefCntblBaseVirtualDtorChecker.cpp
@@ -101,16 +101,16 @@ public:
 }
 return (*hasRefInBase) != nullptr;
   };
-  const auto hasPublicDerefInBase =
-  [](const CXXBaseSpecifier *Base,
- CXXBasePath &) {
-auto hasDerefInBase = clang::hasPublicMethodInBase(Base, 
"deref");
-if (!hasDerefInBase) {
-  AnyInconclusiveBase = true;
-  return false;
-}
-return (*hasDerefInBase) != nullptr;
-  };
+  const auto hasPublicDerefInBase = [](
+const CXXBaseSpecifier *Base,
+CXXBasePath &) {
+auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+if (!hasDerefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasDerefInBase) != nullptr;
+  };
   CXXBasePaths Paths;
   Paths.setOrigin(C);
   hasRef = hasRef || C->lookupInBases(hasPublicRefInBase, Paths,

``




https://github.com/llvm/llvm-project/pull/69985
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)

2023-10-23 Thread Ryosuke Niwa via cfe-commits

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

None

>From d8236358e137967dbbd63606b7d43983709597e8 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa 
Date: Mon, 23 Oct 2023 16:38:10 -0700
Subject: [PATCH] Fix WebKit static analyzers to support ref and deref methods
 to be defined on different classes.

---
 .../Checkers/WebKit/PtrTypesSemantics.cpp | 61 ++-
 .../Checkers/WebKit/PtrTypesSemantics.h   |  8 +--
 .../WebKit/RefCntblBaseVirtualDtorChecker.cpp | 47 --
 ...virtual-dtor-ref-deref-on-diff-classes.cpp | 22 +++
 ...nted-members-ref-deref-on-diff-classes.cpp | 23 +++
 5 files changed, 125 insertions(+), 36 deletions(-)
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/ref-cntbl-base-virtual-dtor-ref-deref-on-diff-classes.cpp
 create mode 100644 
clang/test/Analysis/Checkers/WebKit/uncounted-members-ref-deref-on-diff-classes.cpp

diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index c1f180f31338cb3..8c7eaa3b9a5369d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -18,24 +18,14 @@ using namespace clang;
 
 namespace {
 
-bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
+bool hasPublicMethodInBaseClass(const CXXRecordDecl *R, const char* 
NameToMatch) {
   assert(R);
   assert(R->hasDefinition());
 
-  bool hasRef = false;
-  bool hasDeref = false;
   for (const CXXMethodDecl *MD : R->methods()) {
 const auto MethodName = safeGetName(MD);
-
-if (MethodName == "ref" && MD->getAccess() == AS_public) {
-  if (hasDeref)
-return true;
-  hasRef = true;
-} else if (MethodName == "deref" && MD->getAccess() == AS_public) {
-  if (hasRef)
-return true;
-  hasDeref = true;
-}
+if (MethodName == NameToMatch && MD->getAccess() == AS_public)
+  return true;
   }
   return false;
 }
@@ -44,9 +34,8 @@ bool hasPublicRefAndDeref(const CXXRecordDecl *R) {
 
 namespace clang {
 
-std::optional
-isRefCountable(const CXXBaseSpecifier* Base)
-{
+std::optional
+hasPublicMethodInBase(const CXXBaseSpecifier *Base, const char *NameToMatch) {
   assert(Base);
 
   const Type *T = Base->getType().getTypePtrOrNull();
@@ -59,7 +48,7 @@ isRefCountable(const CXXBaseSpecifier* Base)
   if (!R->hasDefinition())
 return std::nullopt;
 
-  return hasPublicRefAndDeref(R) ? R : nullptr;
+  return hasPublicMethodInBaseClass(R, NameToMatch) ? R : nullptr;
 }
 
 std::optional isRefCountable(const CXXRecordDecl* R)
@@ -70,29 +59,45 @@ std::optional isRefCountable(const CXXRecordDecl* R)
   if (!R)
 return std::nullopt;
 
-  if (hasPublicRefAndDeref(R))
+  bool hasRef = hasPublicMethodInBaseClass(R, "ref");
+  bool hasDeref = hasPublicMethodInBaseClass(R, "deref");
+  if (hasRef && hasDeref)
 return true;
 
   CXXBasePaths Paths;
   Paths.setOrigin(const_cast(R));
 
   bool AnyInconclusiveBase = false;
-  const auto isRefCountableBase =
-  [](const CXXBaseSpecifier* Base, CXXBasePath&) {
-  std::optional IsRefCountable = 
clang::isRefCountable(Base);
-  if (!IsRefCountable) {
-  AnyInconclusiveBase = true;
-  return false;
-  }
-  return (*IsRefCountable) != nullptr;
+  const auto hasPublicRefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasRefInBase = clang::hasPublicMethodInBase(Base, "ref");
+if (!hasRefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasRefInBase) != nullptr;
   };
 
-  bool BasesResult = R->lookupInBases(isRefCountableBase, Paths,
+  hasRef = hasRef || R->lookupInBases(hasPublicRefInBase, Paths,
   /*LookupInDependent =*/true);
   if (AnyInconclusiveBase)
 return std::nullopt;
 
-  return BasesResult;
+  const auto hasPublicDerefInBase =
+  [](const CXXBaseSpecifier *Base, CXXBasePath &) {
+auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref");
+if (!hasDerefInBase) {
+  AnyInconclusiveBase = true;
+  return false;
+}
+return (*hasDerefInBase) != nullptr;
+  };
+  hasDeref = hasDeref || R->lookupInBases(hasPublicDerefInBase, Paths,
+  /*LookupInDependent =*/true);
+  if (AnyInconclusiveBase)
+return std::nullopt;
+
+  return hasRef && hasDeref;
 }
 
 bool isCtorOfRefCounted(const clang::FunctionDecl *F) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 91e3ccf2ec3047e..45b21cc0918443b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -26,10 +26,10 @@ class Type;
 // In WebKit there are two