Author: Ryosuke Niwa
Date: 2025-03-28T17:34:51-07:00
New Revision: 304b3c500021a9281a1d03cf3a63380ca31f7451

URL: 
https://github.com/llvm/llvm-project/commit/304b3c500021a9281a1d03cf3a63380ca31f7451
DIFF: 
https://github.com/llvm/llvm-project/commit/304b3c500021a9281a1d03cf3a63380ca31f7451.diff

LOG: [alpha.webkit.RawPtrRefMemberChecker] The checker doesn't warn Objective-C 
types in ivars. (#132833)

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.

Added: 
    

Modified: 
    clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
    clang/test/Analysis/Checkers/WebKit/mock-system-header.h
    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 dc4e2c7d168fb..89df1a725ab92 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -111,6 +111,14 @@ 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);
@@ -133,6 +141,35 @@ 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);
+      }
+    }
+  }
+
+  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);
+      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);
+      }
     }
   }
 
@@ -181,9 +218,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/mock-system-header.h 
b/clang/test/Analysis/Checkers/WebKit/mock-system-header.h
index e993fd697ffab..450fb24687343 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__
+@class NSString;
+@interface SystemObject {
+  NSString *ns_string;
+  CFStringRef cf_string;
+}
+@end
+#endif

diff  --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm 
b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index e068a583c18c5..92d70a94427c0 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -1,6 +1,7 @@
 // RUN: %clang_analyze_cc1 
-analyzer-checker=alpha.webkit.NoUnretainedMemberChecker -verify %s
 
 #include "objc-mock-types.h"
+#include "mock-system-header.h"
 
 namespace members {
 
@@ -58,3 +59,13 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, 
CFMutableArrayRef>) {}
 
   void forceTmplToInstantiate(RefPtr<SomeObj>) {}
 }
+
+@interface AnotherObject : NSObject {
+  NSString *ns_string;
+  // expected-warning@-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@-1{{Instance variable 'cf_string' in 'AnotherObject' is 
a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+@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}}
+@end


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to