[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)
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)
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)
@@ -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)
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 = - [&AnyInconclusiveBase](const CXXBaseSpecifier* Base, CXXBasePath&) { - std::optional IsRefCountable = clang::isRefCountable(Base); - if (!IsRefCountable) { - AnyInconclusiveBase = true; - return false; - } - return (*IsRefCountable) != nullptr; + const auto hasPublicRefInBase = + [&AnyInconclusiveBase](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 = + [&AnyInconclusiveBase](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/WebK
[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)
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)
@@ -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)
@@ -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)
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)
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)
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)
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 = - [&AnyInconclusiveBase](const CXXBaseSpecifier* Base, CXXBasePath&) { - std::optional IsRefCountable = clang::isRefCountable(Base); - if (!IsRefCountable) { - AnyInconclusiveBase = true; - return false; - } - return (*IsRefCountable) != nullptr; + const auto hasPublicRefInBase = + [&AnyInconclusiveBase](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 = + [&AnyInconclusiveBase](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/WebK
[clang] Fix WebKit static analyzers to support ref and deref methods to be defined on different classes. (PR #69985)
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 = - [&AnyInconclusiveBase](const CXXBaseSpecifier *Base, - CXXBasePath &) { -auto hasDerefInBase = clang::hasPublicMethodInBase(Base, "deref"); -if (!hasDerefInBase) { - AnyInconclusiveBase = true; - return false; -} -return (*hasDerefInBase) != nullptr; - }; + const auto hasPublicDerefInBase = [&AnyInconclusiveBase]( +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)
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 = - [&AnyInconclusiveBase](const CXXBaseSpecifier* Base, CXXBasePath&) { - std::optional IsRefCountable = clang::isRefCountable(Base); - if (!IsRefCountable) { - AnyInconclusiveBase = true; - return false; - } - return (*IsRefCountable) != nullptr; + const auto hasPublicRefInBase = + [&AnyInconclusiveBase](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 = + [&AnyInconclusiveBase](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 @@