[clang] [WebKit checkers] Treat function pointers with "Singleton" suffix as singleton. (PR #158012)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 12 12:40:30 PDT 2025
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/158012
>From a15b50ae7a6099db0a8919c5280820acd4c7051c Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Thu, 11 Sep 2025 01:23:50 -0700
Subject: [PATCH 1/3] [WebKit checkers] Treat function pointers with
"Singleton" suffix as singleton.
---
clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp | 5 +++++
.../Checkers/WebKit/PtrTypesSemantics.cpp | 2 +-
.../Checkers/WebKit/PtrTypesSemantics.h | 3 ++-
.../Analysis/Checkers/WebKit/unretained-call-args.mm | 11 +++++++++++
4 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 478bd85177143..e851d0834226c 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -153,6 +153,11 @@ bool tryToFindPtrOrigin(
if (Name == "__builtin___CFStringMakeConstantString" ||
Name == "NSClassFromString")
return callback(E, true);
+ } else if (auto* CalleeE = call->getCallee()) {
+ if (auto *E = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
+ if (isSingleton(E->getFoundDecl()))
+ return callback(E, true);
+ }
}
}
if (auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E)) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 36c12582a5787..e86859a6aa56d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -479,7 +479,7 @@ bool isTrivialBuiltinFunction(const FunctionDecl *F) {
Name.starts_with("os_log") || Name.starts_with("_os_log");
}
-bool isSingleton(const FunctionDecl *F) {
+bool isSingleton(const NamedDecl *F) {
assert(F);
// FIXME: check # of params == 1
if (auto *MethodDecl = dyn_cast<CXXMethodDecl>(F)) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index 3c9560cb8059b..d2095d07e1434 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -21,6 +21,7 @@ class CXXMethodDecl;
class CXXRecordDecl;
class Decl;
class FunctionDecl;
+class NamedDecl;
class QualType;
class RecordType;
class Stmt;
@@ -156,7 +157,7 @@ bool isPtrConversion(const FunctionDecl *F);
bool isTrivialBuiltinFunction(const FunctionDecl *F);
/// \returns true if \p F is a static singleton function.
-bool isSingleton(const FunctionDecl *F);
+bool isSingleton(const NamedDecl *F);
/// An inter-procedural analysis facility that detects functions with "trivial"
/// behavior with respect to reference counting, such as simple field getters.
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index c69113c48806d..b9010d2be9162 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -438,6 +438,17 @@ void use_const_local() {
} // namespace const_global
+namespace var_decl_ref_singleton {
+
+static Class initSomeObject() { return nil; }
+static Class (*getSomeObjectClassSingleton)() = initSomeObject;
+
+bool foo(NSString *obj) {
+ return [obj isKindOfClass:getSomeObjectClassSingleton()];
+}
+
+} // namespace var_decl_ref_singleton
+
@interface TestObject : NSObject
- (void)doWork:(NSString *)msg, ...;
- (void)doWorkOnSelf;
>From a80026a262520b211158091d8566deac3d33437c Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Thu, 11 Sep 2025 01:30:56 -0700
Subject: [PATCH 2/3] Fix formatting
---
clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index e851d0834226c..f63adac7ff85e 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -153,7 +153,7 @@ bool tryToFindPtrOrigin(
if (Name == "__builtin___CFStringMakeConstantString" ||
Name == "NSClassFromString")
return callback(E, true);
- } else if (auto* CalleeE = call->getCallee()) {
+ } else if (auto *CalleeE = call->getCallee()) {
if (auto *E = dyn_cast<DeclRefExpr>(CalleeE->IgnoreParenCasts())) {
if (isSingleton(E->getFoundDecl()))
return callback(E, true);
>From 8f38c8b37d5207b317da2d351523f68edc6e0211 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Fri, 12 Sep 2025 12:40:12 -0700
Subject: [PATCH 3/3] Add test cases for a member function pointer and a
pointer to static member function. The former should always emit a warning
since we only allow static member function to return a singleton.
---
.../Checkers/WebKit/unretained-call-args.mm | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index b9010d2be9162..28a8964c8a06f 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -447,6 +447,23 @@ bool foo(NSString *obj) {
return [obj isKindOfClass:getSomeObjectClassSingleton()];
}
+class Bar {
+public:
+ Class someObject();
+ static Class staticSomeObject();
+};
+typedef Class (Bar::*SomeObjectSingleton)();
+
+bool bar(NSObject *obj, Bar *bar, SomeObjectSingleton someObjSingleton) {
+ return [obj isKindOfClass:(bar->*someObjSingleton)()];
+ // expected-warning at -1{{Call argument for parameter 'aClass' is unretained and unsafe}}
+}
+
+bool baz(NSObject *obj) {
+ Class (*someObjectSingleton)() = Bar::staticSomeObject;
+ return [obj isKindOfClass:someObjectSingleton()];
+}
+
} // namespace var_decl_ref_singleton
@interface TestObject : NSObject
More information about the cfe-commits
mailing list