-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[alpha.webkit.NoUnretainedMemberChecker] Recognize NS_REQUIRES_PROPERTY_DEFINITIONS #141293
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
@llvm/pr-subscribers-clang-static-analyzer-1 Author: Ryosuke Niwa (rniwa) ChangesAllow @property of a raw pointer when NS_REQUIRES_PROPERTY_DEFINITIONS is specified on the interface since such an interface does not automatically synthesize raw pointer ivars. Full diff: https://github.com/llvm/llvm-project/pull/141293.diff 6 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 4ddd11495f534..f547f86f4782f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -236,6 +236,7 @@ std::optional<bool> isUnchecked(const QualType T) {
void RetainTypeChecker::visitTranslationUnitDecl(
const TranslationUnitDecl *TUD) {
IsARCEnabled = TUD->getLangOpts().ObjCAutoRefCount;
+ DefaultSynthProperties = TUD->getLangOpts().ObjCDefaultSynthProperties;
}
void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index f9fcfe9878d54..3c9560cb8059b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -76,12 +76,14 @@ class RetainTypeChecker {
llvm::DenseSet<const RecordType *> CFPointees;
llvm::DenseSet<const Type *> RecordlessTypes;
bool IsARCEnabled{false};
+ bool DefaultSynthProperties{true};
public:
void visitTranslationUnitDecl(const TranslationUnitDecl *);
void visitTypedef(const TypedefDecl *);
bool isUnretained(const QualType, bool ignoreARC = false);
bool isARCEnabled() const { return IsARCEnabled; }
+ bool defaultSynthProperties() const { return DefaultSynthProperties; }
};
/// \returns true if \p Class is NS or CF objects AND not retained, false if
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index 4ea6158c4c410..acd23b6eae7ea 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -174,6 +174,11 @@ class RawPtrRefMemberChecker
if (!PropType)
return;
+ if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
+ if (!RTC || !RTC->defaultSynthProperties() || ID->isObjCRequiresPropertyDefs())
+ return;
+ }
+
auto IsUnsafePtr = isUnsafePtr(QT);
if (!IsUnsafePtr || !*IsUnsafePtr)
return;
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 93e7dfd77b9e9..9e4356a71f1b5 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -22,6 +22,7 @@ typedef struct CF_BRIDGED_TYPE(id) CGImage *CGImageRef;
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#define CF_CONSUMED __attribute__((cf_consumed))
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+#define NS_REQUIRES_PROPERTY_DEFINITIONS __attribute__((objc_requires_property_definitions))
extern const CFAllocatorRef kCFAllocatorDefault;
typedef struct _NSZone NSZone;
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
index 3491bc93ed98a..ca2679900bebe 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
@@ -64,3 +64,20 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, CFMutableArrayRef>) {}
};
} // namespace ptr_to_ptr_to_retained
+
+NS_REQUIRES_PROPERTY_DEFINITIONS
+@interface NoSynthObject : NSObject {
+ NSString *ns_string;
+ CFStringRef cf_string;
+ // expected-warning@-1{{Instance variable 'cf_string' in 'NoSynthObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+@property(nonatomic, readonly, strong) NSString *prop_string1;
+@property(nonatomic, readonly, strong) NSString *prop_string2;
+@end
+
+@implementation NoSynthObject
+- (NSString *)prop_string1 {
+ return nil;
+}
+@synthesize prop_string2;
+@end
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index 0cb4c4ac0f6a0..7b31296378034 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -99,3 +99,22 @@ @interface AnotherObject : NSObject {
@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
+
+NS_REQUIRES_PROPERTY_DEFINITIONS
+@interface NoSynthObject : NSObject {
+ NSString *ns_string;
+ // expected-warning@-1{{Instance variable 'ns_string' in 'NoSynthObject' 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 'NoSynthObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+@property(nonatomic, readonly, strong) NSString *prop_string1;
+@property(nonatomic, readonly, strong) NSString *prop_string2;
+@end
+
+@implementation NoSynthObject
+- (NSString *)prop_string1 {
+ return nil;
+}
+@synthesize prop_string2;
+// expected-warning@-1{{Instance variable 'prop_string2' in 'NoSynthObject' is a raw pointer to retainable type 'NSString'}}
+@end
|
@llvm/pr-subscribers-clang Author: Ryosuke Niwa (rniwa) ChangesAllow @property of a raw pointer when NS_REQUIRES_PROPERTY_DEFINITIONS is specified on the interface since such an interface does not automatically synthesize raw pointer ivars. Full diff: https://github.com/llvm/llvm-project/pull/141293.diff 6 Files Affected:
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
index 4ddd11495f534..f547f86f4782f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.cpp
@@ -236,6 +236,7 @@ std::optional<bool> isUnchecked(const QualType T) {
void RetainTypeChecker::visitTranslationUnitDecl(
const TranslationUnitDecl *TUD) {
IsARCEnabled = TUD->getLangOpts().ObjCAutoRefCount;
+ DefaultSynthProperties = TUD->getLangOpts().ObjCDefaultSynthProperties;
}
void RetainTypeChecker::visitTypedef(const TypedefDecl *TD) {
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
index f9fcfe9878d54..3c9560cb8059b 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/PtrTypesSemantics.h
@@ -76,12 +76,14 @@ class RetainTypeChecker {
llvm::DenseSet<const RecordType *> CFPointees;
llvm::DenseSet<const Type *> RecordlessTypes;
bool IsARCEnabled{false};
+ bool DefaultSynthProperties{true};
public:
void visitTranslationUnitDecl(const TranslationUnitDecl *);
void visitTypedef(const TypedefDecl *);
bool isUnretained(const QualType, bool ignoreARC = false);
bool isARCEnabled() const { return IsARCEnabled; }
+ bool defaultSynthProperties() const { return DefaultSynthProperties; }
};
/// \returns true if \p Class is NS or CF objects AND not retained, false if
diff --git a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
index 4ea6158c4c410..acd23b6eae7ea 100644
--- a/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
@@ -174,6 +174,11 @@ class RawPtrRefMemberChecker
if (!PropType)
return;
+ if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
+ if (!RTC || !RTC->defaultSynthProperties() || ID->isObjCRequiresPropertyDefs())
+ return;
+ }
+
auto IsUnsafePtr = isUnsafePtr(QT);
if (!IsUnsafePtr || !*IsUnsafePtr)
return;
diff --git a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
index 93e7dfd77b9e9..9e4356a71f1b5 100644
--- a/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
+++ b/clang/test/Analysis/Checkers/WebKit/objc-mock-types.h
@@ -22,6 +22,7 @@ typedef struct CF_BRIDGED_TYPE(id) CGImage *CGImageRef;
#define NS_RETURNS_RETAINED __attribute__((ns_returns_retained))
#define CF_CONSUMED __attribute__((cf_consumed))
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
+#define NS_REQUIRES_PROPERTY_DEFINITIONS __attribute__((objc_requires_property_definitions))
extern const CFAllocatorRef kCFAllocatorDefault;
typedef struct _NSZone NSZone;
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
index 3491bc93ed98a..ca2679900bebe 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm
@@ -64,3 +64,20 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, CFMutableArrayRef>) {}
};
} // namespace ptr_to_ptr_to_retained
+
+NS_REQUIRES_PROPERTY_DEFINITIONS
+@interface NoSynthObject : NSObject {
+ NSString *ns_string;
+ CFStringRef cf_string;
+ // expected-warning@-1{{Instance variable 'cf_string' in 'NoSynthObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+@property(nonatomic, readonly, strong) NSString *prop_string1;
+@property(nonatomic, readonly, strong) NSString *prop_string2;
+@end
+
+@implementation NoSynthObject
+- (NSString *)prop_string1 {
+ return nil;
+}
+@synthesize prop_string2;
+@end
diff --git a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
index 0cb4c4ac0f6a0..7b31296378034 100644
--- a/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
+++ b/clang/test/Analysis/Checkers/WebKit/unretained-members.mm
@@ -99,3 +99,22 @@ @interface AnotherObject : NSObject {
@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
+
+NS_REQUIRES_PROPERTY_DEFINITIONS
+@interface NoSynthObject : NSObject {
+ NSString *ns_string;
+ // expected-warning@-1{{Instance variable 'ns_string' in 'NoSynthObject' 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 'NoSynthObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
+}
+@property(nonatomic, readonly, strong) NSString *prop_string1;
+@property(nonatomic, readonly, strong) NSString *prop_string2;
+@end
+
+@implementation NoSynthObject
+- (NSString *)prop_string1 {
+ return nil;
+}
+@synthesize prop_string2;
+// expected-warning@-1{{Instance variable 'prop_string2' in 'NoSynthObject' is a raw pointer to retainable type 'NSString'}}
+@end
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
07f4f7d
to
bcee060
Compare
clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp
Outdated
Show resolved
Hide resolved
Overall, I think the change aligns with what you described. I've just left a few questions to clarify my understanding. |
Added test cases for synthesizing `assign` and `unsafe_unretained` properties.
@@ -142,6 +144,8 @@ class RawPtrRefMemberChecker | |||
if (auto *ID = dyn_cast<ObjCImplementationDecl>(CD)) { | |||
for (auto *Ivar : ID->ivars()) | |||
visitIvarDecl(CD, Ivar); | |||
for (auto *PropImpl : ID->property_impls()) | |||
visitPropImpl(CD, PropImpl); |
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.
visitPropImpl
populates IvarDeclsToIgnore
. Should it be called before visitIvarDecl
?
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, that must be why my warning is emitted in a seemingly wrong place for one of the test cases. Will fix.
There was a typo in the branch name so closing this in favor of a new PR: #143408 |
Allow @Property of a raw pointer when NS_REQUIRES_PROPERTY_DEFINITIONS is specified on the interface since such an interface does not automatically synthesize raw pointer ivars.