-
Notifications
You must be signed in to change notification settings - Fork 13.4k
[alpha.webkit.RetainPtrCtorAdoptChecker] Recognize mutableCopy from literal as +1 #132350
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
Conversation
…iteral as +1 This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Ryosuke Niwa (rniwa) ChangesThis PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression. Full diff: https://github.com/llvm/llvm-project/pull/132350.diff 4 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index 4ce3262e90e13..1f9a4712cedf6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -202,6 +202,12 @@ class RetainPtrCtorAdoptChecker
bool isAllocInit(const Expr *E) const {
auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E);
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (unsigned ExprCount = POE->getNumSemanticExprs()) {
+ auto *Expr = POE->getSemanticExpr(ExprCount - 1)->IgnoreParenCasts();
+ ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(Expr);
+ }
+ }
if (!ObjCMsgExpr)
return false;
auto Selector = ObjCMsgExpr->getSelector();
@@ -247,6 +253,12 @@ class RetainPtrCtorAdoptChecker
enum class IsOwnedResult { Unknown, Skip, Owned, NotOwned };
IsOwnedResult isOwned(const Expr *E) const {
while (1) {
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (unsigned SemanticExprCount = POE->getNumSemanticExprs()) {
+ E = POE->getSemanticExpr(SemanticExprCount - 1);
+ continue;
+ }
+ }
if (isa<CXXNullPtrLiteralExpr>(E))
return IsOwnedResult::NotOwned;
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 5bd265596a0b4..fc798cfc587b4 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -1,6 +1,8 @@
@class NSString;
@class NSArray;
@class NSMutableArray;
+@class NSDictionary;
+@class NSMutableDictionary;
#define nil ((id)0)
#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T)))
#define CF_BRIDGED_MUTABLE_TYPE(T) __attribute__((objc_bridge_mutable(T)))
@@ -90,12 +92,14 @@ __attribute__((objc_root_class))
- (NSEnumerator *)keyEnumerator;
+ (id)dictionary;
+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
+- (NSMutableDictionary *)mutableCopy;
+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
@end
@interface NSArray : NSObject <NSCopying, NSFastEnumeration>
- (NSUInteger)count;
- (NSEnumerator *)objectEnumerator;
+- (NSMutableArray *)mutableCopy;
+ (NSArray *)arrayWithObjects:(const id [])objects count:(NSUInteger)count;
@end
diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
index dd7208a534ea1..e4bbd5e2fc77b 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
@@ -97,3 +97,9 @@ void create_member_init() {
RetainPtr<id> return_bridge_cast() {
return bridge_cast<CFArrayRef, NSArray>(create_cf_array());
}
+
+void mutable_copy() {
+ RetainPtr<NSMutableDictionary> mutableArray = adoptNS(@{
+ @"Content-Type": @"text/html",
+ }.mutableCopy);
+}
diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
index 79e0bdb7c577b..8f6783288a093 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
@@ -97,3 +97,9 @@ void create_member_init() {
RetainPtr<id> return_bridge_cast() {
return bridge_cast<CFArrayRef, NSArray>(create_cf_array());
}
+
+void mutable_copy() {
+ RetainPtr<NSMutableDictionary> mutableArray = adoptNS(@{
+ @"Content-Type": @"text/html",
+ }.mutableCopy);
+}
|
@llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesThis PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression. Full diff: https://github.com/llvm/llvm-project/pull/132350.diff 4 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
index 4ce3262e90e13..1f9a4712cedf6 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RetainPtrCtorAdoptChecker.cpp
@@ -202,6 +202,12 @@ class RetainPtrCtorAdoptChecker
bool isAllocInit(const Expr *E) const {
auto *ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(E);
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (unsigned ExprCount = POE->getNumSemanticExprs()) {
+ auto *Expr = POE->getSemanticExpr(ExprCount - 1)->IgnoreParenCasts();
+ ObjCMsgExpr = dyn_cast<ObjCMessageExpr>(Expr);
+ }
+ }
if (!ObjCMsgExpr)
return false;
auto Selector = ObjCMsgExpr->getSelector();
@@ -247,6 +253,12 @@ class RetainPtrCtorAdoptChecker
enum class IsOwnedResult { Unknown, Skip, Owned, NotOwned };
IsOwnedResult isOwned(const Expr *E) const {
while (1) {
+ if (auto *POE = dyn_cast<PseudoObjectExpr>(E)) {
+ if (unsigned SemanticExprCount = POE->getNumSemanticExprs()) {
+ E = POE->getSemanticExpr(SemanticExprCount - 1);
+ continue;
+ }
+ }
if (isa<CXXNullPtrLiteralExpr>(E))
return IsOwnedResult::NotOwned;
if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 5bd265596a0b4..fc798cfc587b4 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -1,6 +1,8 @@
@class NSString;
@class NSArray;
@class NSMutableArray;
+@class NSDictionary;
+@class NSMutableDictionary;
#define nil ((id)0)
#define CF_BRIDGED_TYPE(T) __attribute__((objc_bridge(T)))
#define CF_BRIDGED_MUTABLE_TYPE(T) __attribute__((objc_bridge_mutable(T)))
@@ -90,12 +92,14 @@ __attribute__((objc_root_class))
- (NSEnumerator *)keyEnumerator;
+ (id)dictionary;
+ (id)dictionaryWithObject:(id)object forKey:(id <NSCopying>)key;
+- (NSMutableDictionary *)mutableCopy;
+ (instancetype)dictionaryWithObjects:(const id [])objects forKeys:(const id <NSCopying> [])keys count:(NSUInteger)cnt;
@end
@interface NSArray : NSObject <NSCopying, NSFastEnumeration>
- (NSUInteger)count;
- (NSEnumerator *)objectEnumerator;
+- (NSMutableArray *)mutableCopy;
+ (NSArray *)arrayWithObjects:(const id [])objects count:(NSUInteger)count;
@end
diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
index dd7208a534ea1..e4bbd5e2fc77b 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use-arc.mm
@@ -97,3 +97,9 @@ void create_member_init() {
RetainPtr<id> return_bridge_cast() {
return bridge_cast<CFArrayRef, NSArray>(create_cf_array());
}
+
+void mutable_copy() {
+ RetainPtr<NSMutableDictionary> mutableArray = adoptNS(@{
+ @"Content-Type": @"text/html",
+ }.mutableCopy);
+}
diff --git a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
index 79e0bdb7c577b..8f6783288a093 100644
--- a/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
+++ b/clang/test/Analysis/Checkers/WebKit/retain-ptr-ctor-adopt-use.mm
@@ -97,3 +97,9 @@ void create_member_init() {
RetainPtr<id> return_bridge_cast() {
return bridge_cast<CFArrayRef, NSArray>(create_cf_array());
}
+
+void mutable_copy() {
+ RetainPtr<NSMutableDictionary> mutableArray = adoptNS(@{
+ @"Content-Type": @"text/html",
+ }.mutableCopy);
+}
|
RetainPtr<NSMutableDictionary> mutableArray = adoptNS(@{ | ||
@"Content-Type": @"text/html", | ||
}.mutableCopy); | ||
} |
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 a question for my understanding: Is the behavior expected to be same/different for CFArrayCreateMutable
?
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.
Right but I didn't add a test for it separately since CFArrayCreateMutable
contains Create
in its name and it's a regular function call so the regular Create
function rule applies there.
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.
Got it, thank you for explaining.
|
||
void string_copy(NSString *str) { | ||
RetainPtr<NSString> copy = adoptNS(str.copy); | ||
} |
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 also add a test for RetainPtr<NSMutableDictionary>
?
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.
There is a test case for RetainPtr<NSMutableDictionary>
right above it. Or are you saying that we should add a test case which takes NSMutableDictionary* as a function argument?
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.
Sorry, I meant RetainPtr<NSArray>
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.
ah, sure, I can add one.
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! |
…iteral as +1 (llvm#132350) This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.
…iteral as +1 (llvm#132350) This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.
…iteral as +1 (llvm#132350) This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.
…iteral as +1 (llvm#132350) This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.
This PR adds the support for recognizing the return value of copy / mutableCopy as +1. isAllocInit and isOwned now traverses PseudoObjectExpr to its last semantic expression.