-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[WebKit checkers] Recognize NS_RETURNS_RETAINED and CF_RETURNS_RETAINED. #157629
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
[WebKit checkers] Recognize NS_RETURNS_RETAINED and CF_RETURNS_RETAINED. #157629
Conversation
This PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED.
@llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesThis PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED. Full diff: https://github.com/llvm/llvm-project/pull/157629.diff 3 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 478bd85177143..f43e5ac9af198 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -91,6 +91,13 @@ bool tryToFindPtrOrigin(
continue;
}
if (auto *call = dyn_cast<CallExpr>(E)) {
+ if (auto *Callee = call->getCalleeDecl()) {
+ if (Callee->hasAttr<CFReturnsRetainedAttr>() ||
+ Callee->hasAttr<NSReturnsRetainedAttr>()) {
+ return callback(E, true);
+ }
+ }
+
if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) {
if (auto *decl = memberCall->getMethodDecl()) {
std::optional<bool> IsGetterOfRefCt = isGetterOfSafePtr(decl);
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index c69113c48806d..c44f209d80a4e 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -438,6 +438,20 @@ void use_const_local() {
} // namespace const_global
+namespace ns_retained_return_value {
+
+NSString *provideNS() NS_RETURNS_RETAINED;
+CFDictionaryRef provideCF() CF_RETURNS_RETAINED;
+void consumeNS(NSString *);
+void consumeCF(CFDictionaryRef);
+
+void foo() {
+ consumeNS(provideNS());
+ consumeCF(provideCF());
+}
+
+} // namespace ns_retained_return_value
+
@interface TestObject : NSObject
- (void)doWork:(NSString *)msg, ...;
- (void)doWorkOnSelf;
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
index 10f7c9acb7a3c..0ad8f707e254c 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
@@ -408,6 +408,21 @@ void use_const_local() {
} // namespace const_global
+namespace ns_retained_return_value {
+
+NSString *provideNS() NS_RETURNS_RETAINED;
+CFDictionaryRef provideCF() CF_RETURNS_RETAINED;
+void consumeNS(NSString *);
+void consumeCF(CFDictionaryRef);
+
+unsigned foo() {
+ auto *string = provideNS();
+ auto *dictionary = provideCF();
+ return string.length + CFDictionaryGetCount(dictionary);
+}
+
+} // namespace ns_retained_return_value
+
bool doMoreWorkOpaque(OtherObj*);
SomeObj* provide();
|
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Ryosuke Niwa (rniwa) ChangesThis PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED. Full diff: https://github.com/llvm/llvm-project/pull/157629.diff 3 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
index 478bd85177143..f43e5ac9af198 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/ASTUtils.cpp
@@ -91,6 +91,13 @@ bool tryToFindPtrOrigin(
continue;
}
if (auto *call = dyn_cast<CallExpr>(E)) {
+ if (auto *Callee = call->getCalleeDecl()) {
+ if (Callee->hasAttr<CFReturnsRetainedAttr>() ||
+ Callee->hasAttr<NSReturnsRetainedAttr>()) {
+ return callback(E, true);
+ }
+ }
+
if (auto *memberCall = dyn_cast<CXXMemberCallExpr>(call)) {
if (auto *decl = memberCall->getMethodDecl()) {
std::optional<bool> IsGetterOfRefCt = isGetterOfSafePtr(decl);
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
index c69113c48806d..c44f209d80a4e 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-call-args.mm
@@ -438,6 +438,20 @@ void use_const_local() {
} // namespace const_global
+namespace ns_retained_return_value {
+
+NSString *provideNS() NS_RETURNS_RETAINED;
+CFDictionaryRef provideCF() CF_RETURNS_RETAINED;
+void consumeNS(NSString *);
+void consumeCF(CFDictionaryRef);
+
+void foo() {
+ consumeNS(provideNS());
+ consumeCF(provideCF());
+}
+
+} // namespace ns_retained_return_value
+
@interface TestObject : NSObject
- (void)doWork:(NSString *)msg, ...;
- (void)doWorkOnSelf;
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
index 10f7c9acb7a3c..0ad8f707e254c 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-local-vars.mm
@@ -408,6 +408,21 @@ void use_const_local() {
} // namespace const_global
+namespace ns_retained_return_value {
+
+NSString *provideNS() NS_RETURNS_RETAINED;
+CFDictionaryRef provideCF() CF_RETURNS_RETAINED;
+void consumeNS(NSString *);
+void consumeCF(CFDictionaryRef);
+
+unsigned foo() {
+ auto *string = provideNS();
+ auto *dictionary = provideCF();
+ return string.length + CFDictionaryGetCount(dictionary);
+}
+
+} // namespace ns_retained_return_value
+
bool doMoreWorkOpaque(OtherObj*);
SomeObj* provide();
|
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 left a small nit in the test case. Otherwise, LGTM!
} | ||
|
||
} // namespace ns_retained_return_value | ||
|
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'm fairly certain this works, but can we have a test case with inheritance (sub class calls provideNS
defined in super class) for the sake of completion?
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.
You mean provideNS
returns a subclass of a class consumeNS
takes?
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.
Or are you talking about adding a test case where provideNS
is defined in a C++ class then a subclass of it calls consumeNS(provideNS())
in some member function?
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.
Or are you talking about adding a test case where
provideNS
is defined in a C++ class then a subclass of it callsconsumeNS(provideNS())
in some member function?
I was thinking of this case.
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.
ok, added.
Define a function which returns a retained value in a base class and call that in a derived class
Thanks for the review! |
…ED. (llvm#157629) This PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED.
…ED. (llvm#157629) This PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED.
This PR adds the support for treating a function return value to be safe if the function is annotated with NS_RETURNS_RETAINED or CF_RETURNS_RETAINED.