Skip to content

Commit 0d7c086

Browse files
committed
Emit a warning for @Property(assign) and @Property(unsafe_unretained) under ARC.
1 parent bd7daa3 commit 0d7c086

File tree

2 files changed

+22
-7
lines changed

2 files changed

+22
-7
lines changed

clang/lib/StaticAnalyzer/Checkers/WebKit/RawPtrRefMemberChecker.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class RawPtrRefMemberChecker
3838
RawPtrRefMemberChecker(const char *description)
3939
: Bug(this, description, "WebKit coding guidelines") {}
4040

41-
virtual std::optional<bool> isUnsafePtr(QualType) const = 0;
41+
virtual std::optional<bool> isUnsafePtr(QualType, bool ignoreARC = false) const = 0;
4242
virtual const char *typeName() const = 0;
4343
virtual const char *invariant() const = 0;
4444

@@ -175,11 +175,13 @@ class RawPtrRefMemberChecker
175175
return;
176176

177177
if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(CD)) {
178-
if (!RTC || !RTC->defaultSynthProperties() || ID->isObjCRequiresPropertyDefs())
178+
if (!RTC || !RTC->defaultSynthProperties() ||
179+
ID->isObjCRequiresPropertyDefs())
179180
return;
180181
}
181182

182-
auto IsUnsafePtr = isUnsafePtr(QT);
183+
bool ignoreARC = !PD->isReadOnly() && PD->getSetterKind() == ObjCPropertyDecl::Assign;
184+
auto IsUnsafePtr = isUnsafePtr(QT, ignoreARC);
183185
if (!IsUnsafePtr || !*IsUnsafePtr)
184186
return;
185187

@@ -279,7 +281,7 @@ class NoUncountedMemberChecker final : public RawPtrRefMemberChecker {
279281
: RawPtrRefMemberChecker("Member variable is a raw-pointer/reference to "
280282
"reference-countable type") {}
281283

282-
std::optional<bool> isUnsafePtr(QualType QT) const final {
284+
std::optional<bool> isUnsafePtr(QualType QT, bool) const final {
283285
return isUncountedPtr(QT.getCanonicalType());
284286
}
285287

@@ -296,7 +298,7 @@ class NoUncheckedPtrMemberChecker final : public RawPtrRefMemberChecker {
296298
: RawPtrRefMemberChecker("Member variable is a raw-pointer/reference to "
297299
"checked-pointer capable type") {}
298300

299-
std::optional<bool> isUnsafePtr(QualType QT) const final {
301+
std::optional<bool> isUnsafePtr(QualType QT, bool) const final {
300302
return isUncheckedPtr(QT.getCanonicalType());
301303
}
302304

@@ -316,8 +318,8 @@ class NoUnretainedMemberChecker final : public RawPtrRefMemberChecker {
316318
RTC = RetainTypeChecker();
317319
}
318320

319-
std::optional<bool> isUnsafePtr(QualType QT) const final {
320-
return RTC->isUnretained(QT);
321+
std::optional<bool> isUnsafePtr(QualType QT, bool ignoreARC) const final {
322+
return RTC->isUnretained(QT, ignoreARC);
321323
}
322324

323325
const char *typeName() const final { return "retainable type"; }

clang/test/Analysis/Checkers/WebKit/unretained-members-arc.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,19 @@ void forceTmplToInstantiate(FooTmpl<SomeObj, CFMutableArrayRef>) {}
6565

6666
} // namespace ptr_to_ptr_to_retained
6767

68+
@interface AnotherObject : NSObject {
69+
NSString *ns_string;
70+
CFStringRef cf_string;
71+
// expected-warning@-1{{Instance variable 'cf_string' in 'AnotherObject' is a retainable type 'CFStringRef'; member variables must be a RetainPtr}}
72+
}
73+
@property(nonatomic, strong) NSString *prop_string1;
74+
@property(nonatomic, assign) NSString *prop_string2;
75+
// expected-warning@-1{{Property 'prop_string2' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}}
76+
@property(nonatomic, unsafe_unretained) NSString *prop_string3;
77+
// expected-warning@-1{{Property 'prop_string3' in 'AnotherObject' is a raw pointer to retainable type 'NSString'; member variables must be a RetainPtr}}
78+
@property(nonatomic, readonly) NSString *prop_string4;
79+
@end
80+
6881
NS_REQUIRES_PROPERTY_DEFINITIONS
6982
@interface NoSynthObject : NSObject {
7083
NSString *ns_string;

0 commit comments

Comments
 (0)