Author: Ryosuke Niwa
Date: 2025-09-25T11:12:23-07:00
New Revision: 321a7c3caf7c5c6a208501e1406fcab14f8b54f9

URL: 
https://github.com/llvm/llvm-project/commit/321a7c3caf7c5c6a208501e1406fcab14f8b54f9
DIFF: 
https://github.com/llvm/llvm-project/commit/321a7c3caf7c5c6a208501e1406fcab14f8b54f9.diff

LOG: [alpha.webkit.NoUnretainedMemberChecker] Only check @property when 
@implementation is seen (#159947)

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.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
    clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
    clang/test/Analysis/Checkers/WebKit/unretained-members.mm

Removed: 
    


################################################################################
diff  --git 
a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index a97a37f85e96c..15a0c5a7fd9dc 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -130,17 +130,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 19c54c4dc07ba..4eef372d26480 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
@@ -84,6 +84,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;
 @property(nonatomic, readonly) dispatch_queue_t prop_string5;
 @end
 

diff  --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm 
b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index 155848f9834af..adf1d8aef9d7d 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -112,8 +112,59 @@ @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;
-// expected-warning@-1{{Property 'prop_string' in 'AnotherObject' is a raw 
pointer to retainable type 'NSString'}}
+@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
+
+@implementation AnotherObject
+- (NSString *)prop_safe {
+  return nil;
+}
+@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
+
+@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


        
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to