https://github.com/rniwa updated https://github.com/llvm/llvm-project/pull/159947
>From e369e9c9c390191bb8ac0fb5cc80ebe4e22e290a Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <[email protected]> Date: Sat, 20 Sep 2025 14:07:19 -0700 Subject: [PATCH 1/3] [alpha.webkit.NoUnretainedMemberChecker] Only check @property when @implementation is seen A @interface declaration with a raw pointer @property does not necessarily mean it synthesizes ivar of that type. To determine whether such a synthesis happens or not, we must wait for @implementation to appear. So this PR makes the checker only validate @property then. --- .../WebKit/RawPtrRefMemberChecker.cpp | 19 +++++++++---------- .../Checkers/WebKit/unretained-members-arc.mm | 15 +++++++++++++++ .../Checkers/WebKit/unretained-members.mm | 15 +++++++++++++++ 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp index 8faf6a219450a..baafc1bc61c15 100644 --- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp @@ -129,17 +129,16 @@ class RawPtrRefMemberChecker 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); - return; - } if (auto *ID = dyn_cast<ObjCImplementationDecl>(CD)) { + ObjCContainerDecl::PropertyMap map; + CD->collectPropertiesToImplement(map); + for (auto it : map) + visitObjCPropertyDecl(CD, it.second); + + if (auto *Interface = ID->getClassInterface()) { + for (auto *Ivar : Interface->ivars()) + visitIvarDecl(CD, Ivar); + } for (auto *PropImpl : ID->property_impls()) visitPropImpl(CD, PropImpl); for (auto *Ivar : ID->ivars()) diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm index 00e6e6ec1dcfa..daa0c222251d9 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm @@ -76,6 +76,21 @@ @interface AnotherObject : NSObject { @property(nonatomic, unsafe_unretained) NSString *prop_string3; // expected-warning@-1{{Property 'prop_string3' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}} @property(nonatomic, readonly) NSString *prop_string4; +@property(nonatomic, readonly) NSString *prop_safe; +@end + +@implementation AnotherObject +- (NSString *)prop_safe { + return nil; +} +@end + +// No warnings for @interface declaration itself. +@interface InterfaceOnlyObject : NSObject +@property(nonatomic, strong) NSString *prop_string1; +@property(nonatomic, assign) NSString *prop_string2; +@property(nonatomic, unsafe_unretained) NSString *prop_string3; +@property(nonatomic, readonly) NSString *prop_string4; @end NS_REQUIRES_PROPERTY_DEFINITIONS diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm index 46f65dfa603ad..800d882f79696 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm @@ -98,6 +98,21 @@ @interface AnotherObject : NSObject { } @property(nonatomic, strong) NSString *prop_string; // expected-warning@-1{{Property 'prop_string' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}} +@property(nonatomic, readonly) NSString *prop_safe; +@end + +@implementation AnotherObject +- (NSString *)prop_safe { + return nil; +} +@end + +// No warnings for @interface declaration itself. +@interface InterfaceOnlyObject : NSObject +@property(nonatomic, strong) NSString *prop_string1; +@property(nonatomic, assign) NSString *prop_string2; +@property(nonatomic, unsafe_unretained) NSString *prop_string3; +@property(nonatomic, readonly) NSString *prop_string4; @end NS_REQUIRES_PROPERTY_DEFINITIONS >From 6d70f15b25b2b61d3bb0cf41a0b8a8ba2914315c Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <[email protected]> Date: Tue, 23 Sep 2025 23:29:43 -0700 Subject: [PATCH 2/3] Add test cases for inherited interfaces --- .../Checkers/WebKit/unretained-members.mm | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm index 56fae675c3e96..7b66aa9332a85 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm @@ -112,7 +112,7 @@ @interface AnotherObject : NSObject { dispatch_queue_t dispatch; // expected-warning@-1{{Instance variable 'dispatch' in 'AnotherObject' is a retainable type 'dispatch_queue_t'}} } -@property(nonatomic, strong) NSString *prop_string; +@property(nonatomic, readonly, strong) NSString *prop_string; // expected-warning@-1{{Property 'prop_string' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}} @property(nonatomic, readonly) NSString *prop_safe; @end @@ -123,13 +123,31 @@ - (NSString *)prop_safe { } @end +@interface DerivedObject : AnotherObject { + NSNumber *ns_number; + // expected-warning@-1{{Instance variable 'ns_number' in 'DerivedObject' is a raw pointer to retainable type 'NSNumber'}} + CGImageRef cg_image; + // expected-warning@-1{{Instance variable 'cg_image' in 'DerivedObject' is a retainable type 'CGImageRef'}} + dispatch_queue_t os_dispatch; + // expected-warning@-1{{Instance variable 'os_dispatch' in 'DerivedObject' is a retainable type 'dispatch_queue_t'}} +} +@property(nonatomic, strong) NSNumber *prop_number; +// expected-warning@-1{{Property 'prop_number' in 'DerivedObject' is a raw pointer to retainable type 'NSNumber'; member variables must be a RetainPtr}} +@property(nonatomic, readonly) NSString *prop_string; +@end + +@implementation DerivedObject +- (NSString *)prop_string { + return nil; +} +@end + // No warnings for @interface declaration itself. @interface InterfaceOnlyObject : NSObject @property(nonatomic, strong) NSString *prop_string1; @property(nonatomic, assign) NSString *prop_string2; @property(nonatomic, unsafe_unretained) NSString *prop_string3; @property(nonatomic, readonly) NSString *prop_string4; - @end NS_REQUIRES_PROPERTY_DEFINITIONS >From c4bd06b68299cf142a4750ed0667179754ab0a7f Mon Sep 17 00:00:00 2001 From: Ryosuke Niwa <[email protected]> Date: Wed, 24 Sep 2025 19:03:03 -0700 Subject: [PATCH 3/3] Add a test case for a subclass interface with implementation --- .../Checkers/WebKit/unretained-members.mm | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm index 7b66aa9332a85..adf1d8aef9d7d 100644 --- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm +++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm @@ -150,6 +150,23 @@ @interface InterfaceOnlyObject : NSObject @property(nonatomic, readonly) NSString *prop_string4; @end +@interface InterfaceOnlyObject2 : NSObject +@property(nonatomic, strong) NSString *prop_string1; +@property(nonatomic, assign) NSString *prop_string2; +@property(nonatomic, unsafe_unretained) NSString *prop_string3; +// expected-warning@-1{{Property 'prop_string3' in 'DerivedObject2' is a raw pointer to retainable type 'NSString'}} +@property(nonatomic, readonly) NSString *prop_string4; +@end + +@interface DerivedObject2 : InterfaceOnlyObject2 +@property(nonatomic, readonly) NSString *prop_string5; +// expected-warning@-1{{Property 'prop_string5' in 'DerivedObject2' is a raw pointer to retainable type 'NSString'}} +@end + +@implementation DerivedObject2 +@synthesize prop_string3; +@end + NS_REQUIRES_PROPERTY_DEFINITIONS @interface NoSynthObject : NSObject { NSString *ns_string; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
