-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[alpha.webkit.RawPtrRefMemberChecker] The checker doesn't warn Objective-C types in ivars. #132833
[alpha.webkit.RawPtrRefMemberChecker] The checker doesn't warn Objective-C types in ivars. #132833
Conversation
…ive-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.
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Ryosuke Niwa (rniwa) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/132833.diff 3 Files Affected:
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__
+@class NSString;
+@interface SystemObject : NSObject {
+ 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..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
+
+@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}}
+}
+@end
|
@llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesThis 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. Full diff: https://github.com/llvm/llvm-project/pull/132833.diff 3 Files Affected:
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__
+@class NSString;
+@interface SystemObject : NSObject {
+ 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..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
+
+@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}}
+}
+@end
|
CFStringRef cf_string; | ||
// expected-warning@-1{{Instance variable 'cf_string' in 'AnotherObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}} | ||
} | ||
@end |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is more of a question for my understanding: Do we expect the same behavior for raw pointers that are properties?
@interface AnotherObject : NSObject
@property(nonatomic,strong) NSString *prop_string;
@end
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a test case for properties?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out I have to enumerate properties separately from ivars. Added a test with code fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks for the review! |
return; | ||
if (auto *PropCXXRD = PropType->getPointeeCXXRecordDecl()) { | ||
std::optional<bool> IsCompatible = isPtrCompatible(QT, PropCXXRD); | ||
fprintf(stderr, "IsCompatible=%d\n", IsCompatible ? *IsCompatible : -1); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh oops, I forgot to remove this.
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.