[clang] [alpha.webkit.UncountedCallArgsChecker] Allow protector functions in Objective-C++ (PR #108184)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 11 10:10:56 PDT 2024
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/108184
>From c8cd18baa5b285262905ad0d8c49ba102993ef1e Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Wed, 11 Sep 2024 03:14:31 -0700
Subject: [PATCH 1/3] [alpha.webkit.UncountedCallArgsChecker] Allow protector
functions in Objective-C++
This PR fixes the bug that WebKit checkers didn't recognize the return value of
an Objective-C++ selector which returns Ref or RefPtr to be safe.
---
.../Checkers/WebKit/PtrTypesSemantics.cpp | 11 ++++++++
.../Checkers/WebKit/PtrTypesSemantics.h | 5 ++++
.../WebKit/UncountedCallArgsChecker.cpp | 3 +--
.../Checkers/WebKit/uncounted-obj-arg.mm | 26 +++++++++++++++++++
4 files changed, 43 insertions(+), 2 deletions(-)
create mode 100644 clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 49bbff1942167b..5a484d0546e95f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -143,6 +143,17 @@ bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
return false;
}
+std::optional<bool> isUncounted(const clang::QualType T)
+{
+ if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
+ if (auto *Decl = Subst->getAssociatedDecl()) {
+ if (isRefType(safeGetName(Decl)))
+ return false;
+ }
+ }
+ return isUncounted(T->getAsCXXRecordDecl());
+}
+
std::optional<bool> isUncounted(const CXXRecordDecl* Class)
{
// Keep isRefCounted first as it's cheaper.
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index ec1db1cc335807..2932e62ad06e4b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -20,6 +20,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class Decl;
class FunctionDecl;
+class QualType;
class Stmt;
class Type;
@@ -42,6 +43,10 @@ std::optional<bool> isRefCountable(const clang::CXXRecordDecl* Class);
/// \returns true if \p Class is ref-counted, false if not.
bool isRefCounted(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);
+
/// \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::CXXRecordDecl* Class);
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
index 704c082a4d1d63..81c2434ce64775 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/UncountedCallArgsChecker.cpp
@@ -87,8 +87,7 @@ class UncountedCallArgsChecker
}
auto *E = MemberCallExpr->getImplicitObjectArgument();
QualType ArgType = MemberCallExpr->getObjectType();
- std::optional<bool> IsUncounted =
- isUncounted(ArgType->getAsCXXRecordDecl());
+ std::optional<bool> IsUncounted = isUncounted(ArgType);
if (IsUncounted && *IsUncounted && !isPtrOriginSafe(E))
reportBugOnThis(E);
}
diff --git a/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
new file mode 100644
index 00000000000000..db0c5b19eec5bb
--- /dev/null
+++ b/clang/test/Analysis/Checkers/WebKit/uncounted-obj-arg.mm
@@ -0,0 +1,26 @@
+// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.UncountedCallArgsChecker -verify %s
+// expected-no-diagnostics
+
+#import "mock-types.h"
+#import "mock-system-header.h"
+#import "../../Inputs/system-header-simulator-for-objc-dealloc.h"
+
+ at interface Foo : NSObject
+
+ at property (nonatomic, readonly) RefPtr<RefCountable> countable;
+
+- (void)execute;
+- (RefPtr<RefCountable>)_protectedRefCountable;
+ at end
+
+ at implementation Foo
+
+- (void)execute {
+ self._protectedRefCountable->method();
+}
+
+- (RefPtr<RefCountable>)_protectedRefCountable {
+ return _countable;
+}
+
+ at end
>From a598a8f2661bdd6163e2dddbeccb3bbada67ea16 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Wed, 11 Sep 2024 09:32:19 -0700
Subject: [PATCH 2/3] Fix formatting.
---
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 5a484d0546e95f..25aaa5c5fdd900 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -143,8 +143,7 @@ bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
return false;
}
-std::optional<bool> isUncounted(const clang::QualType T)
-{
+std::optional<bool> isUncounted(const clang::QualType T) {
if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
if (auto *Decl = Subst->getAssociatedDecl()) {
if (isRefType(safeGetName(Decl)))
>From a5754c3c5452611384871498ade54cb78d627625 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Wed, 11 Sep 2024 10:10:17 -0700
Subject: [PATCH 3/3] Remove redundant clang namespace qualifier.
---
clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 25aaa5c5fdd900..4a336ea0fe38c0 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -143,7 +143,7 @@ bool isReturnValueRefCounted(const clang::FunctionDecl *F) {
return false;
}
-std::optional<bool> isUncounted(const clang::QualType T) {
+std::optional<bool> isUncounted(const QualType T) {
if (auto *Subst = dyn_cast<SubstTemplateTypeParmType>(T)) {
if (auto *Decl = Subst->getAssociatedDecl()) {
if (isRefType(safeGetName(Decl)))
More information about the cfe-commits
mailing list