[clang] [alpha.webkit.RawPtrRefMemberChecker] The checker doesn't warn Objective-C types in ivars. (PR #132833)
Ryosuke Niwa via cfe-commits
cfe-commits at lists.llvm.org
Fri Mar 28 12:32:04 PDT 2025
https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/132833
>From ca50deea7d8096b065d2bf7aa5e007afc8f0a954 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Mon, 24 Mar 2025 14:22:28 -0700
Subject: [PATCH 1/4] [alpha.webkit.RawPtrRefMemberChecker] The checker doesn't
warn Objective-C types in ivars.
This PR fixes the bug that we weren't generating warnings when a raw poiner is used to
point to a NS type in Objective-C ivars. Also fix the bug that we weren't suppressing this
warning in system headers.
---
.../Checkers/WebKit/RawPtrRefMemberChecker.cpp | 10 ++++++++++
.../Analysis/Checkers/WebKit/mock-system-header.h | 11 +++++++++++
.../Analysis/Checkers/WebKit/unretained-members.mm | 12 +++++++++++-
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index dc4e2c7d168fb..6d20869043358 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -111,6 +111,8 @@ class RawPtrRefMemberChecker
}
void visitObjCDecl(const ObjCContainerDecl *CD) const {
+ if (BR->getSourceManager().isInSystemHeader(CD->getLocation()))
+ return;
if (auto *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
for (auto *Ivar : ID->ivars())
visitIvarDecl(CD, Ivar);
@@ -133,6 +135,14 @@ class RawPtrRefMemberChecker
std::optional<bool> IsCompatible = isPtrCompatible(QT, IvarCXXRD);
if (IsCompatible && *IsCompatible)
reportBug(Ivar, IvarType, IvarCXXRD, CD);
+ } else {
+ std::optional<bool> IsCompatible = isPtrCompatible(QT, nullptr);
+ auto *PointeeType = IvarType->getPointeeType().getTypePtrOrNull();
+ if (IsCompatible && *IsCompatible) {
+ auto *Desugared = PointeeType->getUnqualifiedDesugaredType();
+ if (auto *ObjCType = dyn_cast_or_null<ObjCInterfaceType>(Desugared))
+ reportBug(Ivar, IvarType, ObjCType->getDecl(), CD);
+ }
}
}
diff --git a/clang/test/Analysis/Checkers/WebKit/mock-system-header.h b/clang/test/Analysis/Checkers/WebKit/mock-system-header.h
index e993fd697ffab..b377f5098c002 100644
--- a/clang/test/Analysis/Checkers/WebKit/mock-system-header.h
+++ b/clang/test/Analysis/Checkers/WebKit/mock-system-header.h
@@ -29,3 +29,14 @@ enum os_log_type_t : uint8_t {
typedef struct os_log_s *os_log_t;
os_log_t os_log_create(const char *subsystem, const char *category);
void os_log_msg(os_log_t oslog, os_log_type_t type, const char *msg, ...);
+
+typedef const struct __attribute__((objc_bridge(NSString))) __CFString * CFStringRef;
+
+#ifdef __OBJC__
+ at class NSString;
+ at interface SystemObject : NSObject {
+ NSString *ns_string;
+ CFStringRef cf_string;
+}
+ at end
+#endif
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index e068a583c18c5..79f7a05caa1be 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -1,7 +1,8 @@
// RUN: %clang_analyze_cc1 -analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -verify %s
#include "objc-mock-types.h"
-
+#include "mock-system-header.h"
+#if 0
namespace members {
struct Foo {
@@ -58,3 +59,12 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, CFMutableArrayRef>) {}
void forceTmplToInstantiate(RefPtr<SomeObj>) {}
}
+#endif
+
+ at interface AnotherObject : NSObject {
+ NSString *ns_string;
+ // expected-warning at -1{{Instance variable 'ns_string' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}}
+ CFStringRef cf_string;
+ // expected-warning at -1{{Instance variable 'cf_string' in 'AnotherObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+ at end
>From d72d24363c7ba16463a1f5fe28442dd2740d2d95 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Mon, 24 Mar 2025 16:00:52 -0700
Subject: [PATCH 2/4] Revert erroneous #if 0 ~ #endif
---
clang/test/Analysis/Checkers/WebKit/unretained-members.mm | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index 79f7a05caa1be..483ce4e2763ea 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -2,7 +2,7 @@
#include "objc-mock-types.h"
#include "mock-system-header.h"
-#if 0
+
namespace members {
struct Foo {
@@ -59,7 +59,6 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, CFMutableArrayRef>) {}
void forceTmplToInstantiate(RefPtr<SomeObj>) {}
}
-#endif
@interface AnotherObject : NSObject {
NSString *ns_string;
>From c3796e7e626ee22f89f5b9d5850ed89a0f723c65 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Thu, 27 Mar 2025 15:42:46 -0700
Subject: [PATCH 3/4] Also add the support for detecting raw pointer property
with a test.
---
.../WebKit/RawPtrRefMemberChecker.cpp | 37 +++++++++++++++++--
.../Checkers/WebKit/unretained-members.mm | 2 +
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index 6d20869043358..adcf9fce83b90 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -113,6 +113,12 @@ class RawPtrRefMemberChecker
void visitObjCDecl(const ObjCContainerDecl *CD) const {
if (BR->getSourceManager().isInSystemHeader(CD->getLocation()))
return;
+
+ ObjCContainerDecl::PropertyMap map;
+ CD->collectPropertiesToImplement(map);
+ for (auto it : map)
+ visitObjCPropertyDecl(CD, it.second);
+
if (auto *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
for (auto *Ivar : ID->ivars())
visitIvarDecl(CD, Ivar);
@@ -146,6 +152,28 @@ class RawPtrRefMemberChecker
}
}
+ void visitObjCPropertyDecl(const ObjCContainerDecl *CD,
+ const ObjCPropertyDecl *PD) const {
+ auto QT = PD->getType();
+ const Type *PropType = QT.getTypePtrOrNull();
+ if (!PropType)
+ return;
+ if (auto *PropCXXRD = PropType->getPointeeCXXRecordDecl()) {
+ std::optional<bool> IsCompatible = isPtrCompatible(QT, PropCXXRD);
+ fprintf(stderr, "IsCompatible=%d\n", IsCompatible ? *IsCompatible : -1);
+ if (IsCompatible && *IsCompatible)
+ reportBug(PD, PropType, PropCXXRD, CD);
+ } else {
+ std::optional<bool> IsCompatible = isPtrCompatible(QT, nullptr);
+ auto *PointeeType = PropType->getPointeeType().getTypePtrOrNull();
+ if (IsCompatible && *IsCompatible) {
+ auto *Desugared = PointeeType->getUnqualifiedDesugaredType();
+ if (auto *ObjCType = dyn_cast_or_null<ObjCInterfaceType>(Desugared))
+ reportBug(PD, PropType, ObjCType->getDecl(), CD);
+ }
+ }
+ }
+
bool shouldSkipDecl(const RecordDecl *RD) const {
if (!RD->isThisDeclarationADefinition())
return true;
@@ -191,9 +219,12 @@ class RawPtrRefMemberChecker
SmallString<100> Buf;
llvm::raw_svector_ostream Os(Buf);
- if (isa<ObjCContainerDecl>(ClassCXXRD))
- Os << "Instance variable ";
- else
+ if (isa<ObjCContainerDecl>(ClassCXXRD)) {
+ if (isa<ObjCPropertyDecl>(Member))
+ Os << "Property ";
+ else
+ Os << "Instance variable ";
+ } else
Os << "Member variable ";
printQuotedName(Os, Member);
Os << " in ";
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index 483ce4e2763ea..92d70a94427c0 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -66,4 +66,6 @@ @interface AnotherObject : NSObject {
CFStringRef cf_string;
// expected-warning at -1{{Instance variable 'cf_string' in 'AnotherObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
}
+ at property(nonatomic, strong) NSString *prop_string;
+// expected-warning at -1{{Property 'prop_string' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}}
@end
>From a46ce85a481b353bf7d89cc27ab09e82cf74eef2 Mon Sep 17 00:00:00 2001
From: Ryosuke Niwa <rniwa at webkit.org>
Date: Fri, 28 Mar 2025 12:31:47 -0700
Subject: [PATCH 4/4] Remove fprintf logging for debugging purposes
---
.../StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index adcf9fce83b90..89df1a725ab92 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -160,7 +160,6 @@ class RawPtrRefMemberChecker
return;
if (auto *PropCXXRD = PropType->getPointeeCXXRecordDecl()) {
std::optional<bool> IsCompatible = isPtrCompatible(QT, PropCXXRD);
- fprintf(stderr, "IsCompatible=%d\n", IsCompatible ? *IsCompatible : -1);
if (IsCompatible && *IsCompatible)
reportBug(PD, PropType, PropCXXRD, CD);
} else {
More information about the cfe-commits
mailing list